From 1bd5e040bf11612b7a5ebc832a4d9242064efa08 Mon Sep 17 00:00:00 2001 From: zijiren233 Date: Sun, 31 Dec 2023 16:28:05 +0800 Subject: [PATCH] Refector: op user room entry --- go.mod | 2 +- go.sum | 2 + internal/bootstrap/rtmp.go | 4 +- internal/op/room.go | 4 - internal/op/rooms.go | 123 +++++++++--------- internal/op/user.go | 6 +- internal/op/users.go | 82 ++++-------- server/handlers/admin.go | 84 ++++++------ server/handlers/movie.go | 68 +++++----- server/handlers/room.go | 32 ++--- server/handlers/root.go | 14 +- server/handlers/user.go | 16 +-- server/handlers/vendors/vendorAlist/list.go | 2 +- server/handlers/vendors/vendorAlist/login.go | 4 +- server/handlers/vendors/vendorAlist/me.go | 4 +- .../vendors/vendorBilibili/bilibili.go | 2 +- .../handlers/vendors/vendorBilibili/login.go | 6 +- server/handlers/vendors/vendorBilibili/me.go | 2 +- server/handlers/vendors/vendorEmby/list.go | 2 +- server/handlers/vendors/vendorEmby/login.go | 4 +- server/handlers/vendors/vendorEmby/me.go | 4 +- server/handlers/websocket.go | 4 +- server/middlewares/auth.go | 49 +++++-- server/oauth2/auth.go | 4 +- server/oauth2/bind.go | 8 +- 25 files changed, 267 insertions(+), 265 deletions(-) diff --git a/go.mod b/go.mod index 9028ef1..c9319d7 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/synctv-org/vendors v0.2.2-0.20231227065102-90bfed7f8a05 github.com/ulule/limiter/v3 v3.11.2 github.com/zencoder/go-dash/v3 v3.0.3 - github.com/zijiren233/gencontainer v0.0.0-20231213075414-f7f4c8261dca + github.com/zijiren233/gencontainer v0.0.0-20231231082035-2008befd9bc8 github.com/zijiren233/go-colorable v0.0.0-20230930131441-997304c961cb github.com/zijiren233/livelib v0.3.0 github.com/zijiren233/stream v0.5.1 diff --git a/go.sum b/go.sum index bc37b74..423b928 100644 --- a/go.sum +++ b/go.sum @@ -366,6 +366,8 @@ github.com/zencoder/go-dash/v3 v3.0.3 h1:xqwGJ2fJCSArwONGx6sY26Z1lxQ7zTURoxdRjCp github.com/zencoder/go-dash/v3 v3.0.3/go.mod h1:30R5bKy1aUYY45yesjtZ9l8trNc2TwNqbS17WVQmCzk= github.com/zijiren233/gencontainer v0.0.0-20231213075414-f7f4c8261dca h1:mYxvu0DgfUFviM0GRqRIwC+nXBGZNV/WLnndTYGSwPA= github.com/zijiren233/gencontainer v0.0.0-20231213075414-f7f4c8261dca/go.mod h1:V5oL7PrZxgisuLCblFWd89Jg99O8vM1n58llcxZ2hDY= +github.com/zijiren233/gencontainer v0.0.0-20231231082035-2008befd9bc8 h1:kQ74VfoQx+9G3H7t8CkrdtMXYRsO5/jV0U5gquZe1Gc= +github.com/zijiren233/gencontainer v0.0.0-20231231082035-2008befd9bc8/go.mod h1:V5oL7PrZxgisuLCblFWd89Jg99O8vM1n58llcxZ2hDY= github.com/zijiren233/go-colorable v0.0.0-20230930131441-997304c961cb h1:0DyOxf/TbbGodHhOVHNoPk+7v/YBJACs22gKpKlatWw= github.com/zijiren233/go-colorable v0.0.0-20230930131441-997304c961cb/go.mod h1:6TCzjDiQ8+5gWZiwsC3pnA5M0vUy2jV2Y7ciHJh729g= github.com/zijiren233/livelib v0.3.0 h1:RLfx6vSUr7wfK6F0VY0aFOBDcT/ljvjQUTOlHEcUlUQ= diff --git a/internal/bootstrap/rtmp.go b/internal/bootstrap/rtmp.go index 7886b27..9de7185 100644 --- a/internal/bootstrap/rtmp.go +++ b/internal/bootstrap/rtmp.go @@ -31,7 +31,7 @@ func auth(ReqAppName, ReqChannelName string, IsPublisher bool) (*rtmps.Channel, log.Errorf("rtmp: get room by id error: %v", err) return nil, err } - return r.GetChannel(channelName) + return r.Value().GetChannel(channelName) } if !settings.RtmpPlayer.Get() { @@ -43,5 +43,5 @@ func auth(ReqAppName, ReqChannelName string, IsPublisher bool) (*rtmps.Channel, log.Errorf("rtmp: get room by id error: %v", err) return nil, err } - return r.GetChannel(ReqChannelName) + return r.Value().GetChannel(ReqChannelName) } diff --git a/internal/op/room.go b/internal/op/room.go index 53d63eb..8831a03 100644 --- a/internal/op/room.go +++ b/internal/op/room.go @@ -235,10 +235,6 @@ func (r *Room) SetRoomStatus(status model.RoomStatus) error { return err } r.Status = status - switch status { - case model.RoomStatusBanned, model.RoomStatusPending: - return CompareAndCloseRoom(r) - } return nil } diff --git a/internal/op/rooms.go b/internal/op/rooms.go index 784cab2..f212ef2 100644 --- a/internal/op/rooms.go +++ b/internal/op/rooms.go @@ -2,6 +2,7 @@ package op import ( "errors" + "fmt" "hash/crc32" "time" @@ -13,11 +14,13 @@ import ( var roomCache *synccache.SyncCache[string, *Room] +type RoomEntry = synccache.Entry[*Room] + func RangeRoomCache(f func(key string, value *synccache.Entry[*Room]) bool) { roomCache.Range(f) } -func CreateRoom(name, password string, maxCount int64, conf ...db.CreateRoomConfig) (*Room, error) { +func CreateRoom(name, password string, maxCount int64, conf ...db.CreateRoomConfig) (*RoomEntry, error) { r, err := db.CreateRoom(name, password, maxCount, conf...) if err != nil { return nil, err @@ -26,17 +29,40 @@ func CreateRoom(name, password string, maxCount int64, conf ...db.CreateRoomConf } var ( - ErrRoomPending = errors.New("room pending, please wait for admin to approve") - ErrRoomBanned = errors.New("room banned") + ErrRoomPending = errors.New("room pending, please wait for admin to approve") + ErrRoomBanned = errors.New("room banned") + ErrRoomCreatorBanned = errors.New("room creator banned") + ErrorRoomCreatorPending = errors.New("room creator pending, please wait for admin to approve") ) -func LoadOrInitRoom(room *model.Room) (*Room, error) { +func checkRoomCreatorStatus(creatorID string) error { + e, err := LoadOrInitUserByID(creatorID) + if err != nil { + return fmt.Errorf("load room creator error: %w", err) + } + + if e.Value().IsBanned() { + return ErrRoomCreatorBanned + } + if e.Value().IsPending() { + return ErrorRoomCreatorPending + } + return nil +} + +func LoadOrInitRoom(room *model.Room) (*RoomEntry, error) { switch room.Status { case model.RoomStatusBanned: return nil, ErrRoomBanned case model.RoomStatusPending: return nil, ErrRoomPending } + + err := checkRoomCreatorStatus(room.CreatorID) + if err != nil { + return nil, err + } + i, _ := roomCache.LoadOrStore(room.ID, &Room{ Room: *room, version: crc32.ChecksumIEEE(room.HashedPassword), @@ -45,7 +71,7 @@ func LoadOrInitRoom(room *model.Room) (*Room, error) { roomID: room.ID, }, }, time.Duration(settings.RoomTTL.Get())*time.Hour) - return i.Value(), nil + return i, nil } func DeleteRoomByID(roomID string) error { @@ -56,12 +82,13 @@ func DeleteRoomByID(roomID string) error { return CloseRoomById(roomID) } -func CompareAndDeleteRoom(room *Room) error { - err := db.DeleteRoomByID(room.ID) +func CompareAndDeleteRoom(room *RoomEntry) error { + err := db.DeleteRoomByID(room.Value().ID) if err != nil { return err } - return CompareAndCloseRoom(room) + CompareAndCloseRoom(room) + return nil } func CloseRoomById(roomID string) error { @@ -72,43 +99,47 @@ func CloseRoomById(roomID string) error { return nil } -func CompareAndCloseRoomEntry(id string, room *synccache.Entry[*Room]) error { - if roomCache.CompareAndDelete(id, room) { +func CompareAndCloseRoom(room *RoomEntry) bool { + if roomCache.CompareAndDelete(room.Value().ID, room) { room.Value().close() + return true } - return nil + return false } -func CompareAndCloseRoom(room *Room) error { - r, loaded := roomCache.Load(room.ID) - if loaded { - if r.Value() != room { - return errors.New("room compare failed") - } - if roomCache.CompareAndDelete(room.ID, r) { - r.Value().close() - } +func LoadRoomByID(id string) (*RoomEntry, error) { + r2, loaded := roomCache.Load(id) + if !loaded { + return nil, errors.New("room not found") } - return nil -} -func LoadRoomByID(id string) (*Room, error) { - r2, loaded := roomCache.Load(id) - if loaded { - r2.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get()) * time.Hour)) - return r2.Value(), nil + err := checkRoomCreatorStatus(r2.Value().CreatorID) + if err != nil { + if errors.Is(err, ErrRoomCreatorBanned) || errors.Is(err, ErrorRoomCreatorPending) { + CompareAndCloseRoom(r2) + } + return nil, err } - return nil, errors.New("room not found") + + r2.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get()) * time.Hour)) + return r2, nil } -func LoadOrInitRoomByID(id string) (*Room, error) { +func LoadOrInitRoomByID(id string) (*RoomEntry, error) { if len(id) != 32 { return nil, errors.New("room id is not 32 bit") } i, loaded := roomCache.Load(id) if loaded { + err := checkRoomCreatorStatus(i.Value().CreatorID) + if err != nil { + if errors.Is(err, ErrRoomCreatorBanned) || errors.Is(err, ErrorRoomCreatorPending) { + CompareAndCloseRoom(i) + } + return nil, err + } i.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get()) * time.Hour)) - return i.Value(), nil + return i, nil } room, err := db.GetRoomByID(id) if err != nil { @@ -125,38 +156,14 @@ func PeopleNum(roomID string) int64 { return 0 } -func GetAllRoomsInCacheWithNoNeedPassword() []*Room { - rooms := make([]*Room, 0) - roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool { - v := value.Value() - if !v.NeedPassword() { - rooms = append(rooms, v) - } - return true - }) - return rooms -} - -func GetAllRoomsInCacheWithoutHidden() []*Room { - rooms := make([]*Room, 0) - roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool { - v := value.Value() - if !v.Settings.Hidden { - rooms = append(rooms, v) - } - return true - }) - return rooms -} - -func SetRoomStatus(roomID string, status model.RoomStatus) error { +func SetRoomStatusByID(roomID string, status model.RoomStatus) error { err := db.SetRoomStatus(roomID, status) if err != nil { return err } - e, loaded := roomCache.LoadAndDelete(roomID) - if loaded { - e.Value().close() + switch status { + case model.RoomStatusBanned, model.RoomStatusPending: + roomCache.Delete(roomID) } return nil } diff --git a/internal/op/user.go b/internal/op/user.go index f419969..ac8f3b6 100644 --- a/internal/op/user.go +++ b/internal/op/user.go @@ -76,7 +76,7 @@ func (u *User) SetPassword(password string) error { return db.SetUserHashedPassword(u.ID, hashedPassword) } -func (u *User) CreateRoom(name, password string, conf ...db.CreateRoomConfig) (*Room, error) { +func (u *User) CreateRoom(name, password string, conf ...db.CreateRoomConfig) (*RoomEntry, error) { if u.IsBanned() { return nil, errors.New("user banned") } @@ -178,8 +178,8 @@ func (u *User) HasRoomPermission(room *Room, permission model.RoomUserPermission return room.HasPermission(u.ID, permission) } -func (u *User) DeleteRoom(room *Room) error { - if !u.HasRoomPermission(room, model.PermissionEditRoom) { +func (u *User) DeleteRoom(room *RoomEntry) error { + if !u.HasRoomPermission(room.Value(), model.PermissionEditRoom) { return model.ErrNoPermission } return CompareAndDeleteRoom(room) diff --git a/internal/op/users.go b/internal/op/users.go index 89982d6..ed19ce0 100644 --- a/internal/op/users.go +++ b/internal/op/users.go @@ -13,30 +13,26 @@ import ( var userCache *synccache.SyncCache[string, *User] +type UserEntry = synccache.Entry[*User] + var ( ErrUserBanned = errors.New("user banned") ErrUserPending = errors.New("user pending, please wait for admin to approve") ) -func LoadOrInitUser(u *model.User) (*User, error) { - switch u.Role { - case model.RoleBanned: - return nil, ErrUserBanned - case model.RolePending: - return nil, ErrUserPending - } +func LoadOrInitUser(u *model.User) (*UserEntry, error) { i, _ := userCache.LoadOrStore(u.ID, &User{ User: *u, version: crc32.ChecksumIEEE(u.HashedPassword), }, time.Hour) - return i.Value(), nil + return i, nil } -func LoadOrInitUserByID(id string) (*User, error) { +func LoadOrInitUserByID(id string) (*UserEntry, error) { u, ok := userCache.Load(id) if ok { u.SetExpiration(time.Now().Add(time.Hour)) - return u.Value(), nil + return u, nil } user, err := db.GetUserByID(id) @@ -47,7 +43,7 @@ func LoadOrInitUserByID(id string) (*User, error) { return LoadOrInitUser(user) } -func LoadUserByUsername(username string) (*User, error) { +func LoadUserByUsername(username string) (*UserEntry, error) { u, err := db.GetUserByUsername(username) if err != nil { return nil, err @@ -56,7 +52,7 @@ func LoadUserByUsername(username string) (*User, error) { return LoadOrInitUser(u) } -func CreateOrLoadUser(username string, password string, conf ...db.CreateUserConfig) (*User, error) { +func CreateOrLoadUser(username string, password string, conf ...db.CreateUserConfig) (*UserEntry, error) { if username == "" { return nil, errors.New("username cannot be empty") } @@ -68,7 +64,7 @@ func CreateOrLoadUser(username string, password string, conf ...db.CreateUserCon return LoadOrInitUser(u) } -func CreateUser(username string, password string, conf ...db.CreateUserConfig) (*User, error) { +func CreateUser(username string, password string, conf ...db.CreateUserConfig) (*UserEntry, error) { if username == "" { return nil, errors.New("username cannot be empty") } @@ -80,7 +76,7 @@ func CreateUser(username string, password string, conf ...db.CreateUserConfig) ( return LoadOrInitUser(u) } -func CreateOrLoadUserWithProvider(username, password string, p provider.OAuth2Provider, pid string, conf ...db.CreateUserConfig) (*User, error) { +func CreateOrLoadUserWithProvider(username, password string, p provider.OAuth2Provider, pid string, conf ...db.CreateUserConfig) (*UserEntry, error) { if username == "" { return nil, errors.New("username cannot be empty") } @@ -92,7 +88,7 @@ func CreateOrLoadUserWithProvider(username, password string, p provider.OAuth2Pr return LoadOrInitUser(u) } -func GetUserByProvider(p provider.OAuth2Provider, pid string) (*User, error) { +func GetUserByProvider(p provider.OAuth2Provider, pid string) (*UserEntry, error) { u, err := db.GetUserByProvider(p, pid) if err != nil { return nil, err @@ -101,8 +97,8 @@ func GetUserByProvider(p provider.OAuth2Provider, pid string) (*User, error) { return LoadOrInitUser(u) } -func CompareAndDeleteUser(user *User) error { - err := db.DeleteUserByID(user.ID) +func CompareAndDeleteUser(user *UserEntry) error { + err := db.DeleteUserByID(user.Value().ID) if err != nil { return err } @@ -121,28 +117,23 @@ func CloseUserById(id string) error { userCache.Delete(id) roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool { if value.Value().CreatorID == id { - CompareAndCloseRoomEntry(key, value) + CompareAndCloseRoom(value) } return true }) return nil } -func CompareAndCloseUser(user *User) error { - u, loaded := userCache.LoadAndDelete(user.ID) - if loaded { - if u.Value() != user { - return errors.New("user compare failed") - } - if userCache.CompareAndDelete(user.ID, u) { - roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool { - if value.Value().CreatorID == user.ID { - CompareAndCloseRoomEntry(key, value) - } - return true - }) - } +func CompareAndCloseUser(user *UserEntry) error { + if !userCache.CompareAndDelete(user.Value().ID, user) { + return nil } + roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool { + if value.Value().CreatorID == user.Value().ID { + CompareAndCloseRoom(value) + } + return true + }) return nil } @@ -151,30 +142,5 @@ func GetUserName(userID string) string { if err != nil { return "" } - return u.Username -} - -func SetRoleByID(userID string, role model.Role) error { - err := db.SetRoleByID(userID, role) - if err != nil { - return err - } - - userCache.Delete(userID) - - switch role { - case model.RoleBanned: - err = db.SetRoomStatusByCreator(userID, model.RoomStatusBanned) - if err != nil { - return err - } - roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool { - if value.Value().CreatorID == userID { - CompareAndCloseRoomEntry(key, value) - } - return true - }) - } - - return nil + return u.Value().Username } diff --git a/server/handlers/admin.go b/server/handlers/admin.go index 34be56f..df625b3 100644 --- a/server/handlers/admin.go +++ b/server/handlers/admin.go @@ -24,7 +24,7 @@ import ( ) func EditAdminSettings(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) req := model.AdminSettingsReq{} if err := model.Decode(ctx, &req); err != nil { @@ -44,7 +44,7 @@ func EditAdminSettings(ctx *gin.Context) { } func AdminSettings(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) group := ctx.Param("group") switch group { case "oauth2": @@ -97,7 +97,7 @@ func AdminSettings(ctx *gin.Context) { } func Users(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) page, pageSize, err := utils.GetPageAndMax(ctx) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) @@ -269,30 +269,30 @@ func ApprovePendingUser(ctx *gin.Context) { } func BanUser(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.UserIDReq{} if err := model.Decode(ctx, &req); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - u, err := db.GetUserByID(req.ID) + u, err := op.LoadOrInitUserByID(req.ID) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - if u.IsRoot() { + if u.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot ban root")) return } - if u.IsAdmin() && !user.IsRoot() { + if u.Value().IsAdmin() && !user.IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot ban admin")) return } - err = op.SetRoleByID(req.ID, dbModel.RoleBanned) + err = u.Value().SetRole(dbModel.RoleBanned) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -302,25 +302,25 @@ func BanUser(ctx *gin.Context) { } func UnBanUser(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) req := model.UserIDReq{} if err := model.Decode(ctx, &req); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - u, err := db.GetUserByID(req.ID) + u, err := op.LoadOrInitUserByID(req.ID) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - if !u.IsBanned() { + if !u.Value().IsBanned() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("user is not banned")) return } - err = op.SetRoleByID(req.ID, dbModel.RoleUser) + err = u.Value().SetRole(dbModel.RoleUser) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -330,7 +330,7 @@ func UnBanUser(ctx *gin.Context) { } func Rooms(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) page, pageSize, err := utils.GetPageAndMax(ctx) if err != nil { @@ -482,7 +482,7 @@ func ApprovePendingRoom(ctx *gin.Context) { } func BanRoom(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.RoomIDReq{} if err := model.Decode(ctx, &req); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) @@ -511,7 +511,7 @@ func BanRoom(ctx *gin.Context) { return } - err = op.SetRoomStatus(req.Id, dbModel.RoomStatusBanned) + err = op.SetRoomStatusByID(req.Id, dbModel.RoomStatusBanned) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -521,7 +521,7 @@ func BanRoom(ctx *gin.Context) { } func UnBanRoom(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) req := model.RoomIDReq{} if err := model.Decode(ctx, &req); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) @@ -539,7 +539,7 @@ func UnBanRoom(ctx *gin.Context) { return } - err = op.SetRoomStatus(req.Id, dbModel.RoomStatusActive) + err = op.SetRoomStatusByID(req.Id, dbModel.RoomStatusActive) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -549,7 +549,7 @@ func UnBanRoom(ctx *gin.Context) { } func AddUser(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.AddUserReq{} if err := model.Decode(ctx, &req); err != nil { @@ -572,7 +572,7 @@ func AddUser(ctx *gin.Context) { } func DeleteUser(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.UserIDReq{} if err := model.Decode(ctx, &req); err != nil { @@ -580,18 +580,18 @@ func DeleteUser(ctx *gin.Context) { return } - u, err := db.GetUserByID(req.ID) + u, err := op.LoadOrInitUserByID(req.ID) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - if u.IsRoot() { + if u.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot delete root")) return } - if u.IsAdmin() && !user.IsRoot() { + if u.Value().IsAdmin() && !user.IsRoot() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("cannot delete admin")) return } @@ -605,7 +605,7 @@ func DeleteUser(ctx *gin.Context) { } func AdminUserPassword(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.AdminUserPasswordReq{} if err := model.Decode(ctx, &req); err != nil { @@ -619,17 +619,17 @@ func AdminUserPassword(ctx *gin.Context) { return } - if u.IsRoot() { + if u.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot change root password")) return } - if u.IsAdmin() && !user.IsRoot() { + if u.Value().IsAdmin() && !user.IsRoot() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("cannot change admin password")) return } - if err := u.SetPassword(req.Password); err != nil { + if err := u.Value().SetPassword(req.Password); err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorStringResp(err.Error())) return } @@ -638,7 +638,7 @@ func AdminUserPassword(ctx *gin.Context) { } func AdminUsername(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.AdminUsernameReq{} if err := model.Decode(ctx, &req); err != nil { @@ -652,17 +652,17 @@ func AdminUsername(ctx *gin.Context) { return } - if u.IsRoot() { + if u.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot change root username")) return } - if u.IsAdmin() && !user.IsRoot() { + if u.Value().IsAdmin() && !user.IsRoot() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("cannot change admin username")) return } - if err := u.SetUsername(req.Username); err != nil { + if err := u.Value().SetUsername(req.Username); err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorStringResp(err.Error())) return } @@ -671,7 +671,7 @@ func AdminUsername(ctx *gin.Context) { } func AdminRoomPassword(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.AdminRoomPasswordReq{} if err := model.Decode(ctx, &req); err != nil { @@ -685,23 +685,23 @@ func AdminRoomPassword(ctx *gin.Context) { return } - creator, err := op.LoadOrInitUserByID(r.CreatorID) + creator, err := op.LoadOrInitUserByID(r.Value().CreatorID) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("room creator not found")) return } - if creator.IsRoot() { + if creator.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot change root room password")) return } - if creator.IsAdmin() && !user.IsRoot() { + if creator.Value().IsAdmin() && !user.IsRoot() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("cannot change admin room password")) return } - if err := r.SetPassword(req.Password); err != nil { + if err := r.Value().SetPassword(req.Password); err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorStringResp(err.Error())) return } @@ -710,7 +710,7 @@ func AdminRoomPassword(ctx *gin.Context) { } func AdminGetVendorBackends(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) conns := vendor.LoadConns() page, size, err := utils.GetPageAndMax(ctx) @@ -752,7 +752,7 @@ func AdminGetVendorBackends(ctx *gin.Context) { } func AdminAddVendorBackend(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) var req model.AddVendorBackendReq if err := model.Decode(ctx, &req); err != nil { @@ -769,7 +769,7 @@ func AdminAddVendorBackend(ctx *gin.Context) { } func AdminDeleteVendorBackends(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) var req model.VendorBackendEndpointsReq if err := model.Decode(ctx, &req); err != nil { @@ -786,7 +786,7 @@ func AdminDeleteVendorBackends(ctx *gin.Context) { } func AdminUpdateVendorBackends(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) var req model.AddVendorBackendReq if err := model.Decode(ctx, &req); err != nil { @@ -803,7 +803,7 @@ func AdminUpdateVendorBackends(ctx *gin.Context) { } func AdminReconnectVendorBackends(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) var req model.VendorBackendEndpointsReq if err := model.Decode(ctx, &req); err != nil { @@ -833,7 +833,7 @@ func AdminReconnectVendorBackends(ctx *gin.Context) { } func AdminEnableVendorBackends(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) var req model.VendorBackendEndpointsReq if err := model.Decode(ctx, &req); err != nil { @@ -850,7 +850,7 @@ func AdminEnableVendorBackends(ctx *gin.Context) { } func AdminDisableVendorBackends(ctx *gin.Context) { - // user := ctx.MustGet("user").(*op.User) + // user := ctx.MustGet("user").(*op.UserEntry) var req model.VendorBackendEndpointsReq if err := model.Decode(ctx, &req); err != nil { diff --git a/server/handlers/movie.go b/server/handlers/movie.go index 2ec9b29..6d80195 100644 --- a/server/handlers/movie.go +++ b/server/handlers/movie.go @@ -40,8 +40,8 @@ func GetPageItems[T any](ctx *gin.Context, items []T) ([]T, error) { } func MovieList(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() page, max, err := utils.GetPageAndMax(ctx) if err != nil { @@ -116,8 +116,8 @@ func genCurrentResp(current *op.Current) *model.CurrentMovieResp { } func CurrentMovie(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() current := room.Current() err := genCurrent(ctx, user, room, current) @@ -132,8 +132,8 @@ func CurrentMovie(ctx *gin.Context) { } func Movies(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() page, max, err := utils.GetPageAndMax(ctx) if err != nil { @@ -164,8 +164,8 @@ func Movies(ctx *gin.Context) { } func PushMovie(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.PushMovieReq{} if err := model.Decode(ctx, &req); err != nil { @@ -195,8 +195,8 @@ func PushMovie(ctx *gin.Context) { } func PushMovies(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.PushMoviesReq{} if err := model.Decode(ctx, &req); err != nil { @@ -238,8 +238,8 @@ func NewPublishKey(ctx *gin.Context) { return } - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.IdReq{} if err := model.Decode(ctx, &req); err != nil { @@ -281,8 +281,8 @@ func NewPublishKey(ctx *gin.Context) { } func EditMovie(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.EditMovieReq{} if err := model.Decode(ctx, &req); err != nil { @@ -311,8 +311,8 @@ func EditMovie(ctx *gin.Context) { } func DelMovie(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.IdsReq{} if err := model.Decode(ctx, &req); err != nil { @@ -342,8 +342,8 @@ func DelMovie(ctx *gin.Context) { } func ClearMovies(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() if err := user.ClearMovies(room); err != nil { if errors.Is(err, dbModel.ErrNoPermission) { @@ -366,8 +366,8 @@ func ClearMovies(ctx *gin.Context) { } func SwapMovie(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.SwapMovieReq{} if err := model.Decode(ctx, &req); err != nil { @@ -392,8 +392,8 @@ func SwapMovie(ctx *gin.Context) { } func ChangeCurrentMovie(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.IdCanEmptyReq{} err := model.Decode(ctx, &req) @@ -443,7 +443,7 @@ func ProxyMovie(ctx *gin.Context) { return } - m, err := room.GetMovieByID(ctx.Param("movieId")) + m, err := room.Value().GetMovieByID(ctx.Param("movieId")) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return @@ -558,8 +558,8 @@ func (e FormatErrNotSupportFileType) Error() string { } func JoinLive(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - // user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + // user := ctx.MustGet("user").(*op.UserEntry) movieId := strings.Trim(ctx.Param("movieId"), "/") fileExt := path.Ext(movieId) @@ -661,7 +661,7 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - mpdC, err := movie.BilibiliCache().SharedMpd.Get(ctx, u.BilibiliCache()) + mpdC, err := movie.BilibiliCache().SharedMpd.Get(ctx, u.Value().BilibiliCache()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -707,7 +707,7 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - srtI, err := movie.BilibiliCache().Subtitle.Get(ctx, u.BilibiliCache()) + srtI, err := movie.BilibiliCache().Subtitle.Get(ctx, u.Value().BilibiliCache()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -732,7 +732,7 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - alistC, err := movie.AlistCache().Get(ctx, u.AlistCache()) + alistC, err := movie.AlistCache().Get(ctx, u.Value().AlistCache()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -787,7 +787,7 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - embyC, err := movie.EmbyCache().Get(ctx, u.EmbyCache()) + embyC, err := movie.EmbyCache().Get(ctx, u.Value().EmbyCache()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -819,7 +819,7 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - embyC, err := movie.EmbyCache().Get(ctx, u.EmbyCache()) + embyC, err := movie.EmbyCache().Get(ctx, u.Value().EmbyCache()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -869,12 +869,12 @@ func parse2VendorMovie(ctx context.Context, user *op.User, room *op.Room, movie if !movie.Base.Proxy { var s string if movie.Base.VendorInfo.Bilibili.Shared { - var u *op.User + var u *op.UserEntry u, err = op.LoadOrInitUserByID(movie.CreatorID) if err != nil { return err } - s, err = opM.BilibiliCache().NoSharedMovie.LoadOrStore(ctx, movie.CreatorID, u.BilibiliCache()) + s, err = opM.BilibiliCache().NoSharedMovie.LoadOrStore(ctx, movie.CreatorID, u.Value().BilibiliCache()) } else { s, err = opM.BilibiliCache().NoSharedMovie.LoadOrStore(ctx, user.ID, user.BilibiliCache()) } @@ -911,7 +911,7 @@ func parse2VendorMovie(ctx context.Context, user *op.User, room *op.Room, movie if err != nil { return err } - data, err := opM.AlistCache().Get(ctx, creator.AlistCache()) + data, err := opM.AlistCache().Get(ctx, creator.Value().AlistCache()) if err != nil { return err } @@ -961,7 +961,7 @@ func parse2VendorMovie(ctx context.Context, user *op.User, room *op.Room, movie if err != nil { return err } - data, err := opM.EmbyCache().Get(ctx, u.EmbyCache()) + data, err := opM.EmbyCache().Get(ctx, u.Value().EmbyCache()) if err != nil { return err } diff --git a/server/handlers/room.go b/server/handlers/room.go index dfc98ce..9ffebcb 100644 --- a/server/handlers/room.go +++ b/server/handlers/room.go @@ -35,7 +35,7 @@ func (e FormatErrNotSupportPosition) Error() string { } func CreateRoom(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() if settings.DisableCreateRoom.Get() && !user.IsAdmin() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("create room is disabled")) @@ -54,14 +54,14 @@ func CreateRoom(ctx *gin.Context) { return } - token, err := middlewares.NewAuthRoomToken(user, room) + token, err := middlewares.NewAuthRoomToken(user, room.Value()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } ctx.JSON(http.StatusCreated, model.NewApiDataResp(gin.H{ - "roomId": room.ID, + "roomId": room.Value().ID, "token": token, })) } @@ -207,7 +207,7 @@ func CheckRoom(ctx *gin.Context) { } func LoginRoom(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.LoginRoomReq{} if err := model.Decode(ctx, &req); err != nil { @@ -225,26 +225,26 @@ func LoginRoom(ctx *gin.Context) { return } - if room.CreatorID != user.ID && !room.CheckPassword(req.Password) { + if room.Value().CreatorID != user.ID && !room.Value().CheckPassword(req.Password) { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("password error")) return } - token, err := middlewares.NewAuthRoomToken(user, room) + token, err := middlewares.NewAuthRoomToken(user, room.Value()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{ - "roomId": room.ID, + "roomId": room.Value().ID, "token": token, })) } func DeleteRoom(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry) + user := ctx.MustGet("user").(*op.UserEntry).Value() if err := user.DeleteRoom(room); err != nil { if errors.Is(err, dbModel.ErrNoPermission) { @@ -259,8 +259,8 @@ func DeleteRoom(ctx *gin.Context) { } func SetRoomPassword(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.SetRoomPasswordReq{} if err := model.Decode(ctx, &req); err != nil { @@ -290,15 +290,15 @@ func SetRoomPassword(ctx *gin.Context) { } func RoomSetting(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - // user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + // user := ctx.MustGet("user").(*op.UserEntry) ctx.JSON(http.StatusOK, model.NewApiDataResp(room.Settings)) } func SetRoomSetting(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) - user := ctx.MustGet("user").(*op.User) + room := ctx.MustGet("room").(*op.RoomEntry).Value() + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.SetRoomSettingReq{} if err := model.Decode(ctx, &req); err != nil { @@ -319,7 +319,7 @@ func SetRoomSetting(ctx *gin.Context) { } func RoomUsers(ctx *gin.Context) { - room := ctx.MustGet("room").(*op.Room) + room := ctx.MustGet("room").(*op.RoomEntry).Value() page, pageSize, err := utils.GetPageAndMax(ctx) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) diff --git a/server/handlers/root.go b/server/handlers/root.go index 97dac0c..d4b1b77 100644 --- a/server/handlers/root.go +++ b/server/handlers/root.go @@ -10,7 +10,7 @@ import ( ) func AddAdmin(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := model.IdReq{} if err := model.Decode(ctx, &req); err != nil { @@ -27,12 +27,12 @@ func AddAdmin(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorStringResp("user not found")) return } - if u.IsAdmin() { + if u.Value().IsAdmin() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("user is already admin")) return } - if err := u.SetRole(dbModel.RoleAdmin); err != nil { + if err := u.Value().SetRole(dbModel.RoleAdmin); err != nil { ctx.AbortWithError(http.StatusInternalServerError, err) return } @@ -41,7 +41,7 @@ func AddAdmin(ctx *gin.Context) { } func DeleteAdmin(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry) req := model.IdReq{} if err := model.Decode(ctx, &req); err != nil { @@ -49,7 +49,7 @@ func DeleteAdmin(ctx *gin.Context) { return } - if req.Id == user.ID { + if req.Id == user.Value().ID { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot remove yourself")) return } @@ -58,12 +58,12 @@ func DeleteAdmin(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorStringResp("user not found")) return } - if u.IsRoot() { + if u.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cannot remove root")) return } - if err := u.SetRole(dbModel.RoleUser); err != nil { + if err := u.Value().SetRole(dbModel.RoleUser); err != nil { ctx.AbortWithError(http.StatusInternalServerError, err) return } diff --git a/server/handlers/user.go b/server/handlers/user.go index 2333519..7f39bef 100644 --- a/server/handlers/user.go +++ b/server/handlers/user.go @@ -16,7 +16,7 @@ import ( ) func Me(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() ctx.JSON(http.StatusOK, model.NewApiDataResp(&model.UserInfoResp{ ID: user.ID, @@ -43,12 +43,12 @@ func LoginUser(ctx *gin.Context) { return } - if ok := user.CheckPassword(req.Password); !ok { + if ok := user.Value().CheckPassword(req.Password); !ok { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("password incorrect")) return } - token, err := middlewares.NewAuthUserToken(user) + token, err := middlewares.NewAuthUserToken(user.Value()) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return @@ -60,7 +60,7 @@ func LoginUser(ctx *gin.Context) { } func LogoutUser(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry) err := op.CompareAndDeleteUser(user) if err != nil { @@ -72,7 +72,7 @@ func LogoutUser(ctx *gin.Context) { } func UserRooms(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() page, pageSize, err := utils.GetPageAndMax(ctx) if err != nil { @@ -132,7 +132,7 @@ func UserRooms(ctx *gin.Context) { } func SetUsername(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() var req model.SetUsernameReq if err := model.Decode(ctx, &req); err != nil { @@ -150,7 +150,7 @@ func SetUsername(ctx *gin.Context) { } func SetUserPassword(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() var req model.SetUserPasswordReq if err := model.Decode(ctx, &req); err != nil { @@ -176,7 +176,7 @@ func SetUserPassword(ctx *gin.Context) { } func UserBindProviders(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() up, err := db.GetBindProviders(user.ID) if err != nil { diff --git a/server/handlers/vendors/vendorAlist/list.go b/server/handlers/vendors/vendorAlist/list.go index 24d8ea5..4324924 100644 --- a/server/handlers/vendors/vendorAlist/list.go +++ b/server/handlers/vendors/vendorAlist/list.go @@ -41,7 +41,7 @@ type AlistFileItem struct { type AlistFSListResp = model.VendorFSListResp[*AlistFileItem] func List(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := ListReq{} if err := model.Decode(ctx, &req); err != nil { diff --git a/server/handlers/vendors/vendorAlist/login.go b/server/handlers/vendors/vendorAlist/login.go index 5ead696..5bb9b9f 100644 --- a/server/handlers/vendors/vendorAlist/login.go +++ b/server/handlers/vendors/vendorAlist/login.go @@ -48,7 +48,7 @@ func (r *LoginReq) Decode(ctx *gin.Context) error { } func Login(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := LoginReq{} if err := model.Decode(ctx, &req); err != nil { @@ -100,7 +100,7 @@ func Login(ctx *gin.Context) { } func Logout(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() var req model.ServerIDReq if err := model.Decode(ctx, &req); err != nil { diff --git a/server/handlers/vendors/vendorAlist/me.go b/server/handlers/vendors/vendorAlist/me.go index cb339be..b75f2b0 100644 --- a/server/handlers/vendors/vendorAlist/me.go +++ b/server/handlers/vendors/vendorAlist/me.go @@ -15,7 +15,7 @@ import ( type AlistMeResp = model.VendorMeResp[*alist.MeResp] func Me(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() serverID := ctx.Query("serverID") if serverID == "" { @@ -55,7 +55,7 @@ type AlistBindsResp []*struct { } func Binds(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() ev, err := db.GetAlistVendors(user.ID) if err != nil { diff --git a/server/handlers/vendors/vendorBilibili/bilibili.go b/server/handlers/vendors/vendorBilibili/bilibili.go index 10e8b4d..29f1b1e 100644 --- a/server/handlers/vendors/vendorBilibili/bilibili.go +++ b/server/handlers/vendors/vendorBilibili/bilibili.go @@ -31,7 +31,7 @@ func (r *ParseReq) Decode(ctx *gin.Context) error { } func Parse(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := ParseReq{} if err := model.Decode(ctx, &req); err != nil { diff --git a/server/handlers/vendors/vendorBilibili/login.go b/server/handlers/vendors/vendorBilibili/login.go index 1449777..77b1a09 100644 --- a/server/handlers/vendors/vendorBilibili/login.go +++ b/server/handlers/vendors/vendorBilibili/login.go @@ -42,7 +42,7 @@ func (r *QRCodeLoginReq) Decode(ctx *gin.Context) error { } func LoginWithQR(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := QRCodeLoginReq{} if err := model.Decode(ctx, &req); err != nil { @@ -186,7 +186,7 @@ func (r *SMSLoginReq) Decode(ctx *gin.Context) error { } func LoginWithSMS(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() var req SMSLoginReq if err := model.Decode(ctx, &req); err != nil { @@ -227,7 +227,7 @@ func LoginWithSMS(ctx *gin.Context) { } func Logout(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() err := db.DeleteBilibiliVendor(user.ID) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) diff --git a/server/handlers/vendors/vendorBilibili/me.go b/server/handlers/vendors/vendorBilibili/me.go index e594a8e..04a2b9f 100644 --- a/server/handlers/vendors/vendorBilibili/me.go +++ b/server/handlers/vendors/vendorBilibili/me.go @@ -16,7 +16,7 @@ import ( type BilibiliMeResp = model.VendorMeResp[*bilibili.UserInfoResp] func Me(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() bucd, err := user.BilibiliCache().Get(ctx) if err != nil { diff --git a/server/handlers/vendors/vendorEmby/list.go b/server/handlers/vendors/vendorEmby/list.go index 2a67804..be2f654 100644 --- a/server/handlers/vendors/vendorEmby/list.go +++ b/server/handlers/vendors/vendorEmby/list.go @@ -38,7 +38,7 @@ type EmbyFileItem struct { type EmbyFSListResp = model.VendorFSListResp[*EmbyFileItem] func List(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := ListReq{} if err := model.Decode(ctx, &req); err != nil { diff --git a/server/handlers/vendors/vendorEmby/login.go b/server/handlers/vendors/vendorEmby/login.go index 3923046..561c633 100644 --- a/server/handlers/vendors/vendorEmby/login.go +++ b/server/handlers/vendors/vendorEmby/login.go @@ -48,7 +48,7 @@ func (r *LoginReq) Decode(ctx *gin.Context) error { } func Login(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() req := LoginReq{} if err := model.Decode(ctx, &req); err != nil { @@ -119,7 +119,7 @@ func Login(ctx *gin.Context) { } func Logout(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() var req model.ServerIDReq if err := model.Decode(ctx, &req); err != nil { diff --git a/server/handlers/vendors/vendorEmby/me.go b/server/handlers/vendors/vendorEmby/me.go index f4052f3..a5ea47f 100644 --- a/server/handlers/vendors/vendorEmby/me.go +++ b/server/handlers/vendors/vendorEmby/me.go @@ -15,7 +15,7 @@ import ( type EmbyMeResp = model.VendorMeResp[*emby.SystemInfoResp] func Me(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() serverID := ctx.Query("serverID") if serverID == "" { @@ -55,7 +55,7 @@ type EmbyBindsResp []*struct { } func Binds(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() ev, err := db.GetEmbyVendors(user.ID) if err != nil { diff --git a/server/handlers/websocket.go b/server/handlers/websocket.go index ed2ef15..d826d5d 100644 --- a/server/handlers/websocket.go +++ b/server/handlers/websocket.go @@ -31,8 +31,10 @@ func NewWebSocketHandler(wss *utils.WebSocket) gin.HandlerFunc { } } -func NewWSMessageHandler(u *op.User, r *op.Room) func(c *websocket.Conn) error { +func NewWSMessageHandler(uE *op.UserEntry, rE *op.RoomEntry) func(c *websocket.Conn) error { return func(c *websocket.Conn) error { + r := rE.Value() + u := uE.Value() client, err := r.NewClient(u, c) if err != nil { log.Errorf("ws: register client error: %v", err) diff --git a/server/middlewares/auth.go b/server/middlewares/auth.go index f6f7c3a..b55df05 100644 --- a/server/middlewares/auth.go +++ b/server/middlewares/auth.go @@ -59,7 +59,7 @@ func authUser(Authorization string) (*AuthClaims, error) { return claims, nil } -func AuthRoom(Authorization string) (*op.User, *op.Room, error) { +func AuthRoom(Authorization string) (*op.UserEntry, *op.RoomEntry, error) { claims, err := authRoom(Authorization) if err != nil { return nil, nil, err @@ -78,7 +78,7 @@ func AuthRoom(Authorization string) (*op.User, *op.Room, error) { return nil, nil, err } - if !u.CheckVersion(claims.UserVersion) { + if !u.Value().CheckVersion(claims.UserVersion) { return nil, nil, ErrAuthExpired } @@ -87,14 +87,14 @@ func AuthRoom(Authorization string) (*op.User, *op.Room, error) { return nil, nil, err } - if !r.CheckVersion(claims.RoomVersion) { + if !r.Value().CheckVersion(claims.RoomVersion) { return nil, nil, ErrAuthExpired } return u, r, nil } -func AuthUser(Authorization string) (*op.User, error) { +func AuthUser(Authorization string) (*op.UserEntry, error) { claims, err := authUser(Authorization) if err != nil { return nil, err @@ -109,7 +109,7 @@ func AuthUser(Authorization string) (*op.User, error) { return nil, err } - if !u.CheckVersion(claims.UserVersion) { + if !u.Value().CheckVersion(claims.UserVersion) { return nil, ErrAuthExpired } @@ -145,6 +145,7 @@ func NewAuthRoomToken(user *op.User, room *op.Room) (string, error) { if user.IsPending() { return "", errors.New("user is pending, need admin to approve") } + if room.IsBanned() { return "", errors.New("room banned") } @@ -179,14 +180,34 @@ func NewAuthRoomToken(user *op.User, room *op.Room) (string, error) { } func AuthRoomMiddleware(ctx *gin.Context) { - user, room, err := AuthRoom(ctx.GetHeader("Authorization")) + userE, roomE, err := AuthRoom(ctx.GetHeader("Authorization")) if err != nil { ctx.AbortWithStatusJSON(http.StatusUnauthorized, model.NewApiErrorResp(err)) return } - ctx.Set("user", user) - ctx.Set("room", room) + user := userE.Value() + if user.IsBanned() { + ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("user banned")) + return + } + if user.IsPending() { + ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("user is pending, need admin to approve")) + return + } + + room := roomE.Value() + if room.IsBanned() { + ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("room banned")) + return + } + if room.IsPending() { + ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("room is pending, need admin to approve")) + return + } + + ctx.Set("user", userE) + ctx.Set("room", roomE) ctx.Next() } @@ -196,6 +217,14 @@ func AuthUserMiddleware(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusUnauthorized, model.NewApiErrorResp(err)) return } + if user.Value().IsBanned() { + ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("user banned")) + return + } + if user.Value().IsPending() { + ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("user is pending, need admin to approve")) + return + } ctx.Set("user", user) ctx.Next() @@ -207,7 +236,7 @@ func AuthAdminMiddleware(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusUnauthorized, model.NewApiErrorResp(err)) return } - if !user.IsAdmin() { + if !user.Value().IsAdmin() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("user is not admin")) return } @@ -222,7 +251,7 @@ func AuthRootMiddleware(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusUnauthorized, model.NewApiErrorResp(err)) return } - if !user.IsRoot() { + if !user.Value().IsRoot() { ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("user is not root")) return } diff --git a/server/oauth2/auth.go b/server/oauth2/auth.go index 0e7a93b..cc8bec5 100644 --- a/server/oauth2/auth.go +++ b/server/oauth2/auth.go @@ -129,7 +129,7 @@ func newAuthFunc(redirect string) stateHandler { return } - var user *op.User + var user *op.UserEntry if settings.DisableUserSignup.Get() || pgs.DisableUserSignup.Get() { user, err = op.GetUserByProvider(pi.Provider(), ui.ProviderUserID) } else { @@ -144,7 +144,7 @@ func newAuthFunc(redirect string) stateHandler { return } - token, err := middlewares.NewAuthUserToken(user) + token, err := middlewares.NewAuthUserToken(user.Value()) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return diff --git a/server/oauth2/bind.go b/server/oauth2/bind.go index 51914cd..53dcec6 100644 --- a/server/oauth2/bind.go +++ b/server/oauth2/bind.go @@ -15,7 +15,7 @@ import ( ) func BindApi(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() pi, err := providers.GetProvider(provider.OAuth2Provider(ctx.Param("type"))) if err != nil { @@ -37,7 +37,7 @@ func BindApi(ctx *gin.Context) { } func UnBindApi(ctx *gin.Context) { - user := ctx.MustGet("user").(*op.User) + user := ctx.MustGet("user").(*op.UserEntry).Value() pi, err := providers.GetProvider(provider.OAuth2Provider(ctx.Param("type"))) if err != nil { @@ -74,13 +74,13 @@ func newBindFunc(userID, redirect string) stateHandler { return } - err = user.BindProvider(pi.Provider(), ui.ProviderUserID) + err = user.Value().BindProvider(pi.Provider(), ui.ProviderUserID) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - token, err := middlewares.NewAuthUserToken(user) + token, err := middlewares.NewAuthUserToken(user.Value()) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return