package room import ( "fmt" "sort" "strings" ) type RoomPermission int const ( PermSendChat RoomPermission = iota PermViewChatHistory PermViewMembers PermSubscribe PermWatchRoom PermPublish PermStopStream PermBroadcast PermManageMembers PermAddMembers PermRemoveMembers PermManagePermissions PermManageRoom PermDeleteRoom PermDeleteChatMessages PermControlStream _permCount ) func (p RoomPermission) Bit() uint64 { return 1 << uint(p) } func (p RoomPermission) String() string { switch p { case PermSendChat: return "send_chat" case PermViewChatHistory: return "view_chat_history" case PermViewMembers: return "view_members" case PermSubscribe: return "subscribe" case PermWatchRoom: return "watch_room" case PermPublish: return "publish" case PermStopStream: return "stop_stream" case PermBroadcast: return "broadcast" case PermManageMembers: return "manage_members" case PermAddMembers: return "add_members" case PermRemoveMembers: return "remove_members" case PermManagePermissions: return "manage_permissions" case PermManageRoom: return "manage_room" case PermDeleteRoom: return "delete_room" case PermDeleteChatMessages: return "delete_chat_messages" case PermControlStream: return "control_stream" default: return fmt.Sprintf("perm_%d", int(p)) } } func ParsePermission(s string) (RoomPermission, error) { switch strings.ToLower(strings.TrimSpace(s)) { case "send_chat", "sendchat", "chat", "room:chat": return PermSendChat, nil case "view_chat_history", "viewchathistory": return PermViewChatHistory, nil case "view_members", "viewmembers", "members:view": return PermViewMembers, nil case "subscribe", "room:subscribe": return PermSubscribe, nil case "watch", "watch_room", "room:watch": return PermWatchRoom, nil case "publish", "room:publish": return PermPublish, nil case "stop", "stop_stream", "room:stop": return PermStopStream, nil case "broadcast", "room:broadcast": return PermBroadcast, nil case "manage_members", "managemembers": return PermManageMembers, nil case "add_members", "addmembers": return PermAddMembers, nil case "remove_members", "removemembers", "kick": return PermRemoveMembers, nil case "manage_permissions", "managepermissions": return PermManagePermissions, nil case "manage_room", "manageroom", "room:manage": return PermManageRoom, nil case "delete_room", "deleteroom", "room:delete": return PermDeleteRoom, nil case "delete_chat_messages", "deletechat": return PermDeleteChatMessages, nil case "control_stream", "controlstream": return PermControlStream, nil default: return 0, fmt.Errorf("unknown permission %q", s) } } type PermissionSet uint64 func (s PermissionSet) Has(p RoomPermission) bool { return uint64(s)&p.Bit() != 0 } func (s PermissionSet) HasAll(o PermissionSet) bool { return uint64(s)&uint64(o) == uint64(o) } func (s PermissionSet) HasAny(o PermissionSet) bool { return uint64(s)&uint64(o) != 0 } func (s *PermissionSet) Grant(p RoomPermission) { *s |= PermissionSet(p.Bit()) } func (s *PermissionSet) Revoke(p RoomPermission) { *s &^= PermissionSet(p.Bit()) } func (s PermissionSet) Bits() uint64 { return uint64(s) } func (s PermissionSet) List() []RoomPermission { var out []RoomPermission for i := 0; i < int(_permCount); i++ { p := RoomPermission(i) if s.Has(p) { out = append(out, p) } } return out } func (s PermissionSet) Names() []string { list := s.List() names := make([]string, len(list)) for i, p := range list { names[i] = p.String() } sort.Strings(names) return names } func (s PermissionSet) String() string { return strings.Join(s.Names(), ",") } func AllPermissions() PermissionSet { var all PermissionSet for i := 0; i < int(_permCount); i++ { all.Grant(RoomPermission(i)) } return all } var ( PermAll = AllPermissions() PermNone = PermissionSet(0) PermDefaultCreator = PermAll PermDefaultAdmin = func() PermissionSet { var s PermissionSet s.Grant(PermSendChat) s.Grant(PermViewChatHistory) s.Grant(PermViewMembers) s.Grant(PermSubscribe) s.Grant(PermWatchRoom) s.Grant(PermPublish) s.Grant(PermStopStream) s.Grant(PermBroadcast) s.Grant(PermManageMembers) s.Grant(PermAddMembers) s.Grant(PermRemoveMembers) s.Grant(PermManagePermissions) s.Grant(PermManageRoom) s.Grant(PermDeleteChatMessages) s.Grant(PermControlStream) return s }() PermDefaultMember = func() PermissionSet { var s PermissionSet s.Grant(PermSendChat) s.Grant(PermViewChatHistory) s.Grant(PermViewMembers) s.Grant(PermSubscribe) s.Grant(PermWatchRoom) s.Grant(PermPublish) s.Grant(PermStopStream) return s }() PermDefaultGuest = func() PermissionSet { var s PermissionSet s.Grant(PermViewChatHistory) s.Grant(PermViewMembers) s.Grant(PermSubscribe) s.Grant(PermWatchRoom) return s }() PermGuestAssignable = PermDefaultGuest | func() PermissionSet { var s PermissionSet s.Grant(PermSendChat) return s }() ) func DefaultForRole(r RoomRole) PermissionSet { switch r { case RoleCreator: return PermDefaultCreator case RoleAdmin: return PermDefaultAdmin case RoleMember: return PermDefaultMember case RoleGuest: return PermDefaultGuest default: return PermDefaultGuest } }