mirror of https://github.com/synctv-org/synctv
Feat: init permission control
parent
2f604e2132
commit
9b0b9ff1f2
@ -0,0 +1,133 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/synctv-org/synctv/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CreateRoomMemberRelationConfig func(r *model.RoomMember)
|
||||
|
||||
func WithRoomMemberStatus(status model.RoomMemberStatus) CreateRoomMemberRelationConfig {
|
||||
return func(r *model.RoomMember) {
|
||||
r.Status = status
|
||||
}
|
||||
}
|
||||
|
||||
func WithRoomMemberRole(role model.RoomMemberRole) CreateRoomMemberRelationConfig {
|
||||
return func(r *model.RoomMember) {
|
||||
r.Role = role
|
||||
}
|
||||
}
|
||||
|
||||
func WithRoomMemberRelationPermissions(permissions model.RoomMemberPermission) CreateRoomMemberRelationConfig {
|
||||
return func(r *model.RoomMember) {
|
||||
r.Permissions = permissions
|
||||
}
|
||||
}
|
||||
|
||||
func WithRoomMemberAdminPermissions(permissions model.RoomAdminPermission) CreateRoomMemberRelationConfig {
|
||||
return func(r *model.RoomMember) {
|
||||
r.AdminPermissions = permissions
|
||||
}
|
||||
}
|
||||
|
||||
func FirstOrCreateRoomMemberRelation(roomID, userID string, conf ...CreateRoomMemberRelationConfig) (*model.RoomMember, error) {
|
||||
roomMemberRelation := &model.RoomMember{}
|
||||
d := &model.RoomMember{
|
||||
RoomID: roomID,
|
||||
UserID: userID,
|
||||
Role: model.RoomMemberRoleMember,
|
||||
Status: model.RoomMemberStatusPending,
|
||||
Permissions: model.NoPermission,
|
||||
AdminPermissions: model.NoAdminPermission,
|
||||
}
|
||||
for _, c := range conf {
|
||||
c(d)
|
||||
}
|
||||
err := db.Where("room_id = ? AND user_id = ?", roomID, userID).Attrs(d).FirstOrCreate(roomMemberRelation).Error
|
||||
return roomMemberRelation, err
|
||||
}
|
||||
|
||||
func GetRoomMemberRelation(roomID, userID string) (*model.RoomMember, error) {
|
||||
roomMemberRelation := &model.RoomMember{}
|
||||
err := db.Where("room_id = ? AND user_id = ?", roomID, userID).First(roomMemberRelation).Error
|
||||
return roomMemberRelation, HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RoomApprovePendingMember(roomID, userID string) error {
|
||||
roomMember := &model.RoomMember{}
|
||||
err := db.Where("room_id = ? AND user_id = ?", roomID, userID).First(roomMember).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if roomMember.Status != model.RoomMemberStatusPending {
|
||||
return fmt.Errorf("user is not pending")
|
||||
}
|
||||
err = db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ? AND status = ?", roomID, userID, model.RoomMemberStatusPending).Update("status", model.RoomMemberStatusActive).Error
|
||||
if err != nil && gorm.ErrRecordNotFound != err {
|
||||
return fmt.Errorf("update status failed")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func RoomBanMember(roomID, userID string) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("status", model.RoomMemberStatusBanned).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RoomUnbanMember(roomID, userID string) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("status", model.RoomMemberStatusActive).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func SetMemberPermissions(roomID string, userID string, permission model.RoomMemberPermission) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("permissions", permission).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func AddMemberPermissions(roomID string, userID string, permission model.RoomMemberPermission) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("permissions", db.Raw("permissions | ?", permission)).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RemoveMemberPermissions(roomID string, userID string, permission model.RoomMemberPermission) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("permissions", db.Raw("permissions & ?", ^permission)).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
// func GetAllRoomMembersRelationCount(roomID string, scopes ...func(*gorm.DB) *gorm.DB) (int64, error) {
|
||||
// var count int64
|
||||
// err := db.Model(&model.RoomMember{}).Where("room_id = ?", roomID).Scopes(scopes...).Count(&count).Error
|
||||
// return count, err
|
||||
// }
|
||||
|
||||
func RoomSetAdminPermissions(roomID, userID string, permissions model.RoomAdminPermission) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("admin_permissions", permissions).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RoomAddAdminPermissions(roomID, userID string, permissions model.RoomAdminPermission) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("admin_permissions", db.Raw("admin_permissions | ?", permissions)).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RoomRemoveAdminPermissions(roomID, userID string, permissions model.RoomAdminPermission) error {
|
||||
err := db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("admin_permissions", db.Raw("admin_permissions & ?", ^permissions)).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RoomSetAdmin(roomID, userID string, permissions model.RoomAdminPermission) error {
|
||||
return db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Updates(map[string]interface{}{
|
||||
"role": model.RoomMemberRoleAdmin,
|
||||
"admin_permissions": permissions,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func RoomSetMember(roomID, userID string, permissions model.RoomMemberPermission) error {
|
||||
return db.Model(&model.RoomMember{}).Where("room_id = ? AND user_id = ?", roomID, userID).Updates(map[string]interface{}{
|
||||
"role": model.RoomMemberRoleMember,
|
||||
"permissions": permissions,
|
||||
}).Error
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/synctv-org/synctv/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CreateRoomUserRelationConfig func(r *model.RoomUserRelation)
|
||||
|
||||
func WithRoomUserRelationStatus(status model.RoomUserStatus) CreateRoomUserRelationConfig {
|
||||
return func(r *model.RoomUserRelation) {
|
||||
r.Status = status
|
||||
}
|
||||
}
|
||||
|
||||
func WithRoomUserRelationPermissions(permissions model.RoomUserPermission) CreateRoomUserRelationConfig {
|
||||
return func(r *model.RoomUserRelation) {
|
||||
r.Permissions = permissions
|
||||
}
|
||||
}
|
||||
|
||||
func FirstOrCreateRoomUserRelation(roomID, userID string, conf ...CreateRoomUserRelationConfig) (*model.RoomUserRelation, error) {
|
||||
roomUserRelation := &model.RoomUserRelation{}
|
||||
d := &model.RoomUserRelation{
|
||||
RoomID: roomID,
|
||||
UserID: userID,
|
||||
Permissions: model.DefaultPermissions,
|
||||
}
|
||||
for _, c := range conf {
|
||||
c(d)
|
||||
}
|
||||
err := db.Where("room_id = ? AND user_id = ?", roomID, userID).Attrs(d).FirstOrCreate(roomUserRelation).Error
|
||||
return roomUserRelation, err
|
||||
}
|
||||
|
||||
func GetRoomUserRelation(roomID, userID string) (*model.RoomUserRelation, error) {
|
||||
roomUserRelation := &model.RoomUserRelation{}
|
||||
err := db.Where("room_id = ? AND user_id = ?", roomID, userID).First(roomUserRelation).Error
|
||||
return roomUserRelation, HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func SetRoomUserStatus(roomID string, userID string, status model.RoomUserStatus) error {
|
||||
err := db.Model(&model.RoomUserRelation{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("status", status).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func SetUserPermission(roomID string, userID string, permission model.RoomUserPermission) error {
|
||||
err := db.Model(&model.RoomUserRelation{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("permissions", permission).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func AddUserPermission(roomID string, userID string, permission model.RoomUserPermission) error {
|
||||
err := db.Model(&model.RoomUserRelation{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("permissions", db.Raw("permissions | ?", permission)).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func RemoveUserPermission(roomID string, userID string, permission model.RoomUserPermission) error {
|
||||
err := db.Model(&model.RoomUserRelation{}).Where("room_id = ? AND user_id = ?", roomID, userID).Update("permissions", db.Raw("permissions & ?", ^permission)).Error
|
||||
return HandleNotFound(err, "room or user")
|
||||
}
|
||||
|
||||
func GetAllRoomUsersRelation(roomID string, scopes ...func(*gorm.DB) *gorm.DB) []*model.RoomUserRelation {
|
||||
var roomUserRelations []*model.RoomUserRelation
|
||||
db.Where("room_id = ?", roomID).Scopes(scopes...).Find(&roomUserRelations)
|
||||
return roomUserRelations
|
||||
}
|
||||
|
||||
func GetAllRoomUsersRelationCount(roomID string, scopes ...func(*gorm.DB) *gorm.DB) int64 {
|
||||
var count int64
|
||||
db.Model(&model.RoomUserRelation{}).Where("room_id = ?", roomID).Scopes(scopes...).Count(&count)
|
||||
return count
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RoomMemberStatus uint64
|
||||
|
||||
const (
|
||||
RoomMemberStatusUnknown RoomMemberStatus = iota
|
||||
RoomMemberStatusBanned
|
||||
RoomMemberStatusPending
|
||||
RoomMemberStatusActive
|
||||
)
|
||||
|
||||
func (r RoomMemberStatus) String() string {
|
||||
switch r {
|
||||
case RoomMemberStatusBanned:
|
||||
return "banned"
|
||||
case RoomMemberStatusPending:
|
||||
return "pending"
|
||||
case RoomMemberStatusActive:
|
||||
return "active"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (r RoomMemberStatus) IsPending() bool {
|
||||
return r == RoomMemberStatusPending
|
||||
}
|
||||
|
||||
func (r RoomMemberStatus) IsActive() bool {
|
||||
return r == RoomMemberStatusActive
|
||||
}
|
||||
|
||||
func (r RoomMemberStatus) IsBanned() bool {
|
||||
return r == RoomMemberStatusBanned
|
||||
}
|
||||
|
||||
type RoomMemberPermission uint32
|
||||
|
||||
const (
|
||||
PermissionGetMovieList RoomMemberPermission = 2 << iota
|
||||
PermissionAddMovie
|
||||
PermissionDeleteMovie
|
||||
PermissionEditMovie
|
||||
PermissionSetCurrentMovie
|
||||
PermissionSetCurrentStatus
|
||||
PermissionSendChatMessage
|
||||
|
||||
AllPermissions RoomMemberPermission = math.MaxUint32
|
||||
NoPermission RoomMemberPermission = 0
|
||||
DefaultPermissions RoomMemberPermission = PermissionGetMovieList | PermissionSendChatMessage
|
||||
)
|
||||
|
||||
func (p RoomMemberPermission) RemoveAdmin() RoomMemberPermission {
|
||||
return p & DefaultPermissions
|
||||
}
|
||||
|
||||
func (p RoomMemberPermission) Has(permission RoomMemberPermission) bool {
|
||||
return p&permission == permission
|
||||
}
|
||||
|
||||
func (p RoomMemberPermission) Add(permission RoomMemberPermission) RoomMemberPermission {
|
||||
return p | permission
|
||||
}
|
||||
|
||||
func (p RoomMemberPermission) Remove(permission RoomMemberPermission) RoomMemberPermission {
|
||||
return p &^ permission
|
||||
}
|
||||
|
||||
type RoomMemberRole uint
|
||||
|
||||
const (
|
||||
RoomMemberRoleUnknown RoomMemberRole = iota
|
||||
RoomMemberRoleMember
|
||||
RoomMemberRoleAdmin
|
||||
RoomMemberRoleCreator
|
||||
)
|
||||
|
||||
func (r RoomMemberRole) String() string {
|
||||
switch r {
|
||||
case RoomMemberRoleMember:
|
||||
return "member"
|
||||
case RoomMemberRoleAdmin:
|
||||
return "admin"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (r RoomMemberRole) IsCreator() bool {
|
||||
return r == RoomMemberRoleCreator
|
||||
}
|
||||
|
||||
func (r RoomMemberRole) IsAdmin() bool {
|
||||
return r == RoomMemberRoleAdmin || r.IsCreator()
|
||||
}
|
||||
|
||||
func (r RoomMemberRole) IsMember() bool {
|
||||
return r == RoomMemberRoleMember || r.IsAdmin()
|
||||
}
|
||||
|
||||
type RoomAdminPermission uint32
|
||||
|
||||
const (
|
||||
PermissionApprovePendingMember RoomAdminPermission = 1 << iota
|
||||
PermissionBanRoomMember
|
||||
PermissionSetUserPermission
|
||||
PermissionSetRoomSettings
|
||||
PermissionSetRoomPassword
|
||||
PermissionDeleteRoom
|
||||
|
||||
AllAdminPermissions RoomAdminPermission = math.MaxUint32
|
||||
NoAdminPermission RoomAdminPermission = 0
|
||||
DefaultAdminPermissions RoomAdminPermission = PermissionApprovePendingMember |
|
||||
PermissionBanRoomMember |
|
||||
PermissionSetUserPermission |
|
||||
PermissionSetRoomSettings |
|
||||
PermissionSetRoomPassword
|
||||
)
|
||||
|
||||
func (p RoomAdminPermission) Has(permission RoomAdminPermission) bool {
|
||||
return p&permission == permission
|
||||
}
|
||||
|
||||
func (p RoomAdminPermission) Add(permission RoomAdminPermission) RoomAdminPermission {
|
||||
return p | permission
|
||||
}
|
||||
|
||||
func (p RoomAdminPermission) Remove(permission RoomAdminPermission) RoomAdminPermission {
|
||||
return p &^ permission
|
||||
}
|
||||
|
||||
type RoomMember struct {
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
UserID string `gorm:"primarykey;type:char(32)"`
|
||||
RoomID string `gorm:"primarykey;type:char(32)"`
|
||||
Status RoomMemberStatus `gorm:"not null;default:2"`
|
||||
Role RoomMemberRole `gorm:"not null;default:1"`
|
||||
Permissions RoomMemberPermission
|
||||
AdminPermissions RoomAdminPermission
|
||||
}
|
||||
|
||||
var ErrNoPermission = errors.New("no permission")
|
||||
|
||||
func (r *RoomMember) HasPermission(permission RoomMemberPermission) bool {
|
||||
switch r.Status {
|
||||
case RoomMemberStatusActive:
|
||||
return r.Permissions.Has(permission)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RoomMember) HasAdminPermission(permission RoomAdminPermission) bool {
|
||||
switch r.Status {
|
||||
case RoomMemberStatusActive:
|
||||
if !r.Role.IsAdmin() {
|
||||
return false
|
||||
}
|
||||
if r.Role.IsCreator() {
|
||||
return true
|
||||
}
|
||||
return r.AdminPermissions.Has(permission)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RoomUserStatus uint64
|
||||
|
||||
const (
|
||||
RoomUserStatusBanned RoomUserStatus = iota + 1
|
||||
RoomUserStatusPending
|
||||
RoomUserStatusActive
|
||||
)
|
||||
|
||||
func (r RoomUserStatus) String() string {
|
||||
switch r {
|
||||
case RoomUserStatusBanned:
|
||||
return "banned"
|
||||
case RoomUserStatusPending:
|
||||
return "pending"
|
||||
case RoomUserStatusActive:
|
||||
return "active"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
type RoomUserPermission uint64
|
||||
|
||||
const (
|
||||
PermissionAll RoomUserPermission = 0xffffffff
|
||||
PermissionEditRoom RoomUserPermission = 1 << iota
|
||||
PermissionEditUser
|
||||
PermissionCreateMovie
|
||||
PermissionEditCurrent
|
||||
PermissionSendChat
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultPermissions = PermissionCreateMovie | PermissionEditCurrent | PermissionSendChat
|
||||
)
|
||||
|
||||
func (p RoomUserPermission) Has(permission RoomUserPermission) bool {
|
||||
return p&permission == permission
|
||||
}
|
||||
|
||||
type RoomUserRelation struct {
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
UserID string `gorm:"primarykey;type:char(32)"`
|
||||
RoomID string `gorm:"primarykey;type:char(32)"`
|
||||
Status RoomUserStatus `gorm:"not null;default:2"`
|
||||
Permissions RoomUserPermission
|
||||
}
|
||||
|
||||
var ErrNoPermission = errors.New("no permission")
|
||||
|
||||
func (r *RoomUserRelation) HasPermission(permission RoomUserPermission) bool {
|
||||
switch r.Status {
|
||||
case RoomUserStatusActive:
|
||||
return r.Permissions.Has(permission)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,339 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/synctv-org/synctv/internal/db"
|
||||
dbModel "github.com/synctv-org/synctv/internal/model"
|
||||
"github.com/synctv-org/synctv/internal/op"
|
||||
"github.com/synctv-org/synctv/server/model"
|
||||
"github.com/synctv-org/synctv/utils"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func RoomMembers(ctx *gin.Context) {
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
page, pageSize, err := utils.GetPageAndMax(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
var desc = ctx.DefaultQuery("order", "desc") == "desc"
|
||||
|
||||
scopes := []func(db *gorm.DB) *gorm.DB{}
|
||||
|
||||
switch ctx.DefaultQuery("sort", "name") {
|
||||
case "join":
|
||||
if desc {
|
||||
scopes = append(scopes, db.OrderByCreatedAtDesc)
|
||||
} else {
|
||||
scopes = append(scopes, db.OrderByCreatedAtAsc)
|
||||
}
|
||||
case "name":
|
||||
if desc {
|
||||
scopes = append(scopes, db.OrderByDesc("username"))
|
||||
} else {
|
||||
scopes = append(scopes, db.OrderByAsc("username"))
|
||||
}
|
||||
default:
|
||||
log.Errorf("get room users failed: not support sort")
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support sort"))
|
||||
return
|
||||
}
|
||||
|
||||
if keyword := ctx.Query("keyword"); keyword != "" {
|
||||
// search mode, all, name, id
|
||||
switch ctx.DefaultQuery("search", "all") {
|
||||
case "all":
|
||||
ids, err := db.GerUsersIDByIDLike(keyword)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
scopes = append(scopes, db.WhereUsernameLikeOrIDIn(keyword, ids))
|
||||
case "name":
|
||||
scopes = append(scopes, db.WhereUsernameLike(keyword))
|
||||
case "id":
|
||||
ids, err := db.GerUsersIDByIDLike(keyword)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
scopes = append(scopes, db.WhereIDIn(ids))
|
||||
}
|
||||
}
|
||||
scopes = append(scopes, func(db *gorm.DB) *gorm.DB {
|
||||
return db.InnerJoins("JOIN room_members ON users.id = room_members.user_id AND room_members.room_id = ?", room.ID)
|
||||
}, db.PreloadRoomMembers())
|
||||
|
||||
total, err := db.GetAllUserCount(scopes...)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
list, err := db.GetAllUsers(append(scopes, db.Paginate(page, pageSize))...)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
|
||||
"total": total,
|
||||
"list": genRoomMemberListResp(list),
|
||||
}))
|
||||
}
|
||||
|
||||
func RoomAdminMembers(ctx *gin.Context) {
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
page, pageSize, err := utils.GetPageAndMax(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
var desc = ctx.DefaultQuery("order", "desc") == "desc"
|
||||
|
||||
scopes := []func(db *gorm.DB) *gorm.DB{}
|
||||
|
||||
switch ctx.DefaultQuery("status", "active") {
|
||||
case "pending":
|
||||
scopes = append(scopes, db.WhereRoomMemberStatus(dbModel.RoomMemberStatusPending))
|
||||
case "banned":
|
||||
scopes = append(scopes, db.WhereRoomMemberStatus(dbModel.RoomMemberStatusBanned))
|
||||
case "active":
|
||||
scopes = append(scopes, db.WhereRoomMemberStatus(dbModel.RoomMemberStatusActive))
|
||||
}
|
||||
|
||||
switch ctx.DefaultQuery("sort", "name") {
|
||||
case "join":
|
||||
if desc {
|
||||
scopes = append(scopes, db.OrderByCreatedAtDesc)
|
||||
} else {
|
||||
scopes = append(scopes, db.OrderByCreatedAtAsc)
|
||||
}
|
||||
case "name":
|
||||
if desc {
|
||||
scopes = append(scopes, db.OrderByDesc("username"))
|
||||
} else {
|
||||
scopes = append(scopes, db.OrderByAsc("username"))
|
||||
}
|
||||
default:
|
||||
log.Errorf("get room users failed: not support sort")
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support sort"))
|
||||
return
|
||||
}
|
||||
|
||||
if keyword := ctx.Query("keyword"); keyword != "" {
|
||||
// search mode, all, name, id
|
||||
switch ctx.DefaultQuery("search", "all") {
|
||||
case "all":
|
||||
ids, err := db.GerUsersIDByIDLike(keyword)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
scopes = append(scopes, db.WhereUsernameLikeOrIDIn(keyword, ids))
|
||||
case "name":
|
||||
scopes = append(scopes, db.WhereUsernameLike(keyword))
|
||||
case "id":
|
||||
ids, err := db.GerUsersIDByIDLike(keyword)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
scopes = append(scopes, db.WhereIDIn(ids))
|
||||
}
|
||||
}
|
||||
scopes = append(scopes, func(db *gorm.DB) *gorm.DB {
|
||||
return db.InnerJoins("JOIN room_members ON users.id = room_members.user_id AND room_members.room_id = ?", room.ID)
|
||||
}, db.PreloadRoomMembers())
|
||||
|
||||
total, err := db.GetAllUserCount(scopes...)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
list, err := db.GetAllUsers(append(scopes, db.Paginate(page, pageSize))...)
|
||||
if err != nil {
|
||||
log.Errorf("get room users failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
|
||||
"total": total,
|
||||
"list": genRoomMemberListResp(list),
|
||||
}))
|
||||
}
|
||||
|
||||
func RoomAdminApproveMember(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomApproveMemberReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room approve user req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.ApproveRoomPendingMember(room, req.ID)
|
||||
if err != nil {
|
||||
log.Errorf("approve room user failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func RoomAdminBanMember(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomBanMemberReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room ban user req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.BanRoomMember(room, req.ID)
|
||||
if err != nil {
|
||||
log.Errorf("ban room user failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func RoomAdminUnbanMember(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomUnbanMemberReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room unban user req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.UnbanRoomMember(room, req.ID)
|
||||
if err != nil {
|
||||
log.Errorf("unban room user failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func RoomSetMemberPermissions(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomSetMemberPermissionsReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room set user permissions req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.SetMemberPermissions(room, req.ID, req.Permissions)
|
||||
if err != nil {
|
||||
log.Errorf("set room user permissions failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func RoomSetAdmin(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomSetAdminReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room set admin req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.SetRoomAdmin(room, req.ID, req.AdminPermissions)
|
||||
if err != nil {
|
||||
log.Errorf("set room admin failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func RoomSetMember(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomSetMemberReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room set user req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.SetRoomMember(room, req.ID, req.Permissions)
|
||||
if err != nil {
|
||||
log.Errorf("set room user failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func RoomSetAdminPermissions(ctx *gin.Context) {
|
||||
user := ctx.MustGet("user").(*op.UserEntry).Value()
|
||||
room := ctx.MustGet("room").(*op.RoomEntry).Value()
|
||||
log := ctx.MustGet("log").(*logrus.Entry)
|
||||
|
||||
var req model.RoomSetAdminPermissionsReq
|
||||
if err := model.Decode(ctx, &req); err != nil {
|
||||
log.Errorf("decode room set admin permissions req failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
err := user.SetRoomAdminPermissions(room, req.ID, req.AdminPermissions)
|
||||
if err != nil {
|
||||
log.Errorf("set room admin permissions failed: %v", err)
|
||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
dbModel "github.com/synctv-org/synctv/internal/model"
|
||||
)
|
||||
|
||||
type RoomMembersResp struct {
|
||||
UserID string `json:"userId"`
|
||||
Username string `json:"username"`
|
||||
JoinAt int64 `json:"joinAt"`
|
||||
Role dbModel.RoomMemberRole `json:"role"`
|
||||
RoomID string `json:"roomId"`
|
||||
Permissions dbModel.RoomMemberPermission `json:"permissions"`
|
||||
AdminPermissions dbModel.RoomAdminPermission `json:"adminPermissions"`
|
||||
}
|
||||
|
||||
type RoomApproveMemberReq = UserIDReq
|
||||
type RoomBanMemberReq = UserIDReq
|
||||
type RoomUnbanMemberReq = UserIDReq
|
||||
|
||||
type RoomSetMemberPermissionsReq struct {
|
||||
UserIDReq
|
||||
Permissions dbModel.RoomMemberPermission `json:"permissions"`
|
||||
}
|
||||
|
||||
type RoomMeResp struct {
|
||||
UserID string `json:"userId"`
|
||||
RoomID string `json:"roomId"`
|
||||
JoinAt int64 `json:"joinAt"`
|
||||
Role dbModel.RoomMemberRole `json:"role"`
|
||||
Permissions dbModel.RoomMemberPermission `json:"permissions"`
|
||||
AdminPermissions dbModel.RoomAdminPermission `json:"adminPermissions"`
|
||||
}
|
||||
|
||||
type RoomSetAdminReq struct {
|
||||
UserIDReq
|
||||
AdminPermissions dbModel.RoomAdminPermission `json:"adminPermissions"`
|
||||
}
|
||||
|
||||
type RoomSetMemberReq struct {
|
||||
UserIDReq
|
||||
Permissions dbModel.RoomMemberPermission `json:"permissions"`
|
||||
}
|
||||
|
||||
type RoomSetAdminPermissionsReq struct {
|
||||
UserIDReq
|
||||
AdminPermissions dbModel.RoomAdminPermission `json:"adminPermissions"`
|
||||
}
|
Loading…
Reference in New Issue