|
- package models
-
- import (
- "encoding/json"
- "fmt"
- "os"
- "strings"
- "time"
-
- "github.com/toolkits/pkg/logger"
- "github.com/toolkits/pkg/str"
- "xorm.io/builder"
-
- "github.com/didi/nightingale/v5/pkg/ierr"
- )
-
- type User struct {
- Id int64 `json:"id"`
- Username string `json:"username"`
- Nickname string `json:"nickname"`
- Password string `json:"-"`
- Phone string `json:"phone"`
- Email string `json:"email"`
- Portrait string `json:"portrait"`
- Status int `json:"status"`
- RolesForDB string `json:"-" xorm:"'roles'"` // 这个字段写入数据库
- RolesForFE []string `json:"roles" xorm:"-"` // 这个字段和前端交互
- Contacts json.RawMessage `json:"contacts"` // 内容为 map[string]string 结构
- CreateAt int64 `json:"create_at"`
- CreateBy string `json:"create_by"`
- UpdateAt int64 `json:"update_at"`
- UpdateBy string `json:"update_by"`
- }
-
- func (u *User) TableName() string {
- return "user"
- }
-
- func (u *User) Validate() error {
- u.Username = strings.TrimSpace(u.Username)
-
- if u.Username == "" {
- return _e("Username is blank")
- }
-
- if str.Dangerous(u.Username) {
- return _e("Username has invalid characters")
- }
-
- if str.Dangerous(u.Nickname) {
- return _e("Nickname has invalid characters")
- }
-
- if u.Phone != "" && !str.IsPhone(u.Phone) {
- return _e("Phone invalid")
- }
-
- if u.Email != "" && !str.IsMail(u.Email) {
- return _e("Email invalid")
- }
-
- return nil
- }
-
- func (u *User) Update(cols ...string) error {
- if err := u.Validate(); err != nil {
- return err
- }
-
- _, err := DB.Where("id=?", u.Id).Cols(cols...).Update(u)
- if err != nil {
- logger.Errorf("mysql.error: update user fail: %v", err)
- return internalServerError
- }
-
- return nil
- }
-
- func (u *User) Add() error {
- num, err := DB.Where("username=?", u.Username).Count(new(User))
- if err != nil {
- logger.Errorf("mysql.error: count user(%s) fail: %v", u.Username, err)
- return internalServerError
- }
-
- if num > 0 {
- return _e("Username %s already exists", u.Username)
- }
-
- return DBInsertOne(u)
- }
-
- func InitRoot() {
- var u User
- has, err := DB.Where("username=?", "root").Get(&u)
- if err != nil {
- fmt.Println("fatal: cannot query user root,", err)
- os.Exit(1)
- }
-
- if has {
- return
- }
-
- pass, err := CryptoPass("root.2020")
- if err != nil {
- fmt.Println("fatal: cannot crypto password,", err)
- os.Exit(1)
- }
-
- now := time.Now().Unix()
-
- u = User{
- Username: "root",
- Password: pass,
- Nickname: "超管",
- Portrait: "",
- RolesForDB: "Admin",
- Contacts: []byte("{}"),
- CreateAt: now,
- UpdateAt: now,
- CreateBy: "system",
- UpdateBy: "system",
- }
-
- _, err = DB.Insert(u)
- if err != nil {
- fmt.Println("fatal: cannot insert user root", err)
- os.Exit(1)
- }
-
- fmt.Println("user root init done")
- }
-
- func UserGetByUsername(username string) (*User, error) {
- return UserGet("username=?", username)
- }
-
- func UserGetById(id int64) (*User, error) {
- return UserGet("id=?", id)
- }
-
- func UserGet(where string, args ...interface{}) (*User, error) {
- var obj User
- has, err := DB.Where(where, args...).Get(&obj)
- if err != nil {
- logger.Errorf("mysql.error: query user(%s)%+v fail: %s", where, args, err)
- return nil, internalServerError
- }
-
- if !has {
- return nil, nil
- }
-
- obj.RolesForFE = strings.Fields(obj.RolesForDB)
-
- return &obj, nil
- }
-
- func UserTotal(query string) (num int64, err error) {
- if query != "" {
- q := "%" + query + "%"
- num, err = DB.Where("username like ? or nickname like ? or phone like ? or email like ?", q, q, q, q).Count(new(User))
- } else {
- num, err = DB.Count(new(User))
- }
-
- if err != nil {
- logger.Errorf("mysql.error: count user(query: %s) fail: %v", query, err)
- return num, internalServerError
- }
-
- return num, nil
- }
-
- func UserGets(query string, limit, offset int) ([]User, error) {
- session := DB.Limit(limit, offset).OrderBy("username")
- if query != "" {
- q := "%" + query + "%"
- session = session.Where("username like ? or nickname like ? or phone like ? or email like ?", q, q, q, q)
- }
-
- var users []User
- err := session.Find(&users)
- if err != nil {
- logger.Errorf("mysql.error: select user(query: %s) fail: %v", query, err)
- return users, internalServerError
- }
-
- if len(users) == 0 {
- return []User{}, nil
- }
-
- for i := 0; i < len(users); i++ {
- users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
- }
-
- return users, nil
- }
-
- func UserGetAll() ([]User, error) {
- var users []User
-
- err := DB.Find(&users)
- if err != nil {
- logger.Errorf("mysql.error: select user fail: %v", err)
- return users, internalServerError
- }
-
- if len(users) == 0 {
- return []User{}, nil
- }
-
- for i := 0; i < len(users); i++ {
- users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
- }
-
- return users, nil
- }
-
- func UserGetsByIds(ids []int64) ([]User, error) {
- if len(ids) == 0 {
- return []User{}, nil
- }
-
- var users []User
- err := DB.In("id", ids).OrderBy("username").Find(&users)
- if err != nil {
- logger.Errorf("mysql.error: query users by ids fail: %v", err)
- return users, internalServerError
- }
-
- if len(users) == 0 {
- return []User{}, nil
- }
-
- for i := 0; i < len(users); i++ {
- users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
- }
-
- return users, nil
- }
-
- func UserGetsByIdsStr(ids []string) ([]User, error) {
- var users []User
-
- err := DB.Where("id in (" + strings.Join(ids, ",") + ")").Find(&users)
- if err != nil {
- logger.Errorf("mysql.error: UserGetsByIds fail: %v", err)
- return nil, internalServerError
- }
-
- if len(users) == 0 {
- return []User{}, nil
- }
-
- for i := 0; i < len(users); i++ {
- users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
- }
-
- return users, nil
- }
-
- func PassLogin(username, pass string) (*User, error) {
- user, err := UserGetByUsername(username)
- if err != nil {
- return nil, err
- }
-
- if user == nil {
- logger.Infof("password auth fail, no such user: %s", username)
- return nil, loginFailError
- }
-
- loginPass, err := CryptoPass(pass)
- if err != nil {
- return nil, internalServerError
- }
-
- if loginPass != user.Password {
- logger.Infof("password auth fail, password error, user: %s", username)
- return nil, loginFailError
- }
-
- return user, nil
- }
-
- func LdapLogin(username, pass string) (*User, error) {
- sr, err := ldapReq(username, pass)
- if err != nil {
- return nil, err
- }
-
- user, err := UserGetByUsername(username)
- if err != nil {
- return nil, err
- }
-
- if user == nil {
- // default user settings
- user = &User{
- Username: username,
- Nickname: username,
- }
- }
-
- // copy attributes from ldap
- attrs := LDAP.Attributes
- if attrs.Nickname != "" {
- user.Nickname = sr.Entries[0].GetAttributeValue(attrs.Nickname)
- }
- if attrs.Email != "" {
- user.Email = sr.Entries[0].GetAttributeValue(attrs.Email)
- }
- if attrs.Phone != "" {
- user.Phone = sr.Entries[0].GetAttributeValue(attrs.Phone)
- }
-
- if user.Id > 0 {
- if LDAP.CoverAttributes {
- _, err := DB.Where("id=?", user.Id).Update(user)
- if err != nil {
- logger.Errorf("mysql.error: update user %+v fail: %v", user, err)
- return nil, internalServerError
- }
- }
- return user, nil
- }
-
- now := time.Now().Unix()
-
- user.Password = "******"
- user.Portrait = "/img/linux.jpeg"
- user.RolesForDB = "Standard"
- user.RolesForFE = []string{"Standard"}
- user.Contacts = []byte("{}")
- user.CreateAt = now
- user.UpdateAt = now
- user.CreateBy = "ldap"
- user.UpdateBy = "ldap"
-
- err = DBInsertOne(user)
- return user, err
- }
-
- func (u *User) ChangePassword(oldpass, newpass string) error {
- _oldpass, err := CryptoPass(oldpass)
- if err != nil {
- return err
- }
- _newpass, err := CryptoPass(newpass)
- if err != nil {
- return err
- }
-
- if u.Password != _oldpass {
- return _e("Incorrect old password")
- }
-
- u.Password = _newpass
- return u.Update("password")
- }
-
- func (u *User) _del() error {
- session := DB.NewSession()
- defer session.Close()
-
- if err := session.Begin(); err != nil {
- return err
- }
-
- if _, err := session.Exec("DELETE FROM user_token WHERE user_id=?", u.Id); err != nil {
- return err
- }
-
- if _, err := session.Exec("DELETE FROM user_group_member WHERE user_id=?", u.Id); err != nil {
- return err
- }
-
- if _, err := session.Exec("DELETE FROM classpath_favorite WHERE user_id=?", u.Id); err != nil {
- return err
- }
-
- if _, err := session.Exec("DELETE FROM alert_rule_group_favorite WHERE user_id=?", u.Id); err != nil {
- return err
- }
-
- if _, err := session.Exec("DELETE FROM user WHERE id=?", u.Id); err != nil {
- return err
- }
-
- return session.Commit()
- }
-
- func (u *User) Del() error {
- err := u._del()
- if err != nil {
- logger.Errorf("mysql.error: delete user(%d, %s) fail: %v", u.Id, u.Username, err)
- return internalServerError
- }
- return nil
- }
-
- func (u *User) FavoriteClasspathIds() ([]int64, error) {
- return ClasspathFavoriteGetClasspathIds(u.Id)
- }
-
- func (u *User) FavoriteAlertRuleGroupIds() ([]int64, error) {
- return AlertRuleGroupFavoriteGetGroupIds(u.Id)
- }
-
- func (u *User) FavoriteDashboardIds() ([]int64, error) {
- return DashboardFavoriteGetDashboardIds(u.Id)
- }
-
- // UserGroupIds 我是成员的用户组ID列表
- func (u *User) UserGroupIds() ([]int64, error) {
- var ids []int64
- err := DB.Table(new(UserGroupMember)).Select("group_id").Where("user_id=?", u.Id).Find(&ids)
- if err != nil {
- logger.Errorf("mysql.error: query user_group_member fail: %v", err)
- return ids, internalServerError
- }
-
- return ids, nil
- }
-
- func (u *User) FavoriteClasspaths() ([]Classpath, error) {
- ids, err := u.FavoriteClasspathIds()
- if err != nil {
- return nil, err
- }
-
- var objs []Classpath
- err = DB.In("id", ids).OrderBy("path").Find(&objs)
- if err != nil {
- logger.Errorf("mysql.error: query my classpath fail: %v", err)
- return nil, internalServerError
- }
-
- if len(objs) == 0 {
- return []Classpath{}, nil
- }
-
- return objs, nil
- }
-
- func (u *User) FavoriteAlertRuleGroups() ([]AlertRuleGroup, error) {
- ids, err := u.FavoriteAlertRuleGroupIds()
- if err != nil {
- return nil, err
- }
-
- var objs []AlertRuleGroup
- err = DB.In("id", ids).OrderBy("name").Find(&objs)
- if err != nil {
- logger.Errorf("mysql.error: query my alert_rule_group fail: %v", err)
- return nil, internalServerError
- }
-
- if len(objs) == 0 {
- return []AlertRuleGroup{}, nil
- }
-
- return objs, nil
- }
-
- func (u *User) MyUserGroups() ([]UserGroup, error) {
- cond := builder.NewCond()
- cond = cond.And(builder.Eq{"create_by": u.Username})
-
- ids, err := u.UserGroupIds()
- if err != nil {
- return nil, err
- }
-
- if len(ids) > 0 {
- cond = cond.Or(builder.In("id", ids))
- }
-
- var objs []UserGroup
- err = DB.Where(cond).OrderBy("name").Find(&objs)
- if err != nil {
- logger.Errorf("mysql.error: query my user_group fail: %v", err)
- return nil, internalServerError
- }
-
- if len(objs) == 0 {
- return []UserGroup{}, nil
- }
-
- return objs, nil
- }
-
- func (u *User) CanModifyUserGroup(ug *UserGroup) (bool, error) {
- // 我是管理员,自然可以
- roles := strings.Fields(u.RolesForDB)
- for i := 0; i < len(roles); i++ {
- if roles[i] == "Admin" {
- return true, nil
- }
- }
-
- // 我是创建者,自然可以
- if ug.CreateBy == u.Username {
- return true, nil
- }
-
- // 我是成员,也可以吧,简单搞
- num, err := UserGroupMemberCount("user_id=? and group_id=?", u.Id, ug.Id)
- if err != nil {
- return false, err
- }
-
- return num > 0, nil
- }
-
- func (u *User) CanDo(op string) (bool, error) {
- roles := strings.Fields(u.RolesForDB)
- for i := 0; i < len(roles); i++ {
- if roles[i] == "Admin" {
- return true, nil
- }
- }
-
- return RoleHasOperation(roles, op)
- }
-
- // MustPerm return *User for link program
- func (u *User) MustPerm(op string) *User {
- can, err := u.CanDo(op)
- ierr.Dangerous(err, 500)
-
- if !can {
- ierr.Bomb(403, "forbidden")
- }
-
- return u
- }
|