285 lines
7.5 KiB
Go
285 lines
7.5 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"go-common/app/admin/main/manager/model"
|
|
"go-common/library/ecode"
|
|
"go-common/library/log"
|
|
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Auth return user's auth infomation.
|
|
func (s *Service) Auth(c context.Context, username string) (res *model.Auth, err error) {
|
|
var (
|
|
user model.User
|
|
resp *model.RespPerm
|
|
)
|
|
if err = s.dao.DB().Where("username = ?", username).First(&user).Error; err != nil {
|
|
if err == ecode.NothingFound {
|
|
err = ecode.Int(10001)
|
|
return
|
|
}
|
|
err = errors.Wrapf(err, "s.dao.DB().user.fitst(%s)", username)
|
|
return
|
|
}
|
|
res = &model.Auth{
|
|
UID: user.ID,
|
|
Username: user.Username,
|
|
Nickname: user.Nickname,
|
|
}
|
|
if resp, err = s.permsByMid(c, user.ID); err != nil {
|
|
err = errors.Wrapf(err, "s.permsByMid(%d)", user.ID)
|
|
return
|
|
}
|
|
res.Perms = resp.Res
|
|
res.Admin = resp.Admin
|
|
var aa []*model.AuthAssign
|
|
if result := s.dao.DB().Joins("left join auth_item on auth_item.id=auth_assignment.item_id").Where("auth_assignment.user_id=? and auth_item.type=?", user.ID, model.TypeGroup).Find(&aa); !result.RecordNotFound() {
|
|
res.Assignable = true
|
|
}
|
|
return
|
|
}
|
|
|
|
// Permissions return user's permissions.
|
|
func (s *Service) Permissions(c context.Context, username string) (res *model.Permissions, err error) {
|
|
res = new(model.Permissions)
|
|
var (
|
|
user model.User
|
|
resp *model.RespPerm
|
|
)
|
|
if err = s.dao.DB().Where("username = ?", username).First(&user).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
err = ecode.NothingFound
|
|
}
|
|
log.Error("find user username(%s) error(%v)", username, err)
|
|
return
|
|
}
|
|
res.UID = user.ID
|
|
if resp, err = s.permsByMid(c, user.ID); err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
err = ecode.NothingFound
|
|
}
|
|
log.Error("s.permsByMid(%d) error(%v)", user.ID, err)
|
|
return
|
|
}
|
|
res.Perms = resp.Res
|
|
res.Admin = resp.Admin
|
|
res.Orgs = resp.Groups
|
|
res.Roles = resp.Roles
|
|
return
|
|
}
|
|
|
|
func (s *Service) permsByMid(c context.Context, mid int64) (resp *model.RespPerm, err error) {
|
|
var (
|
|
pointIDs []int64
|
|
as []*model.AuthAssign
|
|
)
|
|
resp = &model.RespPerm{}
|
|
resp.Res = make([]string, 0)
|
|
resp.Groups = make([]*model.AuthOrg, 0)
|
|
resp.Roles = make([]*model.AuthOrg, 0)
|
|
if s.admins[mid] {
|
|
resp.Admin = true
|
|
for _, p := range s.pointList {
|
|
resp.Res = append(resp.Res, p.Data)
|
|
}
|
|
return
|
|
}
|
|
if err = s.dao.DB().Where("user_id = ?", mid).Find(&as).Error; err != nil {
|
|
err = errors.Wrapf(err, "s.dao.DB().user.find(%d)", mid)
|
|
return
|
|
}
|
|
for _, a := range as {
|
|
if info, found := s.orgAuth[a.ItemID]; found { // group & role information
|
|
if info.Type == model.TypeRole {
|
|
resp.Roles = append(resp.Roles, info)
|
|
}
|
|
if info.Type == model.TypeGroup {
|
|
resp.Groups = append(resp.Groups, info)
|
|
}
|
|
}
|
|
if vs, ok := s.roleAuth[a.ItemID]; ok {
|
|
pointIDs = append(pointIDs, vs...)
|
|
continue
|
|
}
|
|
if vs, ok := s.groupAuth[a.ItemID]; ok {
|
|
pointIDs = append(pointIDs, vs...)
|
|
}
|
|
}
|
|
repeat := map[string]byte{}
|
|
for _, id := range pointIDs {
|
|
if assign, ok := s.points[id]; ok {
|
|
l := len(repeat)
|
|
repeat[assign.Data] = 0
|
|
if len(repeat) != l {
|
|
resp.Res = append(resp.Res, assign.Data)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Users get user list.
|
|
func (s *Service) Users(c context.Context, pn, ps int) (res *model.UserPager, err error) {
|
|
res = &model.UserPager{
|
|
Pn: pn,
|
|
Ps: ps,
|
|
}
|
|
var items []*model.User
|
|
if err = s.dao.DB().Where("state = ?", model.UserStateOn).Offset((pn - 1) * ps).Limit(ps).Find(&items).Error; err != nil {
|
|
if err != ecode.NothingFound {
|
|
err = errors.Wrapf(err, "s.dao.DB().users.find(%d,%d)", pn, ps)
|
|
return
|
|
}
|
|
err = nil
|
|
}
|
|
res.Items = items
|
|
return
|
|
}
|
|
|
|
// UsersTotal get user total
|
|
func (s *Service) UsersTotal(c context.Context) (total int64, err error) {
|
|
var item *model.User
|
|
if err = s.dao.DB().Model(&item).Where("state = ?", model.UserStateOn).Count(&total).Error; err != nil {
|
|
err = errors.Wrap(err, "s.dao.DB().users.count")
|
|
}
|
|
return
|
|
}
|
|
|
|
// Heartbeat user activity record
|
|
func (s *Service) Heartbeat(c context.Context, username string) (err error) {
|
|
var user model.User
|
|
if err = s.dao.DB().Where("username = ?", username).First(&user).Error; err != nil {
|
|
if err == ecode.NothingFound {
|
|
err = ecode.Int(10001)
|
|
return
|
|
}
|
|
err = errors.Wrapf(err, "s.dao.DB().user.fitst(%s)", username)
|
|
return
|
|
}
|
|
now := time.Now()
|
|
if err = s.dao.DB().Exec("insert into user_heartbeat (uid,mtime) values (?,?) on duplicate key update mtime=?", user.ID, now, now).Error; err != nil {
|
|
err = errors.Wrapf(err, "s.dao.DB().heartbeat(%d)", user.ID)
|
|
}
|
|
return
|
|
}
|
|
|
|
// loadUnames loads the relation of uid & unames in two maps
|
|
func (s *Service) loadUnames() {
|
|
var (
|
|
err error
|
|
items []*model.User
|
|
unames = make(map[int64]string)
|
|
unicknames = make(map[int64]string)
|
|
uids = make(map[string]int64)
|
|
)
|
|
if err = s.dao.DB().Where("state = ?", model.UserStateOn).Find(&items).Error; err != nil {
|
|
if err != ecode.NothingFound {
|
|
log.Error("LoadUnames Error (%v)", err)
|
|
return
|
|
}
|
|
if len(items) == 0 {
|
|
log.Info("LoadUnames No Active User was found")
|
|
return
|
|
}
|
|
}
|
|
for _, v := range items {
|
|
unames[v.ID] = v.Username
|
|
unicknames[v.ID] = v.Nickname
|
|
uids[v.Username] = v.ID
|
|
}
|
|
if length := len(unames); length != 0 {
|
|
s.userNames = unames
|
|
s.userNicknames = unicknames
|
|
log.Info("LoadUnames Refresh Success! Lines:%d", length)
|
|
}
|
|
if length := len(uids); length != 0 {
|
|
s.userIds = uids
|
|
log.Info("LoadUIds Refresh Success! Lines:%d", length)
|
|
}
|
|
}
|
|
|
|
// regularly load unames
|
|
func (s *Service) loadUnamesproc() {
|
|
var duration time.Duration
|
|
if duration = time.Duration(s.c.UnameTicker); duration == 0 {
|
|
duration = time.Duration(5 * time.Minute) // default value
|
|
}
|
|
ticker := time.NewTicker(duration)
|
|
for range ticker.C {
|
|
s.loadUnames()
|
|
s.loadUdepts()
|
|
}
|
|
ticker.Stop()
|
|
}
|
|
|
|
// Unames treats the param "uids" and give back the unames data
|
|
func (s *Service) Unames(c context.Context, uids []int64) (res map[int64]string) {
|
|
res = make(map[int64]string)
|
|
for _, v := range uids {
|
|
if uname, ok := s.userNames[v]; ok {
|
|
res[v] = uname
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// UIds treats the param "unames" and give back the uids data
|
|
func (s *Service) UIds(c context.Context, unames []string) (res map[string]int64) {
|
|
res = make(map[string]int64)
|
|
for _, v := range unames {
|
|
if uid, ok := s.userIds[v]; ok {
|
|
res[v] = uid
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// loadUdeps loads the relation of uid & department in one map
|
|
func (s *Service) loadUdepts() {
|
|
var (
|
|
items []*model.UserDept
|
|
udepts = make(map[int64]string)
|
|
)
|
|
/**
|
|
select `user`.id,user_department.`name` from `user` LEFT JOIN user_department on `user`.department_id = user_department.id where user_department.`status` = 1 and `user`.state = 0
|
|
*/
|
|
err := s.dao.DB().Table("user").
|
|
Select("user.id, user_department.`name` AS department").
|
|
Joins("LEFT JOIN user_department ON `user`.department_id = user_department.id").
|
|
Where("user_department.`status` = ?", model.UserDepOn).
|
|
Where("state = ?", model.UserStateOn).Find(&items).Error
|
|
if err != nil {
|
|
if err != ecode.NothingFound {
|
|
log.Error("loadUdepts Error (%v)", err)
|
|
return
|
|
}
|
|
if len(items) == 0 {
|
|
log.Info("loadUdepts No Active User was found")
|
|
return
|
|
}
|
|
}
|
|
for _, v := range items {
|
|
udepts[v.ID] = v.Department
|
|
}
|
|
if length := len(udepts); length != 0 {
|
|
s.userDeps = udepts
|
|
log.Info("loadUdepts Refresh Success! Lines:%d", length)
|
|
}
|
|
}
|
|
|
|
// Udepts treats the param "uids" and give back the users' department data
|
|
func (s *Service) Udepts(c context.Context, uids []int64) (res map[int64]string) {
|
|
res = make(map[int64]string)
|
|
for _, v := range uids {
|
|
if udept, ok := s.userDeps[v]; ok {
|
|
res[v] = udept
|
|
}
|
|
}
|
|
return
|
|
}
|