2023-09-06 22:20:09 +01:00
|
|
|
package database
|
|
|
|
|
|
|
|
import (
|
2023-09-07 11:45:16 +01:00
|
|
|
"database/sql"
|
2023-09-08 00:30:03 +01:00
|
|
|
"fmt"
|
2023-09-06 22:20:09 +01:00
|
|
|
"github.com/MrMelon54/pronouns"
|
2023-09-24 18:24:16 +01:00
|
|
|
"github.com/go-oauth2/oauth2/v4"
|
2023-09-06 22:20:09 +01:00
|
|
|
"github.com/google/uuid"
|
|
|
|
"golang.org/x/text/language"
|
|
|
|
"net/url"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type User struct {
|
|
|
|
Sub uuid.UUID `json:"sub"`
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
Username string `json:"username"`
|
|
|
|
Picture NullStringScanner `json:"picture,omitempty"`
|
|
|
|
Website NullStringScanner `json:"website,omitempty"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
EmailVerified bool `json:"email_verified"`
|
|
|
|
Pronouns PronounScanner `json:"pronouns,omitempty"`
|
|
|
|
Birthdate NullDateScanner `json:"birthdate,omitempty"`
|
|
|
|
ZoneInfo LocationScanner `json:"zoneinfo,omitempty"`
|
|
|
|
Locale LocaleScanner `json:"locale,omitempty"`
|
2023-09-15 13:06:31 +01:00
|
|
|
Role UserRole `json:"role"`
|
2023-09-06 22:20:09 +01:00
|
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
Active bool `json:"active"`
|
|
|
|
}
|
|
|
|
|
2023-09-15 13:06:31 +01:00
|
|
|
type UserRole int
|
|
|
|
|
|
|
|
const (
|
|
|
|
RoleMember UserRole = iota
|
|
|
|
RoleAdmin
|
2023-09-24 18:24:16 +01:00
|
|
|
RoleToDelete
|
2023-09-15 13:06:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func (r UserRole) String() string {
|
|
|
|
switch r {
|
|
|
|
case RoleMember:
|
|
|
|
return "Member"
|
|
|
|
case RoleAdmin:
|
|
|
|
return "Admin"
|
2023-09-24 18:24:16 +01:00
|
|
|
case RoleToDelete:
|
|
|
|
return "ToDelete"
|
2023-09-15 13:06:31 +01:00
|
|
|
}
|
|
|
|
return fmt.Sprintf("UserRole{ %d }", r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r UserRole) IsValid() bool {
|
|
|
|
return r == RoleMember || r == RoleAdmin
|
|
|
|
}
|
|
|
|
|
2023-09-06 22:20:09 +01:00
|
|
|
type UserPatch struct {
|
2023-09-07 11:45:16 +01:00
|
|
|
Name string
|
|
|
|
Picture string
|
|
|
|
Website string
|
|
|
|
Pronouns pronouns.Pronoun
|
|
|
|
Birthdate sql.NullTime
|
|
|
|
ZoneInfo *time.Location
|
|
|
|
Locale language.Tag
|
2023-09-06 22:20:09 +01:00
|
|
|
}
|
|
|
|
|
2023-09-08 00:30:03 +01:00
|
|
|
func (u *UserPatch) ParseFromForm(v url.Values) (safeErrs []error) {
|
|
|
|
var err error
|
2023-09-07 11:45:16 +01:00
|
|
|
u.Name = v.Get("name")
|
|
|
|
u.Picture = v.Get("picture")
|
|
|
|
u.Website = v.Get("website")
|
|
|
|
if v.Has("reset_pronouns") {
|
|
|
|
u.Pronouns = pronouns.TheyThem
|
|
|
|
} else {
|
|
|
|
u.Pronouns, err = pronouns.FindPronoun(v.Get("pronouns"))
|
2023-09-06 22:20:09 +01:00
|
|
|
if err != nil {
|
2023-09-08 00:30:03 +01:00
|
|
|
safeErrs = append(safeErrs, fmt.Errorf("invalid pronoun selected"))
|
2023-09-06 22:20:09 +01:00
|
|
|
}
|
|
|
|
}
|
2023-09-08 00:30:03 +01:00
|
|
|
if v.Has("reset_birthdate") || v.Get("birthdate") == "" {
|
2023-09-07 11:45:16 +01:00
|
|
|
u.Birthdate = sql.NullTime{}
|
|
|
|
} else {
|
|
|
|
u.Birthdate = sql.NullTime{Valid: true}
|
|
|
|
u.Birthdate.Time, err = time.Parse(time.DateOnly, v.Get("birthdate"))
|
2023-09-06 22:20:09 +01:00
|
|
|
if err != nil {
|
2023-09-08 00:30:03 +01:00
|
|
|
safeErrs = append(safeErrs, fmt.Errorf("invalid time selected"))
|
2023-09-06 22:20:09 +01:00
|
|
|
}
|
|
|
|
}
|
2023-09-07 11:45:16 +01:00
|
|
|
if v.Has("reset_zoneinfo") {
|
|
|
|
u.ZoneInfo = time.UTC
|
|
|
|
} else {
|
|
|
|
u.ZoneInfo, err = time.LoadLocation(v.Get("zoneinfo"))
|
2023-09-06 22:20:09 +01:00
|
|
|
if err != nil {
|
2023-09-08 00:30:03 +01:00
|
|
|
safeErrs = append(safeErrs, fmt.Errorf("invalid timezone selected"))
|
2023-09-06 22:20:09 +01:00
|
|
|
}
|
|
|
|
}
|
2023-09-07 11:45:16 +01:00
|
|
|
if v.Has("reset_locale") {
|
|
|
|
u.Locale = language.AmericanEnglish
|
|
|
|
} else {
|
|
|
|
u.Locale, err = language.Parse(v.Get("locale"))
|
2023-09-06 22:20:09 +01:00
|
|
|
if err != nil {
|
2023-09-08 00:30:03 +01:00
|
|
|
safeErrs = append(safeErrs, fmt.Errorf("invalid language selected"))
|
2023-09-06 22:20:09 +01:00
|
|
|
}
|
|
|
|
}
|
2023-09-08 00:30:03 +01:00
|
|
|
return
|
2023-09-06 22:20:09 +01:00
|
|
|
}
|
2023-09-24 18:24:16 +01:00
|
|
|
|
2023-09-29 16:37:23 +01:00
|
|
|
type ClientInfoDbOutput struct {
|
|
|
|
Sub, Name, Secret, Domain, Owner string
|
2024-02-08 01:16:46 +00:00
|
|
|
Public, SSO, Active bool
|
2023-09-29 16:37:23 +01:00
|
|
|
}
|
|
|
|
|
2023-09-24 18:24:16 +01:00
|
|
|
var _ oauth2.ClientInfo = &ClientInfoDbOutput{}
|
|
|
|
|
|
|
|
func (c *ClientInfoDbOutput) GetID() string { return c.Sub }
|
|
|
|
func (c *ClientInfoDbOutput) GetSecret() string { return c.Secret }
|
|
|
|
func (c *ClientInfoDbOutput) GetDomain() string { return c.Domain }
|
2024-02-08 01:16:46 +00:00
|
|
|
func (c *ClientInfoDbOutput) IsPublic() bool { return c.Public }
|
2023-09-24 18:24:16 +01:00
|
|
|
func (c *ClientInfoDbOutput) GetUserID() string { return c.Owner }
|
|
|
|
|
|
|
|
// GetName is an extra field for the oauth handler to display the application
|
|
|
|
// name
|
|
|
|
func (c *ClientInfoDbOutput) GetName() string { return c.Name }
|
|
|
|
|
|
|
|
// IsSSO is an extra field for the oauth handler to skip the user input stage
|
|
|
|
// this is for trusted applications to get permissions without asking the user
|
|
|
|
func (c *ClientInfoDbOutput) IsSSO() bool { return c.SSO }
|
|
|
|
|
|
|
|
// IsActive is an extra field for the app manager to get the active state
|
|
|
|
func (c *ClientInfoDbOutput) IsActive() bool { return c.Active }
|