package user import ( "encoding/pem" "log" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" group "example.com/database/group" person "example.com/database/person" "gorm.io/gorm" ) type User struct { gorm.Model Id string `gorm:"primaryKey uniqueIndex" json:"id"` Person person.Person `gorm:"foreignKey:Name" json:"person"` DisplayName string `json:"display_name"` Username string `json:"user_name"` Avatar string `json:"avatar"` AvatarDecoration string `json:"avatar_decoration"` LoginToken string `json:"login_token"` LoggedIn bool `json:"logged_in"` ApiKeys []ApiKey `gorm:"many2many:user_apikey_associations" json:"api_key"` } type ApiKey struct { gorm.Model Name string `gorm:"primaryKey uniqueIndex" json:"name"` Secret string `json:"secret"` } func (user User) Create(db *gorm.DB) error { result := db.Create(&user) if result.Error != nil { return result.Error } return nil } func (user *User) getAssociations(db *gorm.DB) error { result := db.Model(&user).Association("Person").Find(&user.Person) if result != nil { return result } return nil } func (user *User) Get(db *gorm.DB, id string) error { result := db.Where("id = ?", id).Take(&user) if result.Error == gorm.ErrRecordNotFound { result = db.Where("login_token = ?", id).Take(&user) if result.Error != nil { return result.Error } } err := user.getAssociations(db) if err != nil { return err } return nil } func (user *User) GetPersonGroups(db *gorm.DB) []string { var groups []string var groupObjects []group.Group user.getAssociations(db) var person []person.Person db.Model(&user).Association("Person").Find(&person) db.Model(&person[0]).Association("Groups").Find(&groupObjects) for _, groupObject := range groupObjects { groups = append(groups, groupObject.Name) } return groups } func (user *User) GetAPIKeySecret(db *gorm.DB, name string) string { var apiKeys []ApiKey err := db.Model(&user).Association("ApiKeys").Find(&apiKeys) if err != nil { return "" } var secret string result := db.Model(&apiKeys).Select("secret").Where("name = ?", name).Take(&secret) if result.Error != nil { return "" } return secret } func (user User) Update(db *gorm.DB) error { var originalUser User originalUser.Get(db, user.Id) result := db.Model(&originalUser).Updates(&user) if result.Error != nil { return result.Error } return nil } func (user User) Delete(db *gorm.DB) error { result := db.Delete(&user) if result.Error != nil { return result.Error } return nil } func (user User) Logout(db *gorm.DB) error { result := db.Model(&user).Update("logged_in", false) if result.Error != nil { return result.Error } return nil } func (user User) GenerateAPIKey(db *gorm.DB, name string) error { key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) bytestringKey, err := x509.MarshalECPrivateKey(key) pemKey := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: bytestringKey}) newApiKey := ApiKey{ Name: name, Secret: string(pemKey), } db.Create(&newApiKey) user.getAssociations(db) user.ApiKeys = append(user.ApiKeys, newApiKey) user.Update(db) return err } func Logout(db *gorm.DB, oauthToken string) error { var user User user.Get(db, oauthToken) return user.Logout(db) } func Exists(db *gorm.DB, id string) bool { var queryUser User err := queryUser.Get(db, id) return (err == nil) } func Create(db *gorm.DB, id string, displayName string, username string, avatar string, avatarDecoration string, loginToken string, loggedIn bool) error { person.Create(db, displayName, []uint{}) newPerson := (*person.Get(db, []string{displayName}))[0] newUser := User{ Id: id, Person: person.Person{}, DisplayName: displayName, Username: username, Avatar: avatar, AvatarDecoration: avatarDecoration, LoginToken: loginToken, LoggedIn: loggedIn, ApiKeys: nil, } err := newUser.Create(db) if err != nil { return err } err = db.Model(&newUser).Association("Person").Replace(&newPerson) if err != nil { return err } return nil } func Get(db *gorm.DB, inputUsers []string) *[]User { var outputUsers []User for _, inputUser := range inputUsers { var outputUser User outputUser.Get(db, inputUser) outputUsers = append(outputUsers, outputUser) } return &outputUsers } func GetAll(db *gorm.DB) *[]User { var outputUserIDs []string result := db.Model(&User{}).Select("id").Find(&outputUserIDs) if result.Error != nil { log.Println(result.Error) } return Get(db, outputUserIDs) } func Update(db *gorm.DB, id string, displayName string, username string, avatar string, avatarDecoration string, loginToken string, loggedIn bool) error { newPerson := (*person.Get(db, []string{displayName}))[0] return User{ Id: id, Person: newPerson, DisplayName: displayName, Username: username, Avatar: avatar, AvatarDecoration: avatarDecoration, LoginToken: loginToken, LoggedIn: loggedIn, ApiKeys: nil, }.Update(db) }