b0aa111511
The api has been tested and works as intended. Now users do not have to go on the website to get back their token, they just have to register. Torrents show the right stats and username on api request when search is done User model when converted to JSON gives us the apitoken and md5 hash of email (for gravatar) Verification on upload is done by token and username instead of token only Errors are now given in json format in the api Global api response handler for less code redundancy and same response pattern Moved user auth check in cookie_helper to user.go Fixed bug with CSRF prevention in /api Added translation strings
211 lignes
5,9 Kio
Go
211 lignes
5,9 Kio
Go
package model
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/NyaaPantsu/nyaa/config"
|
|
)
|
|
|
|
const (
|
|
// UserStatusBanned : Int for User status banned
|
|
UserStatusBanned = -1
|
|
// UserStatusMember : Int for User status member
|
|
UserStatusMember = 0
|
|
// UserStatusTrusted : Int for User status trusted
|
|
UserStatusTrusted = 1
|
|
// UserStatusModerator : Int for User status moderator
|
|
UserStatusModerator = 2
|
|
// UserStatusScraped : Int for User status scrapped
|
|
UserStatusScraped = 3
|
|
)
|
|
|
|
// User model
|
|
type User struct {
|
|
ID uint `gorm:"column:user_id;primary_key"`
|
|
Username string `gorm:"column:username"`
|
|
Password string `gorm:"column:password"`
|
|
Email string `gorm:"column:email"`
|
|
Status int `gorm:"column:status"`
|
|
CreatedAt time.Time `gorm:"column:created_at"`
|
|
UpdatedAt time.Time `gorm:"column:updated_at"`
|
|
APIToken string `gorm:"column:api_token"`
|
|
APITokenExpiry time.Time `gorm:"column:api_token_expiry"`
|
|
Language string `gorm:"column:language"`
|
|
Theme string `gorm:"column:theme"`
|
|
Mascot string `gorm:"column:mascot"`
|
|
MascotURL string `gorm:"column:mascot_url"`
|
|
UserSettings string `gorm:"column:settings"`
|
|
|
|
// TODO: move this to PublicUser
|
|
Followers []User // Don't work `gorm:"foreignkey:user_id;associationforeignkey:follower_id;many2many:user_follows"`
|
|
Likings []User // Don't work `gorm:"foreignkey:follower_id;associationforeignkey:user_id;many2many:user_follows"`
|
|
|
|
MD5 string `json:"md5" gorm:"column:md5"` // Hash of email address, used for Gravatar
|
|
Torrents []Torrent `gorm:"ForeignKey:UploaderID"`
|
|
Notifications []Notification `gorm:"ForeignKey:UserID"`
|
|
|
|
UnreadNotifications int `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
|
|
Settings UserSettings `gorm:"-"` // We don't want to load settings everytime, stock it as a string, parse it when needed
|
|
}
|
|
|
|
// UserJSON : User model conversion in JSON
|
|
type UserJSON struct {
|
|
ID uint `json:"user_id"`
|
|
Username string `json:"username"`
|
|
Status int `json:"status"`
|
|
APIToken string `json:"token"`
|
|
MD5 string `json:"md5"`
|
|
CreatedAt string `json:"created_at"`
|
|
LikingCount int `json:"liking_count"`
|
|
LikedCount int `json:"liked_count"`
|
|
}
|
|
|
|
// Size : Returns the total size of memory recursively allocated for this struct
|
|
func (u User) Size() (s int) {
|
|
s += 4 + // ints
|
|
6*2 + // string pointers
|
|
4*3 + //time.Time
|
|
3*2 + // arrays
|
|
// string arrays
|
|
len(u.Username) + len(u.Password) + len(u.Email) + len(u.APIToken) + len(u.MD5) + len(u.Language) + len(u.Theme)
|
|
s *= 8
|
|
|
|
// Ignoring foreign key users. Fuck them.
|
|
|
|
return
|
|
}
|
|
|
|
// IsBanned : Return true if user is banned
|
|
func (u *User) IsBanned() bool {
|
|
return u.Status == UserStatusBanned
|
|
}
|
|
|
|
// IsMember : Return true if user is member
|
|
func (u *User) IsMember() bool {
|
|
return u.Status == UserStatusMember
|
|
}
|
|
|
|
// IsTrusted : Return true if user is tusted
|
|
func (u *User) IsTrusted() bool {
|
|
return u.Status == UserStatusTrusted
|
|
}
|
|
|
|
// IsModerator : Return true if user is moderator
|
|
func (u *User) IsModerator() bool {
|
|
return u.Status == UserStatusModerator
|
|
}
|
|
|
|
// IsScraped : Return true if user is a scrapped user
|
|
func (u *User) IsScraped() bool {
|
|
return u.Status == UserStatusScraped
|
|
}
|
|
|
|
// GetUnreadNotifications : Get unread notifications from a user
|
|
func (u *User) GetUnreadNotifications() int {
|
|
if u.UnreadNotifications == 0 {
|
|
for _, notif := range u.Notifications {
|
|
if !notif.Read {
|
|
u.UnreadNotifications++
|
|
}
|
|
}
|
|
}
|
|
return u.UnreadNotifications
|
|
}
|
|
|
|
// PublicUser : Is it Deprecated?
|
|
type PublicUser struct {
|
|
User *User
|
|
}
|
|
|
|
// UserFollows association table : different users following eachother
|
|
type UserFollows struct {
|
|
UserID uint `gorm:"column:user_id"`
|
|
FollowerID uint `gorm:"column:following"`
|
|
}
|
|
|
|
// UserUploadsOld model : Is it deprecated?
|
|
type UserUploadsOld struct {
|
|
Username string `gorm:"column:username"`
|
|
TorrentID uint `gorm:"column:torrent_id"`
|
|
}
|
|
|
|
// UserSettings : Struct for user settings, not a model
|
|
type UserSettings struct {
|
|
Settings map[string]bool `json:"settings"`
|
|
}
|
|
|
|
// TableName : Return the name of OldComment table
|
|
func (c UserUploadsOld) TableName() string {
|
|
// is this needed here?
|
|
return config.Conf.Models.UploadsOldTableName
|
|
}
|
|
|
|
// ToJSON : Conversion of a user model to json
|
|
func (u *User) ToJSON() UserJSON {
|
|
json := UserJSON{
|
|
ID: u.ID,
|
|
Username: u.Username,
|
|
APIToken: u.APIToken,
|
|
MD5: u.MD5,
|
|
Status: u.Status,
|
|
CreatedAt: u.CreatedAt.Format(time.RFC3339),
|
|
LikingCount: len(u.Followers),
|
|
LikedCount: len(u.Likings),
|
|
}
|
|
return json
|
|
}
|
|
|
|
/* User Settings */
|
|
|
|
// Get a user setting by keyname
|
|
func (s *UserSettings) Get(key string) bool {
|
|
if val, ok := s.Settings[key]; ok {
|
|
return val
|
|
}
|
|
return config.Conf.Users.DefaultUserSettings[key]
|
|
}
|
|
|
|
// GetSettings : get all user settings
|
|
func (s *UserSettings) GetSettings() map[string]bool {
|
|
return s.Settings
|
|
}
|
|
|
|
// Set a user setting by keyname
|
|
func (s *UserSettings) Set(key string, val bool) {
|
|
if s.Settings == nil {
|
|
s.Settings = make(map[string]bool)
|
|
}
|
|
s.Settings[key] = val
|
|
}
|
|
|
|
// ToDefault : Set user settings to default
|
|
func (s *UserSettings) ToDefault() {
|
|
s.Settings = config.Conf.Users.DefaultUserSettings
|
|
}
|
|
|
|
func (s *UserSettings) initialize() {
|
|
s.Settings = make(map[string]bool)
|
|
}
|
|
|
|
// SaveSettings : Format settings into a json string for preparing before user insertion
|
|
func (u *User) SaveSettings() {
|
|
byteArray, err := json.Marshal(u.Settings)
|
|
|
|
if err != nil {
|
|
fmt.Print(err)
|
|
}
|
|
u.UserSettings = string(byteArray)
|
|
}
|
|
|
|
// ParseSettings : Function to parse json string into usersettings struct, only parse if necessary
|
|
func (u *User) ParseSettings() {
|
|
if len(u.Settings.GetSettings()) == 0 && u.UserSettings != "" {
|
|
u.Settings.initialize()
|
|
json.Unmarshal([]byte(u.UserSettings), &u.Settings)
|
|
} else if len(u.Settings.GetSettings()) == 0 && u.UserSettings != "" {
|
|
u.Settings.initialize()
|
|
u.Settings.ToDefault()
|
|
}
|
|
}
|