mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-11-03 18:13:27 -05:00 
			
		
		
		
	Move to a consistent way of handling IDs in URLs
This commit is contained in:
		@@ -5,7 +5,6 @@ import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -100,14 +99,6 @@ type AccountList struct {
 | 
			
		||||
	Accounts *[]Account `json:"accounts"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var accountTransactionsRE *regexp.Regexp
 | 
			
		||||
var accountImportRE *regexp.Regexp
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	accountTransactionsRE = regexp.MustCompile(`^/v1/accounts/[0-9]+/transactions/?$`)
 | 
			
		||||
	accountImportRE = regexp.MustCompile(`^/v1/accounts/[0-9]+/imports/[a-z]+/?$`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *Account) Write(w http.ResponseWriter) error {
 | 
			
		||||
	enc := json.NewEncoder(w)
 | 
			
		||||
	return enc.Encode(a)
 | 
			
		||||
@@ -384,18 +375,12 @@ func AccountHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r.Method == "POST" {
 | 
			
		||||
		// if URL looks like /v1/accounts/[0-9]+/imports, use the account
 | 
			
		||||
		// import handler
 | 
			
		||||
		if accountImportRE.MatchString(r.URL.Path) {
 | 
			
		||||
			var accountid int64
 | 
			
		||||
			var importtype string
 | 
			
		||||
			n, err := GetURLPieces(r.URL.Path, "/v1/accounts/%d/imports/%s", &accountid, &importtype)
 | 
			
		||||
 | 
			
		||||
			if err != nil || n != 2 {
 | 
			
		||||
				log.Print(err)
 | 
			
		||||
				return NewError(999 /*Internal Error*/)
 | 
			
		||||
		if !context.LastLevel() {
 | 
			
		||||
			accountid, err := context.NextID()
 | 
			
		||||
			if err != nil || context.NextLevel() != "imports" {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
			}
 | 
			
		||||
			return AccountImportHandler(context, r, user, accountid, importtype)
 | 
			
		||||
			return AccountImportHandler(context, r, user, accountid)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		account_json := r.PostFormValue("account")
 | 
			
		||||
@@ -433,10 +418,7 @@ func AccountHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
 | 
			
		||||
		return ResponseWrapper{201, &account}
 | 
			
		||||
	} else if r.Method == "GET" {
 | 
			
		||||
		var accountid int64
 | 
			
		||||
		n, err := GetURLPieces(r.URL.Path, "/v1/accounts/%d", &accountid)
 | 
			
		||||
 | 
			
		||||
		if err != nil || n != 1 {
 | 
			
		||||
		if context.LastLevel() {
 | 
			
		||||
			//Return all Accounts
 | 
			
		||||
			var al AccountList
 | 
			
		||||
			accounts, err := GetAccounts(context.Tx, user.UserId)
 | 
			
		||||
@@ -446,13 +428,14 @@ func AccountHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			}
 | 
			
		||||
			al.Accounts = accounts
 | 
			
		||||
			return &al
 | 
			
		||||
		} else {
 | 
			
		||||
			// if URL looks like /account/[0-9]+/transactions, use the account
 | 
			
		||||
			// transaction handler
 | 
			
		||||
			if accountTransactionsRE.MatchString(r.URL.Path) {
 | 
			
		||||
				return AccountTransactionsHandler(context, r, user, accountid)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		accountid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if context.LastLevel() {
 | 
			
		||||
			// Return Account with this Id
 | 
			
		||||
			account, err := GetAccount(context.Tx, accountid, user.UserId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
@@ -460,9 +443,11 @@ func AccountHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return account
 | 
			
		||||
		} else if context.NextLevel() == "transactions" {
 | 
			
		||||
			return AccountTransactionsHandler(context, r, user, accountid)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		accountid, err := GetURLID(r.URL.Path)
 | 
			
		||||
		accountid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -35,6 +36,14 @@ func (c *Context) NextLevel() string {
 | 
			
		||||
	return split[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Context) NextID() (int64, error) {
 | 
			
		||||
	return strconv.ParseInt(c.NextLevel(), 0, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Context) LastLevel() bool {
 | 
			
		||||
	return len(c.remainingURL) == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Handler func(*http.Request, *Context) ResponseWriterWriter
 | 
			
		||||
 | 
			
		||||
type APIHandler struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -335,9 +335,10 @@ func OFXFileImportHandler(context *Context, r *http.Request, user *User, account
 | 
			
		||||
/*
 | 
			
		||||
 * Assumes the User is a valid, signed-in user, but accountid has not yet been validated
 | 
			
		||||
 */
 | 
			
		||||
func AccountImportHandler(context *Context, r *http.Request, user *User, accountid int64, importtype string) ResponseWriterWriter {
 | 
			
		||||
func AccountImportHandler(context *Context, r *http.Request, user *User, accountid int64) ResponseWriterWriter {
 | 
			
		||||
 | 
			
		||||
	switch importtype {
 | 
			
		||||
	importType := context.NextLevel()
 | 
			
		||||
	switch importType {
 | 
			
		||||
	case "ofx":
 | 
			
		||||
		return OFXImportHandler(context, r, user, accountid)
 | 
			
		||||
	case "ofxfile":
 | 
			
		||||
 
 | 
			
		||||
@@ -165,10 +165,7 @@ func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
 | 
			
		||||
		return ResponseWrapper{201, &price}
 | 
			
		||||
	} else if r.Method == "GET" {
 | 
			
		||||
		var priceid int64
 | 
			
		||||
		n, err := GetURLPieces(r.URL.Path, "/v1/prices/%d", &priceid)
 | 
			
		||||
 | 
			
		||||
		if err != nil || n != 1 {
 | 
			
		||||
		if context.LastLevel() {
 | 
			
		||||
			//Return all prices
 | 
			
		||||
			var pl PriceList
 | 
			
		||||
 | 
			
		||||
@@ -180,16 +177,21 @@ func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
 | 
			
		||||
			pl.Prices = prices
 | 
			
		||||
			return &pl
 | 
			
		||||
		} else {
 | 
			
		||||
			price, err := GetPrice(context.Tx, priceid, user.UserId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return price
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		priceid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		price, err := GetPrice(context.Tx, priceid, user.UserId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return price
 | 
			
		||||
	} else {
 | 
			
		||||
		priceid, err := GetURLID(r.URL.Path)
 | 
			
		||||
		priceid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,17 +8,10 @@ import (
 | 
			
		||||
	"github.com/yuin/gopher-lua"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var reportTabulationRE *regexp.Regexp
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	reportTabulationRE = regexp.MustCompile(`^/v1/reports/[0-9]+/tabulations/?$`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//type and value to store user in lua's Context
 | 
			
		||||
type key int
 | 
			
		||||
 | 
			
		||||
@@ -255,19 +248,7 @@ func ReportHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
 | 
			
		||||
		return ResponseWrapper{201, &report}
 | 
			
		||||
	} else if r.Method == "GET" {
 | 
			
		||||
		if reportTabulationRE.MatchString(r.URL.Path) {
 | 
			
		||||
			var reportid int64
 | 
			
		||||
			n, err := GetURLPieces(r.URL.Path, "/v1/reports/%d/tabulations", &reportid)
 | 
			
		||||
			if err != nil || n != 1 {
 | 
			
		||||
				log.Print(err)
 | 
			
		||||
				return NewError(999 /*InternalError*/)
 | 
			
		||||
			}
 | 
			
		||||
			return ReportTabulationHandler(context.Tx, r, user, reportid)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var reportid int64
 | 
			
		||||
		n, err := GetURLPieces(r.URL.Path, "/v1/reports/%d", &reportid)
 | 
			
		||||
		if err != nil || n != 1 {
 | 
			
		||||
		if context.LastLevel() {
 | 
			
		||||
			//Return all Reports
 | 
			
		||||
			var rl ReportList
 | 
			
		||||
			reports, err := GetReports(context.Tx, user.UserId)
 | 
			
		||||
@@ -277,6 +258,15 @@ func ReportHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			}
 | 
			
		||||
			rl.Reports = reports
 | 
			
		||||
			return &rl
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		reportid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if context.NextLevel() == "tabulations" {
 | 
			
		||||
			return ReportTabulationHandler(context.Tx, r, user, reportid)
 | 
			
		||||
		} else {
 | 
			
		||||
			// Return Report with this Id
 | 
			
		||||
			report, err := GetReport(context.Tx, reportid, user.UserId)
 | 
			
		||||
@@ -287,7 +277,7 @@ func ReportHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			return report
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		reportid, err := GetURLID(r.URL.Path)
 | 
			
		||||
		reportid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -274,10 +274,7 @@ func SecurityHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
 | 
			
		||||
		return ResponseWrapper{201, &security}
 | 
			
		||||
	} else if r.Method == "GET" {
 | 
			
		||||
		var securityid int64
 | 
			
		||||
		n, err := GetURLPieces(r.URL.Path, "/v1/securities/%d", &securityid)
 | 
			
		||||
 | 
			
		||||
		if err != nil || n != 1 {
 | 
			
		||||
		if context.LastLevel() {
 | 
			
		||||
			//Return all securities
 | 
			
		||||
			var sl SecurityList
 | 
			
		||||
 | 
			
		||||
@@ -290,6 +287,10 @@ func SecurityHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			sl.Securities = securities
 | 
			
		||||
			return &sl
 | 
			
		||||
		} else {
 | 
			
		||||
			securityid, err := context.NextID()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
			}
 | 
			
		||||
			security, err := GetSecurity(context.Tx, securityid, user.UserId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
@@ -298,7 +299,7 @@ func SecurityHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			return security
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		securityid, err := GetURLID(r.URL.Path)
 | 
			
		||||
		securityid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -452,9 +452,7 @@ func TransactionHandler(r *http.Request, context *Context) ResponseWriterWriter
 | 
			
		||||
 | 
			
		||||
		return &transaction
 | 
			
		||||
	} else if r.Method == "GET" {
 | 
			
		||||
		transactionid, err := GetURLID(r.URL.Path)
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
		if context.LastLevel() {
 | 
			
		||||
			//Return all Transactions
 | 
			
		||||
			var al TransactionList
 | 
			
		||||
			transactions, err := GetTransactions(context.Tx, user.UserId)
 | 
			
		||||
@@ -466,6 +464,10 @@ func TransactionHandler(r *http.Request, context *Context) ResponseWriterWriter
 | 
			
		||||
			return &al
 | 
			
		||||
		} else {
 | 
			
		||||
			//Return Transaction with this Id
 | 
			
		||||
			transactionid, err := context.NextID()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
			}
 | 
			
		||||
			transaction, err := GetTransaction(context.Tx, transactionid, user.UserId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
@@ -473,7 +475,7 @@ func TransactionHandler(r *http.Request, context *Context) ResponseWriterWriter
 | 
			
		||||
			return transaction
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		transactionid, err := GetURLID(r.URL.Path)
 | 
			
		||||
		transactionid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
@@ -518,11 +520,6 @@ func TransactionHandler(r *http.Request, context *Context) ResponseWriterWriter
 | 
			
		||||
 | 
			
		||||
			return &transaction
 | 
			
		||||
		} else if r.Method == "DELETE" {
 | 
			
		||||
			transactionid, err := GetURLID(r.URL.Path)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			transaction, err := GetTransaction(context.Tx, transactionid, user.UserId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return NewError(3 /*Invalid Request*/)
 | 
			
		||||
 
 | 
			
		||||
@@ -207,7 +207,7 @@ func UserHandler(r *http.Request, context *Context) ResponseWriterWriter {
 | 
			
		||||
			return NewError(1 /*Not Signed In*/)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		userid, err := GetURLID(r.URL.Path)
 | 
			
		||||
		userid, err := context.NextID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return NewError(3 /*Invalid Request*/)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,21 +3,8 @@ package handlers
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GetURLID(url string) (int64, error) {
 | 
			
		||||
	pieces := strings.Split(strings.Trim(url, "/"), "/")
 | 
			
		||||
	return strconv.ParseInt(pieces[len(pieces)-1], 10, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetURLPieces(url string, format string, a ...interface{}) (int, error) {
 | 
			
		||||
	url = strings.Replace(url, "/", " ", -1)
 | 
			
		||||
	format = strings.Replace(format, "/", " ", -1)
 | 
			
		||||
	return fmt.Sscanf(url, format, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ResponseWrapper struct {
 | 
			
		||||
	Code   int
 | 
			
		||||
	Writer ResponseWriterWriter
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user