package controller import ( "arimelody-web/global" "arimelody-web/model" "errors" "fmt" "math/rand" "net/http" "strings" "github.com/jmoiron/sqlx" ) 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 { 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 { 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 err.Error() == "sql: no rows in result set" { return nil, nil } return nil, err } return &account, nil } func GetAccountByRequest(db *sqlx.DB, r *http.Request) (*model.Account, error) { tokenStr := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ") if tokenStr == "" { cookie, err := r.Cookie(global.COOKIE_TOKEN) if err != nil { // not logged in return nil, nil } tokenStr = cookie.Value } token, err := GetToken(db, tokenStr) if err != nil { if strings.HasPrefix(err.Error(), "sql: no rows") { return nil, nil } return nil, errors.New(fmt.Sprintf("GetToken: %s", 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.Exec( "INSERT INTO account (username, password, email, avatar_url) " + "VALUES ($1, $2, $3, $4)", 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, accountID string) error { _, err := db.Exec("DELETE FROM account WHERE id=$1", accountID) return err } var inviteChars = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") func GenerateInviteCode(length int) []byte { code := []byte{} for i := 0; i < length; i++ { code = append(code, inviteChars[rand.Intn(len(inviteChars) - 1)]) } return code }