party/cmd/party/common/tokens.go

68 lines
2.0 KiB
Go

package common
import (
"crypto/sha256"
"errors"
"fmt"
"time"
"party.at/party/internal/data"
)
func (app *Application) LoginUser(email, password string) (*data.Token, error) {
app.Logger.PrintInfo("login attempt", map[string]string{"email": email})
user, err := app.Models.Users.GetByEmail(email)
if err != nil {
if errors.Is(err, data.ErrRecordNotFound) {
app.Logger.PrintInfo("login failed: user not found", map[string]string{"email": email})
return nil, data.ErrInvalidCredentials
}
return nil, err
}
identities, err := app.Models.UserIdentities.GetByUser(user.ID)
if err != nil {
if errors.Is(err, data.ErrRecordNotFound) {
app.Logger.PrintInfo("login failed: no identities", map[string]string{"email": email, "user_id": fmt.Sprint(user.ID)})
return nil, data.ErrInvalidCredentials
}
return nil, err
}
app.Logger.PrintInfo("login: found identities", map[string]string{"email": email, "count": fmt.Sprint(len(identities))})
var authenticatedIdentity *data.UserIdentity
for _, identity := range identities {
match, err := identity.Password.Matches(password)
if err != nil {
return nil, err
}
if match {
authenticatedIdentity = identity
break
}
}
if authenticatedIdentity == nil {
app.Logger.PrintInfo("login failed: wrong password", map[string]string{"email": email})
return nil, data.ErrInvalidCredentials
}
app.Logger.PrintInfo("login success", map[string]string{"email": email, "user_id": fmt.Sprint(user.ID)})
return app.Models.Tokens.New(user.ID, authenticatedIdentity.ID, 24*time.Hour, data.ScopeAuthentication)
}
func (app *Application) GetUserFromToken(plaintext string) (*data.User, error) {
userIdentity, err := app.Models.UserIdentities.GetForToken(data.ScopeAuthentication, plaintext)
if err != nil {
return nil, err
}
return app.Models.Users.Get(userIdentity.UserID)
}
func (app *Application) DeleteToken(plaintext string) error {
hash := sha256.Sum256([]byte(plaintext))
return app.Models.Tokens.Delete(hash[:])
}