2019-05-06 01:40:41 +03:00
package models
2021-04-25 15:15:18 +03:00
import (
2021-10-14 13:01:06 +03:00
"crypto/md5"
"fmt"
2021-04-25 15:15:18 +03:00
"regexp"
2021-10-14 13:01:06 +03:00
"strings"
2021-04-25 15:15:18 +03:00
"time"
)
2021-02-21 15:02:11 +03:00
func init ( ) {
mailRegex = regexp . MustCompile ( MailPattern )
}
2019-05-06 01:40:41 +03:00
type User struct {
2021-02-07 00:32:03 +03:00
ID string ` json:"id" gorm:"primary_key" `
2022-05-08 00:17:15 +03:00
ApiKey string ` json:"api_key" gorm:"unique; default:NULL" `
2021-04-14 01:17:02 +03:00
Email string ` json:"email" gorm:"index:idx_user_email; size:255" `
2021-04-25 15:15:18 +03:00
Location string ` json:"location" `
2021-02-07 00:32:03 +03:00
Password string ` json:"-" `
2021-02-07 13:54:07 +03:00
CreatedAt CustomTime ` gorm:"type:timestamp; default:CURRENT_TIMESTAMP" swaggertype:"string" format:"date" example:"2006-01-02 15:04:05.000" `
LastLoggedInAt CustomTime ` gorm:"type:timestamp; default:CURRENT_TIMESTAMP" swaggertype:"string" format:"date" example:"2006-01-02 15:04:05.000" `
2021-02-07 01:23:26 +03:00
ShareDataMaxDays int ` json:"-" gorm:"default:0" `
2021-02-07 00:32:03 +03:00
ShareEditors bool ` json:"-" gorm:"default:false; type:bool" `
ShareLanguages bool ` json:"-" gorm:"default:false; type:bool" `
ShareProjects bool ` json:"-" gorm:"default:false; type:bool" `
ShareOSs bool ` json:"-" gorm:"default:false; type:bool; column:share_oss" `
ShareMachines bool ` json:"-" gorm:"default:false; type:bool" `
2021-06-11 21:59:34 +03:00
ShareLabels bool ` json:"-" gorm:"default:false; type:bool" `
2021-02-12 20:13:49 +03:00
IsAdmin bool ` json:"-" gorm:"default:false; type:bool" `
2021-02-13 14:59:59 +03:00
HasData bool ` json:"-" gorm:"default:false; type:bool" `
2022-01-21 14:35:05 +03:00
WakatimeApiKey string ` json:"-" ` // for relay middleware and imports
WakatimeApiUrl string ` json:"-" ` // for relay middleware and imports
2021-04-05 23:57:57 +03:00
ResetToken string ` json:"-" `
2021-04-30 15:07:14 +03:00
ReportsWeekly bool ` json:"-" gorm:"default:false; type:bool" `
2019-05-06 01:40:41 +03:00
}
2020-05-24 14:41:19 +03:00
type Login struct {
2020-05-24 17:34:32 +03:00
Username string ` schema:"username" `
Password string ` schema:"password" `
}
type Signup struct {
Username string ` schema:"username" `
2021-02-21 15:02:11 +03:00
Email string ` schema:"email" `
2020-05-24 17:34:32 +03:00
Password string ` schema:"password" `
PasswordRepeat string ` schema:"password_repeat" `
2021-04-25 21:02:45 +03:00
Location string ` schema:"location" `
2020-05-24 14:41:19 +03:00
}
2020-05-24 22:42:15 +03:00
2021-04-05 23:57:57 +03:00
type SetPasswordRequest struct {
Password string ` schema:"password" `
PasswordRepeat string ` schema:"password_repeat" `
Token string ` schema:"token" `
}
type ResetPasswordRequest struct {
Email string ` schema:"email" `
}
2020-06-07 20:28:32 +03:00
type CredentialsReset struct {
PasswordOld string ` schema:"password_old" `
PasswordNew string ` schema:"password_new" `
PasswordRepeat string ` schema:"password_repeat" `
}
2021-02-21 15:02:11 +03:00
type UserDataUpdate struct {
2021-04-30 17:20:08 +03:00
Email string ` schema:"email" `
Location string ` schema:"location" `
ReportsWeekly bool ` schema:"reports_weekly" `
2021-02-21 15:02:11 +03:00
}
2020-11-07 14:01:35 +03:00
type TimeByUser struct {
User string
2021-02-07 14:37:51 +03:00
Time CustomTime
2020-11-07 14:01:35 +03:00
}
2021-02-13 13:23:58 +03:00
type CountByUser struct {
User string
Count int64
}
2021-04-25 15:15:18 +03:00
func ( u * User ) TZ ( ) * time . Location {
if u . Location == "" {
u . Location = "Local"
}
tz , err := time . LoadLocation ( u . Location )
if err != nil {
return time . Local
}
return tz
}
2022-01-02 22:25:07 +03:00
// TZOffset returns the time difference between the user's current time zone and UTC
// TODO: is this actually working??
2021-04-25 15:15:18 +03:00
func ( u * User ) TZOffset ( ) time . Duration {
_ , offset := time . Now ( ) . In ( u . TZ ( ) ) . Zone ( )
return time . Duration ( offset * int ( time . Second ) )
}
2021-10-14 13:01:06 +03:00
func ( u * User ) AvatarURL ( urlTemplate string ) string {
urlTemplate = strings . ReplaceAll ( urlTemplate , "{username}" , u . ID )
urlTemplate = strings . ReplaceAll ( urlTemplate , "{email}" , u . Email )
if strings . Contains ( urlTemplate , "{username_hash}" ) {
urlTemplate = strings . ReplaceAll ( urlTemplate , "{username_hash}" , fmt . Sprintf ( "%x" , md5 . Sum ( [ ] byte ( u . ID ) ) ) )
}
if strings . Contains ( urlTemplate , "{email_hash}" ) {
urlTemplate = strings . ReplaceAll ( urlTemplate , "{email_hash}" , fmt . Sprintf ( "%x" , md5 . Sum ( [ ] byte ( u . Email ) ) ) )
}
return urlTemplate
}
2022-01-21 14:35:05 +03:00
// WakaTimeURL returns the user's effective WakaTime URL, i.e. a custom one (which could also point to another Wakapi instance) or fallback if not specified otherwise.
func ( u * User ) WakaTimeURL ( fallback string ) string {
if u . WakatimeApiUrl != "" {
return strings . TrimSuffix ( u . WakatimeApiUrl , "/" )
}
return fallback
}
2020-06-07 20:28:32 +03:00
func ( c * CredentialsReset ) IsValid ( ) bool {
2021-02-21 15:02:11 +03:00
return ValidatePassword ( c . PasswordNew ) &&
2020-06-07 20:28:32 +03:00
c . PasswordNew == c . PasswordRepeat
}
2021-04-05 23:57:57 +03:00
func ( c * SetPasswordRequest ) IsValid ( ) bool {
return ValidatePassword ( c . Password ) &&
c . Password == c . PasswordRepeat
}
2020-05-24 22:42:15 +03:00
func ( s * Signup ) IsValid ( ) bool {
2021-02-21 15:02:11 +03:00
return ValidateUsername ( s . Username ) &&
ValidateEmail ( s . Email ) &&
ValidatePassword ( s . Password ) &&
2020-05-24 22:42:15 +03:00
s . Password == s . PasswordRepeat
}
2020-06-07 20:28:32 +03:00
2021-02-21 15:02:11 +03:00
func ( r * UserDataUpdate ) IsValid ( ) bool {
2021-04-25 15:15:18 +03:00
return ValidateEmail ( r . Email ) && ValidateTimezone ( r . Location )
2021-02-21 15:02:11 +03:00
}
func ValidateUsername ( username string ) bool {
2021-01-12 13:05:07 +03:00
return len ( username ) >= 1 && username != "current"
2020-06-07 20:28:32 +03:00
}
2021-02-21 15:02:11 +03:00
func ValidatePassword ( password string ) bool {
2020-06-07 20:28:32 +03:00
return len ( password ) >= 6
}
2021-02-21 15:02:11 +03:00
func ValidateEmail ( email string ) bool {
return email == "" || mailRegex . Match ( [ ] byte ( email ) )
}
2021-04-25 15:15:18 +03:00
func ValidateTimezone ( tz string ) bool {
_ , err := time . LoadLocation ( tz )
return err == nil
}