cpularp-manager-api/src/lib/database/user/user.go

205 lines
5.1 KiB
Go

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, discordId string, displayName string, username string, avatar string, avatarDecoration string, loginToken string, loggedIn bool) error {
person.Create(db, displayName, []uint{})
newPerson := person.GetByName(db, username)
newUser := User{
Id: discordId,
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, discordId string, displayName string, username string, avatar string, avatarDecoration string, loginToken string, loggedIn bool) error {
newPerson := *person.GetByName(db, username)
return User{
Id: discordId,
Person: newPerson,
DisplayName: displayName,
Username: username,
Avatar: avatar,
AvatarDecoration: avatarDecoration,
LoginToken: loginToken,
LoggedIn: loggedIn,
ApiKeys: nil,
}.Update(db)
}