Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add some api about admin #303

Merged
merged 6 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/scripts-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ jobs:
-v "/etc/localtime:/etc/localtime" \
-e MYSQL_ROOT_PASSWORD="openIM123" \
--restart always \
mysql:5.7
mysql:5.7
sleep 30;
- name: start all services
run: |
sudo cp ./config/config.yaml.template ./config/config.yaml
Expand Down
20 changes: 20 additions & 0 deletions internal/api/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ func (o *AdminApi) AdminInfo(c *gin.Context) {
a2r.Call(admin.AdminClient.GetAdminInfo, o.adminClient, c)
}

func (o *AdminApi) ChangeAdminPassword(c *gin.Context) {
a2r.Call(admin.AdminClient.ChangeAdminPassword, o.adminClient, c)
}

func (o *AdminApi) AddAdminAccount(c *gin.Context) {
a2r.Call(admin.AdminClient.AddAdminAccount, o.adminClient, c)
}

func (o *AdminApi) AddUserAccount(c *gin.Context) {
a2r.Call(chat.ChatClient.AddUserAccount, o.chatClient, c)
}

func (o *AdminApi) DelAdminAccount(c *gin.Context) {
a2r.Call(admin.AdminClient.DelAdminAccount, o.adminClient, c)
}

func (o *AdminApi) SearchAdminAccount(c *gin.Context) {
a2r.Call(admin.AdminClient.SearchAdminAccount, o.adminClient, c)
}

func (o *AdminApi) AddDefaultFriend(c *gin.Context) {
a2r.Call(admin.AdminClient.AddDefaultFriend, o.adminClient, c)
}
Expand Down
11 changes: 8 additions & 3 deletions internal/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,14 @@ func NewAdminRoute(router gin.IRouter, discov discoveryregistry.SvcDiscoveryRegi
mw := NewMW(adminConn)
admin := NewAdmin(chatConn, adminConn)
adminRouterGroup := router.Group("/account")
adminRouterGroup.POST("/login", admin.AdminLogin) // 登录
adminRouterGroup.POST("/update", mw.CheckAdmin, admin.AdminUpdateInfo) // 修改信息
adminRouterGroup.POST("/info", mw.CheckAdmin, admin.AdminInfo) // 获取信息
adminRouterGroup.POST("/login", admin.AdminLogin) // 登录
adminRouterGroup.POST("/update", mw.CheckAdmin, admin.AdminUpdateInfo) // 修改信息
adminRouterGroup.POST("/info", mw.CheckAdmin, admin.AdminInfo) // 获取信息
adminRouterGroup.POST("/change_password", mw.CheckAdmin, admin.ChangeAdminPassword) // 修改管理员账号的密码
adminRouterGroup.POST("/add_admin", mw.CheckAdmin, admin.AddAdminAccount) // 添加管理员账号
adminRouterGroup.POST("/add_user", mw.CheckAdmin, admin.AddUserAccount) // 添加用户账号
adminRouterGroup.POST("/del_admin", mw.CheckAdmin, admin.DelAdminAccount) // 删除管理员
adminRouterGroup.POST("/search", mw.CheckAdmin, admin.SearchAdminAccount) // 获取管理员列表

defaultRouter := router.Group("/default", mw.CheckAdmin)
defaultUserRouter := defaultRouter.Group("/user")
Expand Down
141 changes: 139 additions & 2 deletions internal/rpc/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ package admin

import (
"context"

"crypto/md5"
"encoding/hex"
"fmt"
"github.com/OpenIMSDK/chat/pkg/common/db/cache"
"github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
"google.golang.org/grpc"
"math/rand"
"time"

"github.com/OpenIMSDK/chat/pkg/common/config"
"github.com/OpenIMSDK/chat/pkg/common/constant"
Expand Down Expand Up @@ -95,6 +102,99 @@ func (o *adminServer) GetAdminInfo(ctx context.Context, req *admin.GetAdminInfoR
}, nil
}

func (o *adminServer) ChangeAdminPassword(ctx context.Context, req *admin.ChangeAdminPasswordReq) (*admin.ChangeAdminPasswordResp, error) {
user, err := o.Database.GetAdminUserID(ctx, req.UserID)
if err != nil {
return nil, err
}

if user.Password != o.passwordEncryption(req.CurrentPassword) {
return nil, errs.ErrInternalServer.Wrap("password error")
}

if err := o.Database.ChangePassword(ctx, req.UserID, o.passwordEncryption(req.NewPassword)); err != nil {
return nil, err
}
return &admin.ChangeAdminPasswordResp{}, nil
}

func (o *adminServer) AddAdminAccount(ctx context.Context, req *admin.AddAdminAccountReq) (*admin.AddAdminAccountResp, error) {
if err := o.CheckSuperAdmin(ctx); err != nil {
return nil, err
}

_, err := o.Database.GetAdmin(ctx, req.Account)
if err == nil {
return nil, errs.ErrRegisteredAlready.Wrap("the account is registered")
}

adm := &admin2.Admin{
Account: req.Account,
Password: o.passwordEncryption(req.Password),
FaceURL: req.FaceURL,
Nickname: req.Nickname,
UserID: o.genUserID(),
Level: 80,
CreateTime: time.Now(),
}
if err = o.Database.AddAdminAccount(ctx, adm); err != nil {
return nil, err
}
return &admin.AddAdminAccountResp{}, nil
}

func (o *adminServer) DelAdminAccount(ctx context.Context, req *admin.DelAdminAccountReq) (*admin.DelAdminAccountResp, error) {
if err := o.CheckSuperAdmin(ctx); err != nil {
return nil, err
}

if utils.Duplicate(req.UserIDs) {
return nil, errs.ErrArgs.Wrap("user ids is duplicate")
}

for _, userID := range req.UserIDs {
superAdmin, err := o.Database.GetAdminUserID(ctx, userID)
if err != nil {
return nil, err
}
if superAdmin.Level == constant.AdvancedUserLevel {
str := fmt.Sprintf("%s is superAdminID", userID)
return nil, errs.ErrNoPermission.Wrap(str)
}
}

if err := o.Database.DelAdminAccount(ctx, req.UserIDs); err != nil {
return nil, err
}
return &admin.DelAdminAccountResp{}, nil
}

func (o *adminServer) SearchAdminAccount(ctx context.Context, req *admin.SearchAdminAccountReq) (*admin.SearchAdminAccountResp, error) {
defer log.ZDebug(ctx, "return")

if err := o.CheckSuperAdmin(ctx); err != nil {
return nil, err
}

total, adminAccounts, err := o.Database.SearchAdminAccount(ctx, req.Pagination.PageNumber, req.Pagination.ShowNumber)
if err != nil {
return nil, err
}
accounts := make([]*admin.GetAdminInfoResp, 0, len(adminAccounts))
for _, v := range adminAccounts {
temp := &admin.GetAdminInfoResp{
Account: v.Account,
FaceURL: v.FaceURL,
Nickname: v.Nickname,
UserID: v.UserID,
Level: v.Level,
CreateTime: v.CreateTime.Unix(),
}
accounts = append(accounts, temp)
}
return &admin.SearchAdminAccountResp{Total: total, AdminAccounts: accounts}, nil
}

func (o *adminServer) AdminUpdateInfo(ctx context.Context, req *admin.AdminUpdateInfoReq) (*admin.AdminUpdateInfoResp, error) {
userID, err := mctx.CheckAdmin(ctx)
if err != nil {
Expand Down Expand Up @@ -133,7 +233,7 @@ func (o *adminServer) Login(ctx context.Context, req *admin.LoginReq) (*admin.Lo
}
return nil, err
}
if a.Password != req.Password {
if a.Password != o.passwordEncryption(req.Password) {
return nil, eerrs.ErrPassword.Wrap()
}
adminToken, err := o.CreateToken(ctx, &admin.CreateTokenReq{UserID: a.UserID, UserType: constant.AdminUser})
Expand Down Expand Up @@ -168,3 +268,40 @@ func (o *adminServer) ChangePassword(ctx context.Context, req *admin.ChangePassw
}
return &admin.ChangePasswordResp{}, nil
}

func (o *adminServer) genUserID() string {
const l = 10
data := make([]byte, l)
rand.Read(data)
chars := []byte("0123456789")
for i := 0; i < len(data); i++ {
if i == 0 {
data[i] = chars[1:][data[i]%9]
} else {
data[i] = chars[data[i]%10]
}
}
return string(data)
}

func (o *adminServer) passwordEncryption(password string) string {
paswd := md5.Sum([]byte(password))
return hex.EncodeToString(paswd[:])
}

func (o *adminServer) CheckSuperAdmin(ctx context.Context) error {
userID, err := mctx.CheckAdmin(ctx)
if err != nil {
return err
}

adminUser, err := o.Database.GetAdminUserID(ctx, userID)
if err != nil {
return err
}

if adminUser.Level != constant.AdvancedUserLevel {
return errs.ErrNoPermission.Wrap()
}
return nil
}
96 changes: 96 additions & 0 deletions internal/rpc/chat/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ package chat

import (
"context"
"github.com/OpenIMSDK/chat/pkg/common/db/dbutil"
chat2 "github.com/OpenIMSDK/chat/pkg/common/db/table/chat"
constant2 "github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/mcontext"
"strconv"
"time"

"github.com/OpenIMSDK/chat/pkg/common/constant"
"github.com/OpenIMSDK/chat/pkg/common/mctx"
Expand Down Expand Up @@ -113,6 +119,96 @@ func (o *chatSvr) FindUserPublicInfo(ctx context.Context, req *chat.FindUserPubl
}, nil
}

func (o *chatSvr) AddUserAccount(ctx context.Context, req *chat.AddUserAccountReq) (*chat.AddUserAccountResp, error) {
if _, _, err := mctx.Check(ctx); err != nil {
return nil, err
}

if req.User.PhoneNumber != "" {
if req.User.AreaCode[0] != '+' {
req.User.AreaCode = "+" + req.User.AreaCode
}
if _, err := strconv.ParseUint(req.User.AreaCode[1:], 10, 64); err != nil {
return nil, errs.ErrArgs.Wrap("area code must be number")
}
if _, err := strconv.ParseUint(req.User.PhoneNumber, 10, 64); err != nil {
return nil, errs.ErrArgs.Wrap("phone number must be number")
}
_, err := o.Database.TakeAttributeByPhone(ctx, req.User.AreaCode, req.User.PhoneNumber)
if err == nil {
return nil, eerrs.ErrPhoneAlreadyRegister.Wrap()
} else if !o.Database.IsNotFound(err) {
return nil, err
}
}

if req.User.Email != "" {
_, err := o.Database.TakeAttributeByEmail(ctx, req.User.Email)
if err == nil {
return nil, eerrs.ErrEmailAlreadyRegister.Wrap()
} else if !o.Database.IsNotFound(err) {
return nil, err
}
}

if req.User.UserID == "" {
for i := 0; i < 20; i++ {
userID := o.genUserID()
_, err := o.Database.GetUser(ctx, userID)
if err == nil {
continue
} else if dbutil.IsGormNotFound(err) {
req.User.UserID = userID
break
} else {
return nil, err
}
}
if req.User.UserID == "" {
return nil, errs.ErrInternalServer.Wrap("gen user id failed")
}
}

register := &chat2.Register{
UserID: req.User.UserID,
DeviceID: req.DeviceID,
IP: req.Ip,
Platform: constant2.PlatformID2Name[int(req.Platform)],
AccountType: "",
Mode: constant.UserMode,
CreateTime: time.Now(),
}
account := &chat2.Account{
UserID: req.User.UserID,
Password: req.User.Password,
OperatorUserID: mcontext.GetOpUserID(ctx),
ChangeTime: register.CreateTime,
CreateTime: register.CreateTime,
}
attribute := &chat2.Attribute{
UserID: req.User.UserID,
Account: req.User.Account,
PhoneNumber: req.User.PhoneNumber,
AreaCode: req.User.AreaCode,
Email: req.User.Email,
Nickname: req.User.Nickname,
FaceURL: req.User.FaceURL,
Gender: req.User.Gender,
BirthTime: time.UnixMilli(req.User.Birth),
ChangeTime: register.CreateTime,
CreateTime: register.CreateTime,
AllowVibration: constant.DefaultAllowVibration,
AllowBeep: constant.DefaultAllowBeep,
AllowAddFriend: constant.DefaultAllowAddFriend,
}

if err := o.Database.RegisterUser(ctx, register, account, attribute); err != nil {
return nil, err
}

return &chat.AddUserAccountResp{}, nil
}

func (o *chatSvr) SearchUserPublicInfo(ctx context.Context, req *chat.SearchUserPublicInfoReq) (*chat.SearchUserPublicInfoResp, error) {
defer log.ZDebug(ctx, "return")
if _, _, err := mctx.Check(ctx); err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/common/constant/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const (
// user level.
const (
OrdinaryUserLevel = 1
NormalAdmin = 80
AdvancedUserLevel = 100
)

Expand Down
19 changes: 19 additions & 0 deletions pkg/common/db/database/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ type AdminDatabaseInterface interface {
GetAdmin(ctx context.Context, account string) (*table.Admin, error)
GetAdminUserID(ctx context.Context, userID string) (*table.Admin, error)
UpdateAdmin(ctx context.Context, userID string, update map[string]any) error
ChangePassword(ctx context.Context, userID string, newPassword string) error
AddAdminAccount(ctx context.Context, admin *table.Admin) error
DelAdminAccount(ctx context.Context, userIDs []string) error
SearchAdminAccount(ctx context.Context, page, size int32) (uint32, []*table.Admin, error)
CreateApplet(ctx context.Context, applets ...*table.Applet) error
DelApplet(ctx context.Context, appletIDs []string) error
GetApplet(ctx context.Context, appletID string) (*table.Applet, error)
Expand Down Expand Up @@ -121,6 +125,21 @@ func (o *AdminDatabase) UpdateAdmin(ctx context.Context, userID string, update m
return o.admin.Update(ctx, userID, update)
}

func (o *AdminDatabase) ChangePassword(ctx context.Context, userID string, newPassword string) error {
return o.admin.ChangePassword(ctx, userID, newPassword)
}
func (o *AdminDatabase) AddAdminAccount(ctx context.Context, admin *table.Admin) error {
return o.admin.Create(ctx, admin)
}

func (o *AdminDatabase) DelAdminAccount(ctx context.Context, userIDs []string) error {
return o.admin.Delete(ctx, userIDs)
}

func (o *AdminDatabase) SearchAdminAccount(ctx context.Context, page, size int32) (uint32, []*table.Admin, error) {
return o.admin.Search(ctx, page, size)
}

func (o *AdminDatabase) CreateApplet(ctx context.Context, applets ...*table.Applet) error {
return o.applet.Create(ctx, applets...)
}
Expand Down
Loading