mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-10-30 17:33:26 -04:00 
			
		
		
		
	Initial commit
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | *.swp | ||||||
							
								
								
									
										21
									
								
								accounts.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								accounts.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | type AccountType int64 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	Bank       AccountType = 1 | ||||||
|  | 	Cash                   = 2 | ||||||
|  | 	Asset                  = 3 | ||||||
|  | 	Liability              = 4 | ||||||
|  | 	Investment             = 5 | ||||||
|  | 	Income                 = 6 | ||||||
|  | 	Expense                = 7 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Account struct { | ||||||
|  | 	AccountId  int64 | ||||||
|  | 	UserId     int64 | ||||||
|  | 	SecurityId int64 | ||||||
|  | 	Type       AccountType | ||||||
|  | 	Name       string | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								db.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								db.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"database/sql" | ||||||
|  | 	_ "github.com/mattn/go-sqlite3" | ||||||
|  | 	"gopkg.in/gorp.v1" | ||||||
|  | 	"log" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var DB *gorp.DbMap = initDB() | ||||||
|  |  | ||||||
|  | func initDB() *gorp.DbMap { | ||||||
|  | 	db, err := sql.Open("sqlite3", "file:moneygo.sqlite?cache=shared&mode=rwc") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}} | ||||||
|  | 	dbmap.AddTableWithName(User{}, "users").SetKeys(true, "UserId") | ||||||
|  | 	dbmap.AddTableWithName(Session{}, "sessions").SetKeys(true, "SessionId") | ||||||
|  | 	dbmap.AddTableWithName(Account{}, "accounts").SetKeys(true, "AccountId") | ||||||
|  | 	dbmap.AddTableWithName(Security{}, "security").SetKeys(true, "SecurityId") | ||||||
|  | 	dbmap.AddTableWithName(Transaction{}, "transactions").SetKeys(true, "TransactionId") | ||||||
|  | 	dbmap.AddTableWithName(Split{}, "splits").SetKeys(true, "SplitId") | ||||||
|  |  | ||||||
|  | 	err = dbmap.CreateTablesIfNotExists() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return dbmap | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								errors.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"log" | ||||||
|  | 	"net/http" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Error struct { | ||||||
|  | 	ErrorId     int | ||||||
|  | 	ErrorString string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var error_codes = map[int]string{ | ||||||
|  | 	1: "Not Signed In", | ||||||
|  | 	2: "Unauthorized Access", | ||||||
|  | 	3: "Invalid Request", | ||||||
|  | 	4: "User Exists", | ||||||
|  | 	//  5:   "Connection Failed", //client-side error | ||||||
|  | 	999: "Internal Error", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func WriteError(w http.ResponseWriter, error_code int) { | ||||||
|  | 	msg, ok := error_codes[error_code] | ||||||
|  | 	if !ok { | ||||||
|  | 		log.Printf("Error: WriteError received error code of %d", error_code) | ||||||
|  | 		msg = error_codes[999] | ||||||
|  | 	} | ||||||
|  | 	e := Error{error_code, msg} | ||||||
|  |  | ||||||
|  | 	enc := json.NewEncoder(w) | ||||||
|  | 	err := enc.Encode(e) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"github.com/gorilla/context" | ||||||
|  | 	"log" | ||||||
|  | 	"net" | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/fcgi" | ||||||
|  | 	"os" | ||||||
|  | 	"path" | ||||||
|  | 	"strconv" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var serveFcgi bool | ||||||
|  | var baseDir string | ||||||
|  | var port int | ||||||
|  | var smtpServer string | ||||||
|  | var smtpPort int | ||||||
|  | var smtpUsername string | ||||||
|  | var smtpPassword string | ||||||
|  | var reminderEmail string | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	flag.StringVar(&baseDir, "base", "./", "Base directory for server") | ||||||
|  | 	flag.IntVar(&port, "port", 80, "Port to serve API/files on") | ||||||
|  | 	flag.StringVar(&smtpServer, "smtp.server", "smtp.example.com", "SMTP server to send reminder emails from.") | ||||||
|  | 	flag.IntVar(&smtpPort, "smtp.port", 587, "SMTP server port to connect to") | ||||||
|  | 	flag.StringVar(&smtpUsername, "smtp.username", "moneygo", "SMTP username") | ||||||
|  | 	flag.StringVar(&smtpPassword, "smtp.password", "password", "SMTP password") | ||||||
|  | 	flag.StringVar(&reminderEmail, "email", "moneygo@example.com", "Email address to send reminder emails as.") | ||||||
|  | 	flag.BoolVar(&serveFcgi, "fcgi", false, "Serve via fcgi rather than http.") | ||||||
|  | 	flag.Parse() | ||||||
|  |  | ||||||
|  | 	static_path := path.Join(baseDir, "static") | ||||||
|  |  | ||||||
|  | 	// Ensure base directory is valid | ||||||
|  | 	dir_err_str := "The base directory doesn't look like it contains the " + | ||||||
|  | 		"'static' directory. Check to make sure you're passing the right " + | ||||||
|  | 		"value to the -base argument." | ||||||
|  | 	static_dir, err := os.Stat(static_path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Print(err) | ||||||
|  | 		log.Fatal(dir_err_str) | ||||||
|  | 	} | ||||||
|  | 	if !static_dir.IsDir() { | ||||||
|  | 		log.Fatal(dir_err_str) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func rootHandler(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	http.ServeFile(w, r, path.Join(baseDir, "static/index.html")) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func staticHandler(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	http.ServeFile(w, r, path.Join(baseDir, r.URL.Path)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	servemux := http.NewServeMux() | ||||||
|  | 	servemux.HandleFunc("/", rootHandler) | ||||||
|  | 	servemux.HandleFunc("/static/", staticHandler) | ||||||
|  | 	servemux.HandleFunc("/session/", SessionHandler) | ||||||
|  | 	servemux.HandleFunc("/user/", UserHandler) | ||||||
|  |  | ||||||
|  | 	listener, err := net.Listen("tcp", ":"+strconv.Itoa(port)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log.Printf("Serving on port %d out of directory: %s", port, baseDir) | ||||||
|  | 	if serveFcgi { | ||||||
|  | 		fcgi.Serve(listener, context.ClearHandler(servemux)) | ||||||
|  | 	} else { | ||||||
|  | 		http.Serve(listener, context.ClearHandler(servemux)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								securities.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								securities.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | type SecurityType int64 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	Banknote   SecurityType = 1 | ||||||
|  | 	Bond                    = 2 | ||||||
|  | 	Stock                   = 3 | ||||||
|  | 	MutualFund              = 4 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Security struct { | ||||||
|  | 	SecurityId int64 | ||||||
|  | 	Name       string | ||||||
|  | 	// Number of decimal digits (to the right of the decimal point) this | ||||||
|  | 	// security is precise to | ||||||
|  | 	Precision int64 | ||||||
|  | 	Type      SecurityType | ||||||
|  | } | ||||||
							
								
								
									
										118
									
								
								sessions.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								sessions.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/gorilla/securecookie" | ||||||
|  | 	"github.com/gorilla/sessions" | ||||||
|  | 	"net/http" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var cookie_store = sessions.NewCookieStore(securecookie.GenerateRandomKey(64)) | ||||||
|  |  | ||||||
|  | type Session struct { | ||||||
|  | 	SessionId     int64 | ||||||
|  | 	SessionSecret string `json:"-"` | ||||||
|  | 	UserId        int64 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *Session) Write(w http.ResponseWriter) error { | ||||||
|  | 	enc := json.NewEncoder(w) | ||||||
|  | 	return enc.Encode(s) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetSession(r *http.Request) (*Session, error) { | ||||||
|  | 	var s Session | ||||||
|  |  | ||||||
|  | 	session, _ := cookie_store.Get(r, "moneygo") | ||||||
|  | 	_, ok := session.Values["session-secret"] | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil, fmt.Errorf("session-secret cookie not set") | ||||||
|  | 	} | ||||||
|  | 	s.SessionSecret = session.Values["session-secret"].(string) | ||||||
|  |  | ||||||
|  | 	err := DB.SelectOne(&s, "SELECT * from sessions where SessionSecret=?", s.SessionSecret) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return &s, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func DeleteSessionIfExists(r *http.Request) { | ||||||
|  | 	session, err := GetSession(r) | ||||||
|  | 	if err == nil { | ||||||
|  | 		DB.Delete(session) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewSession(w http.ResponseWriter, r *http.Request, userid int64) (*Session, error) { | ||||||
|  | 	s := Session{} | ||||||
|  |  | ||||||
|  | 	session, _ := cookie_store.Get(r, "moneygo") | ||||||
|  |  | ||||||
|  | 	session.Values["session-secret"] = string(securecookie.GenerateRandomKey(64)) | ||||||
|  | 	s.SessionSecret = session.Values["session-secret"].(string) | ||||||
|  | 	s.UserId = userid | ||||||
|  |  | ||||||
|  | 	err := DB.Insert(&s) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = session.Save(r, w) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} else { | ||||||
|  | 		return &s, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func SessionHandler(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	if r.Method == "POST" || r.Method == "PUT" { | ||||||
|  | 		user_json := r.PostFormValue("user") | ||||||
|  | 		if user_json == "" { | ||||||
|  | 			WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		user := User{} | ||||||
|  | 		err := user.Read(user_json) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		dbuser, err := GetUserByUsername(user.Username) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 2 /*Unauthorized Access*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		user.HashPassword() | ||||||
|  | 		if user.PasswordHash != dbuser.PasswordHash { | ||||||
|  | 			WriteError(w, 2 /*Unauthorized Access*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		DeleteSessionIfExists(r) | ||||||
|  |  | ||||||
|  | 		_, err = NewSession(w, r, dbuser.UserId) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 999 /*Internal Error*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		WriteSuccess(w) | ||||||
|  | 	} else if r.Method == "GET" { | ||||||
|  | 		s, err := GetSession(r) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 1 /*Not Signed In*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		s.Write(w) | ||||||
|  | 	} else if r.Method == "DELETE" { | ||||||
|  | 		DeleteSessionIfExists(r) | ||||||
|  | 		WriteSuccess(w) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								transactions.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								transactions.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"math/big" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Split struct { | ||||||
|  | 	SplitId       int64 | ||||||
|  | 	TransactionId int64 | ||||||
|  | 	AccountId     int64 | ||||||
|  | 	Number        int64 // Check or reference number | ||||||
|  | 	Memo          string | ||||||
|  | 	Amount        big.Rat | ||||||
|  | 	Debit         bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type TransactionStatus int64 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	Entered    TransactionStatus = 1 | ||||||
|  | 	Cleared                      = 2 | ||||||
|  | 	Reconciled                   = 3 | ||||||
|  | 	Voided                       = 4 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Transaction struct { | ||||||
|  | 	TransactionId int64 | ||||||
|  | 	UserId        int64 | ||||||
|  | 	Description   string | ||||||
|  | 	Status        TransactionStatus | ||||||
|  | 	Date          time.Time | ||||||
|  | } | ||||||
							
								
								
									
										203
									
								
								users.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								users.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/sha256" | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"log" | ||||||
|  | 	"net/http" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type User struct { | ||||||
|  | 	UserId       int64 | ||||||
|  | 	Name         string | ||||||
|  | 	Username     string | ||||||
|  | 	Password     string `db:"-"` | ||||||
|  | 	PasswordHash string `json:"-"` | ||||||
|  | 	Email        string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const BogusPassword = "password" | ||||||
|  |  | ||||||
|  | type UserExistsError struct{} | ||||||
|  |  | ||||||
|  | func (ueu UserExistsError) Error() string { | ||||||
|  | 	return "User exists" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *User) Write(w http.ResponseWriter) error { | ||||||
|  | 	enc := json.NewEncoder(w) | ||||||
|  | 	return enc.Encode(u) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *User) Read(json_str string) error { | ||||||
|  | 	dec := json.NewDecoder(strings.NewReader(json_str)) | ||||||
|  | 	return dec.Decode(u) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *User) HashPassword() { | ||||||
|  | 	password_hasher := sha256.New() | ||||||
|  | 	io.WriteString(password_hasher, u.Password) | ||||||
|  | 	u.PasswordHash = fmt.Sprintf("%x", password_hasher.Sum(nil)) | ||||||
|  | 	u.Password = "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetUser(userid int64) (*User, error) { | ||||||
|  | 	var u User | ||||||
|  |  | ||||||
|  | 	err := DB.SelectOne(&u, "SELECT * from users where UserId=?", userid) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return &u, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetUserByUsername(username string) (*User, error) { | ||||||
|  | 	var u User | ||||||
|  |  | ||||||
|  | 	err := DB.SelectOne(&u, "SELECT * from users where Username=?", username) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return &u, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func InsertUser(u *User) error { | ||||||
|  | 	transaction, err := DB.Begin() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	existing, err := transaction.SelectInt("SELECT count(*) from users where Username=?", u.Username) | ||||||
|  | 	if err != nil { | ||||||
|  | 		transaction.Rollback() | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if existing > 0 { | ||||||
|  | 		transaction.Rollback() | ||||||
|  | 		return UserExistsError{} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = transaction.Insert(u) | ||||||
|  | 	if err != nil { | ||||||
|  | 		transaction.Rollback() | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = transaction.Commit() | ||||||
|  | 	if err != nil { | ||||||
|  | 		transaction.Rollback() | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetUserFromSession(r *http.Request) (*User, error) { | ||||||
|  | 	s, err := GetSession(r) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return GetUser(s.UserId) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func UserHandler(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	if r.Method == "POST" { | ||||||
|  | 		user_json := r.PostFormValue("user") | ||||||
|  | 		if user_json == "" { | ||||||
|  | 			WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var user User | ||||||
|  | 		err := user.Read(user_json) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		user.UserId = -1 | ||||||
|  | 		user.HashPassword() | ||||||
|  |  | ||||||
|  | 		err = InsertUser(&user) | ||||||
|  | 		if err != nil { | ||||||
|  | 			if _, ok := err.(UserExistsError); ok { | ||||||
|  | 				WriteError(w, 4 /*User Exists*/) | ||||||
|  | 			} else { | ||||||
|  | 				WriteError(w, 999 /*Internal Error*/) | ||||||
|  | 				log.Print(err) | ||||||
|  | 			} | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		WriteSuccess(w) | ||||||
|  | 	} else { | ||||||
|  | 		user, err := GetUserFromSession(r) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 1 /*Not Signed In*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		userid, err := GetURLID(r.URL.Path) | ||||||
|  | 		if err != nil { | ||||||
|  | 			WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if userid != user.UserId { | ||||||
|  | 			WriteError(w, 2 /*Unauthorized Access*/) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if r.Method == "GET" { | ||||||
|  | 			err = user.Write(w) | ||||||
|  | 			if err != nil { | ||||||
|  | 				WriteError(w, 999 /*Internal Error*/) | ||||||
|  | 				log.Print(err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} else if r.Method == "PUT" { | ||||||
|  | 			user_json := r.PostFormValue("user") | ||||||
|  | 			if user_json == "" { | ||||||
|  | 				WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Save old PWHash in case the new password is bogus | ||||||
|  | 			old_pwhash := user.PasswordHash | ||||||
|  |  | ||||||
|  | 			err = user.Read(user_json) | ||||||
|  | 			if err != nil || user.UserId != userid { | ||||||
|  | 				WriteError(w, 3 /*Invalid Request*/) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// If the user didn't create a new password, keep their old one | ||||||
|  | 			if user.Password != BogusPassword { | ||||||
|  | 				user.HashPassword() | ||||||
|  | 			} else { | ||||||
|  | 				user.Password = "" | ||||||
|  | 				user.PasswordHash = old_pwhash | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			count, err := DB.Update(user) | ||||||
|  | 			if count != 1 || err != nil { | ||||||
|  | 				WriteError(w, 999 /*Internal Error*/) | ||||||
|  | 				log.Print(err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			WriteSuccess(w) | ||||||
|  | 		} else if r.Method == "DELETE" { | ||||||
|  | 			count, err := DB.Delete(&user) | ||||||
|  | 			if count != 1 || err != nil { | ||||||
|  | 				WriteError(w, 999 /*Internal Error*/) | ||||||
|  | 				log.Print(err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			WriteSuccess(w) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								util.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | 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 WriteSuccess(w http.ResponseWriter) { | ||||||
|  | 	fmt.Fprint(w, "{}") | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user