package user import ( "OneAuth/cfg" "OneAuth/libs/base" "OneAuth/libs/oerr" "OneAuth/models" //"OneAuth/ws" "encoding/base64" "fmt" "github.com/veypi/OneBD" "github.com/veypi/OneBD/rfc" "github.com/veypi/utils/log" "gorm.io/gorm" "math/rand" "strconv" "time" ) func Router(r OneBD.Router) { pool := OneBD.NewHandlerPool(func() OneBD.Handler { h := &handler{} h.Ignore(rfc.MethodHead, rfc.MethodPost) return h }) r.Set("/", pool, rfc.MethodGet, rfc.MethodPost) // list r.Set("/:user_id", pool, rfc.MethodGet, rfc.MethodPatch, rfc.MethodHead, rfc.MethodDelete) r.Set("/:user_id/role/", userRoleP, rfc.MethodPost) r.Set("/:user_id/role/:role_id", userRoleP, rfc.MethodDelete) //r.WS("/ws", func(m OneBD.Meta) (conn OneBD.WebsocketConn, err error) { //return ws.User.Upgrade(m.ResponseWriter(), m.Request()) //}) } type handler struct { base.ApiHandler User *models.User } // Get get user data func (h *handler) Get() (interface{}, error) { username := h.Meta().Query("username") if username != "" { users := make([]*models.User, 0, 10) err := cfg.DB().Preload("Scores").Preload("Roles.Auths").Where("username LIKE ? OR nickname LIKE ?", "%"+username+"%", "%"+username+"%").Find(&users).Error if err != nil { return nil, err } return users, nil } userID := h.Meta().ParamsInt("user_id") if userID != 0 { user := &models.User{} user.ID = uint(userID) return user, cfg.DB().Where(user).Preload("Scores").Preload("Roles.Auths").Preload("Favorites").First(user).Error } else { users := make([]models.User, 10) skip, err := strconv.Atoi(h.Meta().Query("skip")) if err != nil || skip < 0 { skip = 0 } if err := cfg.DB().Preload("Scores").Preload("Roles.Auths").Offset(skip).Find(&users).Error; err != nil { return nil, err } return users, nil } } // Post register user func (h *handler) Post() (interface{}, error) { if !cfg.CFG.EnableRegister { return nil, oerr.NoAuth.AttachStr("register disabled.") } var userdata = struct { Username string `json:"username"` Password string `json:"password"` Nickname string `json:"nickname"` Phone string `json:"phone"` Email string `json:"email"` Domain string `json:"domain"` Title string `json:"title"` Position string `json:"position"` }{} if err := h.Meta().ReadJson(&userdata); err != nil { return nil, err } pass, err := base64.StdEncoding.DecodeString(userdata.Password) if err != nil { return nil, err } if len(pass) > 32 || len(pass) < 6 { return nil, oerr.PassError } r := rand.New(rand.NewSource(time.Now().UnixNano())) h.User = new(models.User) h.User.Icon = fmt.Sprintf("/media/icon/default/%04d.jpg", r.Intn(230)) h.User.Nickname = userdata.Nickname h.User.Phone = userdata.Phone h.User.Username = userdata.Username h.User.Email = userdata.Email h.User.Position = userdata.Position if err := h.User.UpdateAuth(string(pass)); err != nil { log.HandlerErrs(err) return nil, oerr.ResourceCreatedFailed } tx := cfg.DB().Begin() if err := tx.Create(&h.User).Error; err != nil { tx.Rollback() return nil, oerr.ResourceDuplicated } tx.Commit() return h.User, nil } // Patch update user data func (h *handler) Patch() (interface{}, error) { uid := h.Meta().Params("user_id") opts := struct { Password string `json:"password"` Nickname string `json:"nickname"` Phone string `json:"phone" gorm:"type:varchar(20);unique;default:null" json:",omitempty"` Email string `json:"email" gorm:"type:varchar(50);unique;default:null" json:",omitempty"` Status string `json:"status"` Position string `json:"position"` }{} if err := h.Meta().ReadJson(&opts); err != nil { return nil, err } target := models.User{} if tempID, err := strconv.Atoi(uid); err != nil || tempID <= 0 { return nil, oerr.ApiArgsError.Attach(err) } else { target.ID = uint(tempID) } tx := cfg.DB().Begin() if err := cfg.DB().Where(&target).First(&target).Error; err != nil { return nil, err } if target.ID != h.Payload.ID { return nil, oerr.NoAuth } if len(opts.Password) >= 6 { if err := target.UpdateAuth(opts.Password); err != nil { log.HandlerErrs(err) return nil, oerr.ApiArgsError.AttachStr(err.Error()) } } if opts.Nickname != "" { target.Nickname = opts.Nickname } if opts.Position != "" { target.Position = opts.Position } if opts.Phone != "" { target.Phone = opts.Phone } if opts.Email != "" { target.Email = opts.Email } if opts.Status != "" { target.Status = opts.Status } if err := tx.Updates(&target).Error; err != nil { tx.Rollback() return nil, err } tx.Commit() return nil, nil } // Delete delete user func (h *handler) Delete() (interface{}, error) { // TODO:: return nil, nil } // Head user login func (h *handler) Head() (interface{}, error) { uid := h.Meta().Params("user_id") pass, err := base64.StdEncoding.DecodeString(h.Meta().Query("password")) if err != nil { return nil, oerr.ApiArgsError.Attach(err) } password := string(pass) if len(uid) == 0 || len(password) == 0 { return nil, oerr.ApiArgsError } appID, err := strconv.Atoi(h.Meta().Query("app_id")) if err != nil || appID <= 0 { return nil, oerr.ApiArgsMissing } h.User = new(models.User) uidType := h.Meta().Query("uid_type") switch uidType { case "username": h.User.Username = uid case "phone": h.User.Phone = uid case "email": h.User.Email = uid default: h.User.Username = uid } app := &models.App{} app.ID = uint(appID) err = cfg.DB().Where(app).Find(app).Error if err != nil { return nil, oerr.DBErr.Attach(err) } if err := cfg.DB().Preload("Roles").Where(h.User).First(h.User).Error; err != nil { if err.Error() == gorm.ErrRecordNotFound.Error() { // admin 登录自动注册 if h.User.Username == "admin" { r := rand.New(rand.NewSource(time.Now().UnixNano())) h.User.Icon = fmt.Sprintf("/media/icon/default/%04d.jpg", r.Intn(230)) err = h.User.UpdateAuth(password) if err != nil { return nil, err } role := &models.Role{} role.ID = 1 h.User.Roles = []*models.Role{role} err = cfg.DB().Create(h.User).Error if err != nil { return nil, err } } else { return nil, oerr.AccountNotExist } } else { log.HandlerErrs(err) return nil, oerr.DBErr.Attach(err) } } isAuth, err := h.User.CheckLogin(password) if err != nil || !isAuth { return nil, oerr.PassError.Attach(err) } if h.User.Status == "disabled" { return nil, oerr.DisableLogin } token, err := h.User.GetToken(app.Key, app.ID) if err != nil { log.HandlerErrs(err) return nil, oerr.Unknown.Attach(err) } h.Meta().SetHeader("auth_token", token) log.Info().Msg(h.User.Username + " login") return nil, nil }