package v1 import ( "fmt" "net/http" "time" "github.com/dgrijalva/jwt-go" ) type User struct { ID int64 `json:"id"` Username string `json:"username"` Password string `json:"-"` Email string `json:"-"` RegistrationDate time.Time `json:"reg_date" db:"reg_date"` LastSeen time.Time `json:"last_seen" db:"last_seen"` Avatar string `json:"avatar"` IsSuperuser bool `json:"is_superuser" db:"is_superuser"` IsActivated bool `json:"is_activated" db:"is_activated"` GroupID int8 `json:"-" db:"group_id"` Group Group `json:"group"` Cover string `json:"cover"` UseGravatar bool `json:"use_gravatar" db:"use_gravatar"` Theme string `json:"theme"` IsBanned bool `json:"is_banned" db:"is_banned"` } type UserNovels struct { UserID int64 `json:"user_id" db:"user_id" sql:"REFERENCES users(id)"` NovelID int16 `json:"novel_id" db:"novel_id" sql:"REFERENCES novels(id)"` Mark int8 `json:"mark"` Status string `json:"status"` } type UserNovelWithInfo struct { UserNovels Novel } var ( ErrNotAuthorized = fmt.Errorf("%s", "not authorized") ) func FetchUsers() ([]*User, error) { var users = make([]*User, 0) err := database.Select(&users, "select * from users limit 100;") for _, user := range users { if user.UseGravatar { user.Avatar = GetUserGravatar(user.Email) } } return users, err } func FetchUser(id int) (*User, error) { var user = &User{} err := database.Get(user, `select users.* from users where users.id = $1;`, id) if err == nil { if user.UseGravatar { user.Avatar = GetUserGravatar(user.Email) } err = database.Get(&user.Group, `select * from groups where id = $1;`, user.GroupID) } return user, err } func UpdateUser(user *User) (*User, error) { var u = &User{} rows, err := database.NamedQuery(`update users set avatar=:avatar, username=:username, is_activated=:is_activated, use_gravatar=:use_gravatar where id=:id returning *;`, user) if rows != nil && rows.Next() { _ = rows.StructScan(u) if u.UseGravatar { u.Avatar = GetUserGravatar(u.Email) } } return u, err } func UpdatePassword(id int, password string) error { _, err := database.Exec("update users set password=$1 where id=$2;", password, id) return err } func FetchCurrentUser(r *http.Request) (*User, error) { cookie, err := r.Cookie("token") if err == http.ErrNoCookie { return nil, ErrNotAuthorized } if err != nil { return nil, err } if len(cookie.Value) == 0 { return nil, ErrNotAuthorized } return FetchUserByToken(cookie.Value) } func FetchUserByToken(tokenString string) (*User, error) { var user = &User{} token, err := jwt.Parse(tokenString, func(token *jwt.Token) (i interface{}, e error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return []byte(privateConfig.AuthTokenSecret), nil }) if err != nil { return user, err } if !token.Valid { return user, fmt.Errorf("token not valid") } if claims, ok := token.Claims.(jwt.MapClaims); ok { err = database.Get(user, `select users.* from users where users.id = $1;`, claims["id"]) if err == nil { if user.UseGravatar { user.Avatar = GetUserGravatar(user.Email) } err = database.Get(&user.Group, `select * from groups where id = $1;`, user.GroupID) } } return user, err } func FetchUserByLogin(login string) (*User, error) { user := new(User) err := database.Get(user, `select * from users where username = $1 or email = $1;`, login) if err == nil { if user.UseGravatar { user.Avatar = GetUserGravatar(user.Email) } err = database.Get(&user.Group, `select * from groups where id = $1;`, user.GroupID) } return user, err } func FetchUserNovels(id int) ([]*UserNovelWithInfo, error) { var novels = make([]*UserNovelWithInfo, 0) err := database.Select(&novels, `select novels.*, user_novel.* from user_novel inner join novels on (novels.id = user_novel.novel_id) where user_id = $1;`, id) return novels, err } func CreateUserNovel(novelData *UserNovels) (*UserNovels, error) { var novel = &UserNovels{} rows, err := database.NamedQuery(`insert into user_novel(user_id, novel_id, mark, status) VALUES (:user_id, :novel_id, :mark, :status) returning *;`, novelData) if rows != nil && rows.Next() { _ = rows.StructScan(novel) } return novel, err } func FetchUserNovel(userId int, novelId int) (*UserNovels, error) { var novel = &UserNovels{} err := database.Get(novel, `select user_novel.* from user_novel where user_id = $1 and novel_id = $2;`, userId, novelId) return novel, err } func UpdateUserNovel(novel *UserNovels) (*UserNovels, error) { var updatedNovel = &UserNovels{} rows, err := database.NamedQuery(`update user_novel set mark=:mark, status=:status where user_id=:user_id and novel_id=:novel_id returning *;`, novel) _, _ = database.Exec(`update novels set rating=avg_novel($1) where id=$1;`, novel.NovelID) if rows != nil && rows.Next() { _ = rows.StructScan(updatedNovel) } return updatedNovel, err } func DeleteUserNovel(userId int, novelId int) error { _, err := database.Exec("delete from user_novel where user_id = $1 and novel_id = $2;", userId, novelId) return err } func FetchUserNovelsComments(id int) ([]CommentNovel, error) { var comments = make([]CommentNovel, 0) err := database.Select(&comments, `select * from novel_comment where user_id = $1;`, id) return comments, err } func CreateUser(username string, password string, email string) (*User, error) { var user = &User{} var currentTime = time.Now() err := database.Get(user, "insert into users(username, password, email, reg_date, last_seen) VALUES ($1, $2, $3, $4, $4) returning *;", username, password, email, currentTime) return user, err } func ActivateUser(id int) (*User, error) { var user = &User{} err := database.Get(user, `update users set is_activated=true where id=$1 returning *;`, id) return user, err } func GetUserGravatar(email string) string { return fmt.Sprintf("https://www.gravatar.com/avatar/%s", MD5(email)) } // Settings func FetchUserSettings(id uint64) (*Settings, error) { settings := new(Settings) err := database.Get(settings, "select use_gravatar, avatar, theme from users where id=$1;", id) return settings, err } func UpdateUserSettings(id uint64, settings *Settings) (*User, error) { user := new(User) err := database.Get(user, "update users set use_gravatar=$2, avatar=$3, theme=$4 where id=$1 returning *;", id, settings.UseGravatar, settings.Avatar, settings.Theme) return user, err }