package controller import ( "arimelody-web/model" "errors" "fmt" "net/http" "strings" "github.com/jmoiron/sqlx" ) func GetAllAccounts(db *sqlx.DB) ([]model.Account, error) { var accounts = []model.Account{} err := db.Select(&accounts, "SELECT * FROM account ORDER BY created_at ASC") if err != nil { return nil, err } return accounts, nil } func GetAccount(db *sqlx.DB, username string) (*model.Account, error) { var account = model.Account{} err := db.Get(&account, "SELECT * FROM account WHERE username=$1", username) if err != nil { if strings.Contains(err.Error(), "no rows") { return nil, nil } return nil, err } return &account, nil } func GetAccountByEmail(db *sqlx.DB, email string) (*model.Account, error) { var account = model.Account{} err := db.Get(&account, "SELECT * FROM account WHERE email=$1", email) if err != nil { if strings.Contains(err.Error(), "no rows") { return nil, nil } return nil, err } return &account, nil } func GetAccountByToken(db *sqlx.DB, token string) (*model.Account, error) { if token == "" { return nil, nil } account := model.Account{} err := db.Get(&account, "SELECT account.* FROM account JOIN token ON id=account WHERE token=$1", token) if err != nil { if strings.Contains(err.Error(), "no rows") { return nil, nil } return nil, err } return &account, nil } func GetTokenFromRequest(db *sqlx.DB, r *http.Request) string { tokenStr := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ") if len(tokenStr) > 0 { return tokenStr } cookie, err := r.Cookie(model.COOKIE_TOKEN) if err != nil { return "" } return cookie.Value } func GetAccountByRequest(db *sqlx.DB, r *http.Request) (*model.Account, error) { tokenStr := GetTokenFromRequest(db, r) token, err := GetToken(db, tokenStr) if err != nil { if strings.Contains(err.Error(), "no rows") { return nil, nil } return nil, errors.New("GetToken: " + err.Error()) } // does user-agent match the token? if r.UserAgent() != token.UserAgent { // invalidate the token DeleteToken(db, tokenStr) fmt.Printf("WARN: Attempted use of token by unauthorised User-Agent (Expected `%s`, got `%s`)\n", token.UserAgent, r.UserAgent()) // TODO: log unauthorised activity to the user return nil, errors.New("User agent mismatch") } return GetAccountByToken(db, tokenStr) } func CreateAccount(db *sqlx.DB, account *model.Account) error { err := db.Get( &account.ID, "INSERT INTO account (username, password, email, avatar_url) " + "VALUES ($1, $2, $3, $4) " + "RETURNING id", account.Username, account.Password, account.Email, account.AvatarURL, ) return err } func UpdateAccount(db *sqlx.DB, account *model.Account) error { _, err := db.Exec( "UPDATE account " + "SET username=$2, password=$3, email=$4, avatar_url=$5) " + "WHERE id=$1", account.ID, account.Username, account.Password, account.Email, account.AvatarURL, ) return err } func DeleteAccount(db *sqlx.DB, username string) error { _, err := db.Exec("DELETE FROM account WHERE username=$1", username) return err }