forked from nixcn/nixcn-cms
160 lines
4.3 KiB
Go
160 lines
4.3 KiB
Go
package data
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/go-viper/mapstructure/v2"
|
|
"github.com/google/uuid"
|
|
"github.com/meilisearch/meilisearch-go"
|
|
"gorm.io/datatypes"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
// Permission Level
|
|
// Banned User: 0
|
|
// Normal User: 10
|
|
// Admin User: 20
|
|
// Super User: 30
|
|
|
|
type User struct {
|
|
Id uint `json:"id" gorm:"primarykey;autoincrement"`
|
|
UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueindex;not null"`
|
|
UserId uuid.UUID `json:"user_id" gorm:"type:uuid;uniqueindex;not null"`
|
|
Email string `json:"email" gorm:"type:varchar(255);uniqueindex;not null"`
|
|
Type string `json:"type" gorm:"type:varchar(32);index;not null"`
|
|
Nickname string `json:"nickname"`
|
|
Subtitle string `json:"subtitle"`
|
|
Avatar string `json:"avatar"`
|
|
Checkin datatypes.JSONMap `json:"checkin"`
|
|
PermissionLevel uint `json:"permission_level" gorm:"default:10;not null"`
|
|
}
|
|
|
|
type UserSearchDoc struct {
|
|
UserId string `json:"user_id"`
|
|
Email string `json:"email"`
|
|
Type string `json:"type"`
|
|
Nickname string `json:"nickname"`
|
|
Subtitle string `json:"subtitle"`
|
|
Avatar string `json:"avatar"`
|
|
PermissionLevel uint `json:"permission_level"`
|
|
}
|
|
|
|
func (self *User) GetByEmail(email string) error {
|
|
if err := Database.Where("email = ?", email).First(&self).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (self *User) GetByUserId(userId uuid.UUID) error {
|
|
if err := Database.Where("user_id = ?", userId).First(&self).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (self *User) UpdateCheckin(userId, eventId uuid.UUID, time time.Time) error {
|
|
return Database.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.
|
|
Clauses(clause.Locking{Strength: "UPDATE"}).
|
|
Where("user_id = ?", userId).
|
|
First(self).Error; err != nil {
|
|
return err // if error then rollback
|
|
}
|
|
|
|
self.Checkin = datatypes.JSONMap{eventId.String(): time}
|
|
|
|
if err := tx.Save(self).Error; err != nil {
|
|
return err // rollback
|
|
}
|
|
|
|
// Update user to document index
|
|
doc := UserSearchDoc{
|
|
UserId: self.UserId.String(),
|
|
Email: self.Email,
|
|
Type: self.Type,
|
|
Nickname: self.Nickname,
|
|
Subtitle: self.Subtitle,
|
|
Avatar: self.Avatar,
|
|
PermissionLevel: self.PermissionLevel,
|
|
}
|
|
index := MeiliSearch.Index("user")
|
|
docPrimaryKey := "user_id"
|
|
meiliOptions := &meilisearch.DocumentOptions{PrimaryKey: &docPrimaryKey}
|
|
if _, err := index.UpdateDocuments([]UserSearchDoc{doc}, meiliOptions); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil // commit
|
|
})
|
|
}
|
|
|
|
func (self *User) Create() error {
|
|
return Database.Transaction(func(tx *gorm.DB) error {
|
|
if self.UUID == uuid.Nil {
|
|
self.UUID = uuid.New()
|
|
}
|
|
if self.UserId == uuid.Nil {
|
|
self.UserId = uuid.New()
|
|
}
|
|
|
|
if err := tx.Create(self).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create user to document index
|
|
doc := UserSearchDoc{
|
|
UserId: self.UserId.String(),
|
|
Email: self.Email,
|
|
Type: self.Type,
|
|
Nickname: self.Nickname,
|
|
Subtitle: self.Subtitle,
|
|
Avatar: self.Avatar,
|
|
PermissionLevel: self.PermissionLevel,
|
|
}
|
|
index := MeiliSearch.Index("user")
|
|
docPrimaryKey := "user_id"
|
|
meiliOptions := &meilisearch.DocumentOptions{PrimaryKey: &docPrimaryKey}
|
|
if _, err := index.AddDocuments([]UserSearchDoc{doc}, meiliOptions); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (self *User) UpdateByUserID(userId uuid.UUID) error {
|
|
return Database.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Model(&User{}).Where("user_id = ?", userId).Updates(&self).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (self *User) GetFullTable() (*[]User, error) {
|
|
var users []User
|
|
err := Database.Find(&users).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &users, nil
|
|
}
|
|
|
|
func (self *User) FastListUsers(limit, offset int64) (*[]UserSearchDoc, error) {
|
|
index := MeiliSearch.Index("user")
|
|
result, err := index.Search("", &meilisearch.SearchRequest{
|
|
Limit: limit,
|
|
Offset: offset,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var list []UserSearchDoc
|
|
if err := mapstructure.Decode(result.Hits, &list); err != nil {
|
|
return nil, err
|
|
}
|
|
return &list, nil
|
|
}
|