mirror of https://github.com/synctv-org/synctv
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			633 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
			
		
		
	
	
			633 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
package op
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"hash/crc32"
 | 
						|
	"sync/atomic"
 | 
						|
 | 
						|
	"github.com/synctv-org/synctv/internal/cache"
 | 
						|
	"github.com/synctv-org/synctv/internal/db"
 | 
						|
	"github.com/synctv-org/synctv/internal/email"
 | 
						|
	"github.com/synctv-org/synctv/internal/model"
 | 
						|
	"github.com/synctv-org/synctv/internal/provider"
 | 
						|
	"github.com/synctv-org/synctv/internal/settings"
 | 
						|
	pb "github.com/synctv-org/synctv/proto/message"
 | 
						|
	"github.com/zijiren233/stream"
 | 
						|
	"golang.org/x/crypto/bcrypt"
 | 
						|
)
 | 
						|
 | 
						|
type User struct {
 | 
						|
	model.User
 | 
						|
	version       uint32
 | 
						|
	alistCache    atomic.Pointer[cache.AlistUserCache]
 | 
						|
	bilibiliCache atomic.Pointer[cache.BilibiliUserCache]
 | 
						|
	embyCache     atomic.Pointer[cache.EmbyUserCache]
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) AlistCache() *cache.AlistUserCache {
 | 
						|
	c := u.alistCache.Load()
 | 
						|
	if c == nil {
 | 
						|
		c = cache.NewAlistUserCache(u.ID)
 | 
						|
		if !u.alistCache.CompareAndSwap(nil, c) {
 | 
						|
			return u.AlistCache()
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return c
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) BilibiliCache() *cache.BilibiliUserCache {
 | 
						|
	c := u.bilibiliCache.Load()
 | 
						|
	if c == nil {
 | 
						|
		c = cache.NewBilibiliUserCache(u.ID)
 | 
						|
		if !u.bilibiliCache.CompareAndSwap(nil, c) {
 | 
						|
			return u.BilibiliCache()
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return c
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) EmbyCache() *cache.EmbyUserCache {
 | 
						|
	c := u.embyCache.Load()
 | 
						|
	if c == nil {
 | 
						|
		c = cache.NewEmbyUserCache(u.ID)
 | 
						|
		if !u.embyCache.CompareAndSwap(nil, c) {
 | 
						|
			return u.EmbyCache()
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return c
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) Version() uint32 {
 | 
						|
	return atomic.LoadUint32(&u.version)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) CheckVersion(version uint32) bool {
 | 
						|
	return atomic.LoadUint32(&u.version) == version
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetPassword(password string) error {
 | 
						|
	if u.IsGuest() {
 | 
						|
		return errors.New("guest cannot set password")
 | 
						|
	}
 | 
						|
	if u.CheckPassword(password) {
 | 
						|
		return errors.New("password is the same")
 | 
						|
	}
 | 
						|
	hashedPassword, err := bcrypt.GenerateFromPassword(stream.StringToBytes(password), bcrypt.DefaultCost)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	atomic.StoreUint32(&u.version, crc32.ChecksumIEEE(hashedPassword))
 | 
						|
	u.HashedPassword = hashedPassword
 | 
						|
	return db.SetUserHashedPassword(u.ID, hashedPassword)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) CreateRoom(name, password string, conf ...db.CreateRoomConfig) (*RoomEntry, error) {
 | 
						|
	if u.IsAdmin() {
 | 
						|
		conf = append(conf, db.WithStatus(model.RoomStatusActive))
 | 
						|
	} else {
 | 
						|
		if password == "" && settings.RoomMustNeedPwd.Get() {
 | 
						|
			return nil, errors.New("room must need password")
 | 
						|
		}
 | 
						|
		if password != "" && settings.RoomMustNoNeedPwd.Get() {
 | 
						|
			return nil, errors.New("room must no need password")
 | 
						|
		}
 | 
						|
		if settings.CreateRoomNeedReview.Get() {
 | 
						|
			conf = append(conf, db.WithStatus(model.RoomStatusPending))
 | 
						|
		} else {
 | 
						|
			conf = append(conf, db.WithStatus(model.RoomStatusActive))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	var maxCount int64
 | 
						|
	if !u.IsAdmin() {
 | 
						|
		maxCount = settings.UserMaxRoomCount.Get()
 | 
						|
	}
 | 
						|
 | 
						|
	return CreateRoom(name, password, maxCount, append(conf, db.WithCreator(&u.User))...)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) NewMovie(movie *model.MovieBase) (*model.Movie, error) {
 | 
						|
	if movie == nil {
 | 
						|
		return nil, errors.New("movie is nil")
 | 
						|
	}
 | 
						|
	switch movie.VendorInfo.Vendor {
 | 
						|
	case model.VendorBilibili:
 | 
						|
		if movie.VendorInfo.Bilibili == nil {
 | 
						|
			return nil, errors.New("bilibili payload is nil")
 | 
						|
		}
 | 
						|
	case model.VendorAlist:
 | 
						|
		if movie.VendorInfo.Alist == nil {
 | 
						|
			return nil, errors.New("alist payload is nil")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return &model.Movie{
 | 
						|
		MovieBase: *movie,
 | 
						|
		CreatorID: u.ID,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) AddRoomMovie(room *Room, movie *model.MovieBase) (*model.Movie, error) {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionAddMovie) {
 | 
						|
		return nil, model.ErrNoPermission
 | 
						|
	}
 | 
						|
	m, err := u.NewMovie(movie)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	err = room.AddMovie(m)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return m, room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) NewMovies(movies []*model.MovieBase) ([]*model.Movie, error) {
 | 
						|
	var ms = make([]*model.Movie, len(movies))
 | 
						|
	for i, m := range movies {
 | 
						|
		movie, err := u.NewMovie(m)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		ms[i] = movie
 | 
						|
	}
 | 
						|
	return ms, nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) AddRoomMovies(room *Room, movies []*model.MovieBase) ([]*model.Movie, error) {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionAddMovie) {
 | 
						|
		return nil, model.ErrNoPermission
 | 
						|
	}
 | 
						|
	m, err := u.NewMovies(movies)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	err = room.AddMovies(m)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return m, room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsRoot() bool {
 | 
						|
	return u.Role == model.RoleRoot
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsAdmin() bool {
 | 
						|
	return u.Role == model.RoleAdmin || u.IsRoot()
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsBanned() bool {
 | 
						|
	return u.Role == model.RoleBanned
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsPending() bool {
 | 
						|
	return u.Role == model.RolePending
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsGuest() bool {
 | 
						|
	return u.ID == db.GuestUserID
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) HasRoomPermission(room *Room, permission model.RoomMemberPermission) bool {
 | 
						|
	if u.IsAdmin() {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	return room.HasPermission(u.ID, permission)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) HasRoomAdminPermission(room *Room, permission model.RoomAdminPermission) bool {
 | 
						|
	if u.IsAdmin() {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	if u.IsGuest() {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return room.HasAdminPermission(u.ID, permission)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsRoomAdmin(room *Room) bool {
 | 
						|
	return room.IsAdmin(u.ID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) IsRoomCreator(room *Room) bool {
 | 
						|
	return room.IsCreator(u.ID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) DeleteRoom(room *RoomEntry) error {
 | 
						|
	if !u.HasRoomAdminPermission(room.Value(), model.PermissionDeleteRoom) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return CompareAndDeleteRoom(room)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomPassword(room *Room, password string) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetRoomPassword) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if !u.IsAdmin() {
 | 
						|
		if password == "" && settings.RoomMustNeedPwd.Get() {
 | 
						|
			return errors.New("room must need password")
 | 
						|
		}
 | 
						|
		if password != "" && settings.RoomMustNoNeedPwd.Get() {
 | 
						|
			return errors.New("room must no need password")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return room.SetPassword(password)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetUserRole() error {
 | 
						|
	if u.IsGuest() {
 | 
						|
		return errors.New("cannot set guest role")
 | 
						|
	}
 | 
						|
	if err := db.SetUserRoleByID(u.ID); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Role = model.RoleUser
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetAdminRole() error {
 | 
						|
	if u.IsGuest() {
 | 
						|
		return errors.New("guest cannot be admin")
 | 
						|
	}
 | 
						|
	if err := db.SetAdminRoleByID(u.ID); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Role = model.RoleAdmin
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRootRole() error {
 | 
						|
	if u.IsGuest() {
 | 
						|
		return errors.New("guest cannot be root")
 | 
						|
	}
 | 
						|
	if err := db.SetRootRoleByID(u.ID); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Role = model.RoleRoot
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) Ban() error {
 | 
						|
	if u.IsGuest() {
 | 
						|
		return errors.New("guest cannot be banned")
 | 
						|
	}
 | 
						|
	if err := db.BanUserByID(u.ID); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Role = model.RoleBanned
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) Unban() error {
 | 
						|
	if err := db.UnbanUserByID(u.ID); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Role = model.RoleUser
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetUsername(username string) error {
 | 
						|
	if err := db.SetUsernameByID(u.ID, username); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Username = username
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) UpdateRoomMovie(room *Room, movieID string, movie *model.MovieBase) error {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionEditMovie) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	err := room.UpdateMovie(movieID, movie)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomSettings(room *Room, setting *model.RoomSettings) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetRoomSettings) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.SetSettings(setting)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) UpdateRoomSettings(room *Room, settings map[string]interface{}) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetRoomSettings) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.UpdateSettings(settings)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) DeleteRoomMovieByID(room *Room, movieID string) error {
 | 
						|
	m, err := room.GetMovieByID(movieID)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if m.Movie.CreatorID != u.ID && !u.HasRoomPermission(room, model.PermissionDeleteMovie) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.DeleteMovieByID(movieID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) DeleteRoomMoviesByID(room *Room, movieIDs []string) error {
 | 
						|
	for _, id := range movieIDs {
 | 
						|
		m, err := room.GetMovieByID(id)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		if m.Movie.CreatorID != u.ID && !u.HasRoomPermission(room, model.PermissionDeleteMovie) {
 | 
						|
			return model.ErrNoPermission
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if err := room.DeleteMoviesByID(movieIDs); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) ClearRoomMovies(room *Room) error {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionDeleteMovie) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	err := room.ClearMovies()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) ClearRoomMoviesByParentID(room *Room, parentID string) error {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionDeleteMovie) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	err := room.ClearMoviesByParentID(parentID)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SwapRoomMoviePositions(room *Room, id1, id2 string) error {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionEditMovie) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	err := room.SwapMoviePositions(id1, id2)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_MOVIES_CHANGED,
 | 
						|
		MoviesChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomCurrentMovie(room *Room, movieID string, subPath string, play bool) error {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionSetCurrentMovie) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	err := room.SetCurrentMovie(movieID, subPath, play)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return room.Broadcast(&pb.ElementMessage{
 | 
						|
		Type: pb.ElementMessageType_CURRENT_CHANGED,
 | 
						|
		CurrentChanged: &pb.Sender{
 | 
						|
			Username: u.Username,
 | 
						|
			Userid:   u.ID,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) BindProvider(p provider.OAuth2Provider, pid string) error {
 | 
						|
	err := db.BindProvider(u.ID, p, pid)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SendBindCaptchaEmail(e string) error {
 | 
						|
	return email.SendBindCaptchaEmail(u.ID, e)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) VerifyBindCaptchaEmail(e, captcha string) (bool, error) {
 | 
						|
	return email.VerifyBindCaptchaEmail(u.ID, e, captcha)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) BindEmail(e string) error {
 | 
						|
	err := db.BindEmail(u.ID, e)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Email = model.EmptyNullString(e)
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) UnbindEmail() error {
 | 
						|
	err := db.UnbindEmail(u.ID)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	u.Email = ""
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
var ErrEmailUnbound = errors.New("email unbound")
 | 
						|
 | 
						|
func (u *User) SendTestEmail() error {
 | 
						|
	if u.Email == "" {
 | 
						|
		return ErrEmailUnbound
 | 
						|
	}
 | 
						|
 | 
						|
	return email.SendTestEmail(u.Username, u.Email.String())
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SendRetrievePasswordCaptchaEmail(host string) error {
 | 
						|
	if u.Email == "" {
 | 
						|
		return ErrEmailUnbound
 | 
						|
	}
 | 
						|
 | 
						|
	return email.SendRetrievePasswordCaptchaEmail(u.ID, u.Email.String(), host)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) VerifyRetrievePasswordCaptchaEmail(e, captcha string) (bool, error) {
 | 
						|
	if u.Email.String() != e {
 | 
						|
		return false, errors.New("email has changed, please resend the captcha email")
 | 
						|
	}
 | 
						|
	return email.VerifyRetrievePasswordCaptchaEmail(u.ID, e, captcha)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) GetRoomMoviesWithPage(room *Room, page, pageSize int, parentID string) ([]*model.Movie, int64, error) {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionGetMovieList) {
 | 
						|
		return nil, 0, model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.GetMoviesWithPage(page, pageSize, parentID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomCurrentSeekRate(room *Room, seek, rate, timeDiff float64) (*Status, error) {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionSetCurrentStatus) {
 | 
						|
		return nil, model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.SetCurrentSeekRate(seek, rate, timeDiff), nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomCurrentStatus(room *Room, playing bool, seek, rate, timeDiff float64) (*Status, error) {
 | 
						|
	if !u.HasRoomPermission(room, model.PermissionSetCurrentStatus) {
 | 
						|
		return nil, model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.SetCurrentStatus(playing, seek, rate, timeDiff), nil
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) BanRoomMember(room *Room, userID string) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionBanRoomMember) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if u.ID == userID {
 | 
						|
		return errors.New("cannot ban yourself")
 | 
						|
	}
 | 
						|
	if room.IsAdmin(userID) && !u.IsRoomCreator(room) {
 | 
						|
		return errors.New("cannot ban admin")
 | 
						|
	}
 | 
						|
	return room.BanMember(userID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) UnbanRoomMember(room *Room, userID string) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionBanRoomMember) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if u.ID == userID {
 | 
						|
		return errors.New("cannot unban yourself")
 | 
						|
	}
 | 
						|
	return room.UnbanMember(userID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetMemberPermissions(room *Room, userID string, permissions model.RoomMemberPermission) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetUserPermission) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if room.IsAdmin(userID) && !u.IsRoomCreator(room) {
 | 
						|
		return errors.New("cannot set admin permissions")
 | 
						|
	}
 | 
						|
	return room.SetMemberPermissions(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) AddMemberPermissions(room *Room, userID string, permissions model.RoomMemberPermission) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetUserPermission) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if room.IsAdmin(userID) && !u.IsRoomCreator(room) {
 | 
						|
		return errors.New("cannot add admin permissions")
 | 
						|
	}
 | 
						|
	return room.AddMemberPermissions(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) RemoveMemberPermissions(room *Room, userID string, permissions model.RoomMemberPermission) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetUserPermission) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if room.IsAdmin(userID) && !u.IsRoomCreator(room) {
 | 
						|
		return errors.New("cannot remove admin permissions")
 | 
						|
	}
 | 
						|
	return room.RemoveMemberPermissions(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) ResetMemberPermissions(room *Room, userID string) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionSetUserPermission) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	if room.IsAdmin(userID) && !u.IsRoomCreator(room) {
 | 
						|
		return errors.New("cannot reset admin permissions")
 | 
						|
	}
 | 
						|
	return room.ResetMemberPermissions(userID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) ApproveRoomPendingMember(room *Room, userID string) error {
 | 
						|
	if !u.HasRoomAdminPermission(room, model.PermissionApprovePendingMember) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.ApprovePendingMember(userID)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomAdmin(room *Room, userID string, permissions model.RoomAdminPermission) error {
 | 
						|
	if !u.IsRoomCreator(room) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.SetAdmin(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomMember(room *Room, userID string, permissions model.RoomMemberPermission) error {
 | 
						|
	if !u.IsRoomCreator(room) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.SetMember(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) SetRoomAdminPermissions(room *Room, userID string, permissions model.RoomAdminPermission) error {
 | 
						|
	if !u.IsRoomCreator(room) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.SetAdminPermissions(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) AddRoomAdminPermissions(room *Room, userID string, permissions model.RoomAdminPermission) error {
 | 
						|
	if !u.IsRoomCreator(room) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.AddAdminPermissions(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) RemoveRoomAdminPermissions(room *Room, userID string, permissions model.RoomAdminPermission) error {
 | 
						|
	if !u.IsRoomCreator(room) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.RemoveAdminPermissions(userID, permissions)
 | 
						|
}
 | 
						|
 | 
						|
func (u *User) ResetRoomAdminPermissions(room *Room, userID string) error {
 | 
						|
	if !u.IsRoomCreator(room) {
 | 
						|
		return model.ErrNoPermission
 | 
						|
	}
 | 
						|
	return room.ResetAdminPermissions(userID)
 | 
						|
}
 |