From 33794bb671ca938c91dc0a93b4a27a52d728ab17 Mon Sep 17 00:00:00 2001 From: Sisi Date: Fri, 1 May 2026 18:50:46 +0200 Subject: [PATCH] add channel: remove create set name logic --- packages/httpRequest/hubs.go | 126 ++++++++++++++++++++++++++++++++--- packages/types/types.go | 43 ++++++------ 2 files changed, 139 insertions(+), 30 deletions(-) diff --git a/packages/httpRequest/hubs.go b/packages/httpRequest/hubs.go index 44e6389..f6a81f4 100644 --- a/packages/httpRequest/hubs.go +++ b/packages/httpRequest/hubs.go @@ -25,7 +25,7 @@ func haveHubUserPermission(u *types.HubUser, h *types.Hub, needed types.Permissi if role == nil { continue } - if !u.Roles.Has(role.Id) { + if !u.Roles.ContainsRoleId(role.Id) { continue } if (needed&role.Permissions) == needed && role.Id > id { @@ -44,7 +44,7 @@ func hubUserHighestRoleId(u *types.HubUser, h *types.Hub) (id uint8) { if role == nil { continue } - if !u.Roles.Has(role.Id) { + if !u.Roles.ContainsRoleId(role.Id) { continue } if role.Id > id { @@ -54,6 +54,34 @@ func hubUserHighestRoleId(u *types.HubUser, h *types.Hub) (id uint8) { return id } +func updateUserChannelCache(u *types.HubUser, c *types.HubChannel) { + c.Mu.Lock() + defer c.Mu.Unlock() + if u.Roles.DoesIntersect(c.RolesCanView) { + c.UsersCachedPermissions[u.OriginalId] |= types.CachedUserCanView + } else { + c.UsersCachedPermissions[u.OriginalId] &^= types.CachedUserCanView + } + if u.Roles.DoesIntersect(c.RolesCanReadHistory) { + c.UsersCachedPermissions[u.OriginalId] |= types.CachedUserCanReadHistory + } else { + c.UsersCachedPermissions[u.OriginalId] &^= types.CachedUserCanReadHistory + } + if u.Roles.DoesIntersect(c.RolesCanMessage) { + c.UsersCachedPermissions[u.OriginalId] |= types.CachedUserCanMessage + } else { + c.UsersCachedPermissions[u.OriginalId] &^= types.CachedUserCanMessage + } +} + +func updateChannelCache(c *types.HubChannel, h *types.Hub) { + h.Mu.RLock() + defer h.Mu.RUnlock() + for _, u := range h.Users { + updateUserChannelCache(u, c) + } +} + func haveHubUserCachedPermissions(needed types.CachedUserPermissions, user *types.HubUser, channel *types.HubChannel) bool { channel.Mu.RLock() checkAgainst, ok := channel.UsersCachedPermissions[user.OriginalId] @@ -117,7 +145,6 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) { channel := types.NewHubChannel() channel.Name = "main channel" - channel.Position = uint8(0) channel.Id = uuid.New() channel.Description = "The fist channel!" channel.CreatedAt = hub.CreatedAt @@ -128,7 +155,7 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) { channel.RolesCanReadHistory.Add(rootRole.Id) channel.RolesCanReadHistory.Add(memberRole.Id) channel.UsersCachedPermissions[creator.OriginalId] = types.CachedUserPermissionsAll - hub.Channels[channel.Id] = channel + hub.Channels[0] = channel cache.SaveHub(hub) } @@ -534,7 +561,7 @@ func HandleHubRemoveRole(response http.ResponseWriter, request *http.Request) { response.WriteHeader(http.StatusAccepted) } -func HandlePermissionSetRoleName(response http.ResponseWriter, request *http.Request) { +func HandleRoleSetName(response http.ResponseWriter, request *http.Request) { _, hub, _, usedRoleId, ok := hubPermissionContext(response, request, normal, types.PermissionSetRoleName) if !ok { return @@ -565,7 +592,7 @@ func HandlePermissionSetRoleName(response http.ResponseWriter, request *http.Req response.WriteHeader(http.StatusAccepted) } -func HandlePermissionSetRoleColor(response http.ResponseWriter, request *http.Request) { +func HandleRoleSetColor(response http.ResponseWriter, request *http.Request) { _, hub, _, usedRoleId, ok := hubPermissionContext(response, request, normal, types.PermissionSetRoleColor) if !ok { return @@ -596,7 +623,7 @@ func HandlePermissionSetRoleColor(response http.ResponseWriter, request *http.Re response.WriteHeader(http.StatusAccepted) } -func HandlePermissionSetRolePermissions(response http.ResponseWriter, request *http.Request) { +func HandleRoleSetPermissions(response http.ResponseWriter, request *http.Request) { requestor, hub, _, usedRoleId, ok := hubPermissionContext(response, request, normal, types.PermissionSetRolePermissions) if !ok { return @@ -642,7 +669,7 @@ func HandlePermissionSetRolePermissions(response http.ResponseWriter, request *h response.WriteHeader(http.StatusAccepted) } -func HandlePermissionSelfRoleRemove(response http.ResponseWriter, request *http.Request) { +func HandleRoleSelfRemove(response http.ResponseWriter, request *http.Request) { requestor, _, _, usedRoleId, ok := hubPermissionContext(response, request, normal, types.PermissionUserSelfRoleRemove) if !ok { return @@ -650,3 +677,86 @@ func HandlePermissionSelfRoleRemove(response http.ResponseWriter, request *http. requestor.Roles.Remove(usedRoleId) response.WriteHeader(http.StatusAccepted) } + +func HandleChannelCreate(response http.ResponseWriter, request *http.Request) { + requestor, hub, _, usedRoleId, ok := hubPermissionContext(response, request, normal, types.PermissionCreateChannel) + if !ok { + return + } + name := request.FormValue("name") + if name == "" { // TODO think about some restriction to not be too big + http.Error(response, "name empty", http.StatusBadRequest) + return + } + + newHubChannel := types.NewHubChannel() + newHubChannel.Name = name + newHubChannel.Id = uuid.New() + newHubChannel.CreatedAt = time.Now() + + newHubChannel.RolesCanView.Add(usedRoleId) + newHubChannel.RolesCanMessage.Add(usedRoleId) + newHubChannel.RolesCanReadHistory.Add(usedRoleId) + + if requestor.Roles.ContainsRoleId(types.HubBoundRolesMax) { + newHubChannel.RolesCanView.Add(types.HubBoundRolesMax) + newHubChannel.RolesCanMessage.Add(types.HubBoundRolesMax) + newHubChannel.RolesCanReadHistory.Add(types.HubBoundRolesMax) + } + hub.Mu.Lock() + for i, channel := range hub.Channels { + if channel != nil { + continue + } + hub.Channels[i] = newHubChannel + break + } + hub.Mu.Unlock() + + updateChannelCache(newHubChannel, hub) + response.WriteHeader(http.StatusAccepted) +} + +func HandleChannelRemove(response http.ResponseWriter, request *http.Request) { + _, hub, _, _, ok := hubPermissionContext(response, request, normal, types.PermissionRemoveChannel) + if !ok { + return + } + channelId, err := convertions.StringToUint8(request.FormValue("id")) + if err != nil { + http.Error(response, "invalid channel id", http.StatusBadRequest) + return + } + + hub.Mu.Lock() + hub.Channels[channelId] = nil + hub.Mu.Unlock() + response.WriteHeader(http.StatusAccepted) +} +func HandleChannelSetName(response http.ResponseWriter, request *http.Request) { + _, hub, _, _, ok := hubPermissionContext(response, request, normal, types.PermissionSetChannelName) + if !ok { + return + } + newName := request.FormValue("newname") + if newName == "" { + http.Error(response, "newname empty", http.StatusBadRequest) + return + } + channelId, err := convertions.StringToUint8(request.FormValue("id")) + if err != nil { + http.Error(response, "invalid channel id", http.StatusBadRequest) + return + } + + hub.Mu.Lock() + channel := hub.Channels[channelId] + if channel == nil { + http.Error(response, "no such channel", http.StatusNotFound) + return + } + channel.Name = newName + hub.Mu.Unlock() + + response.WriteHeader(http.StatusAccepted) +} diff --git a/packages/types/types.go b/packages/types/types.go index 1bd4a44..18d3fa3 100644 --- a/packages/types/types.go +++ b/packages/types/types.go @@ -167,9 +167,10 @@ const ( PermissionSetRolePermissions // Channel permissions - PermissionAddChannel + PermissionCreateChannel PermissionRemoveChannel PermissionSetChannelName + PermissionSetChannelDescription PermissionSetChannelIcon PermissionSetChannelPermittedVisibleRoles PermissionSetChannelPermittedSendMessageRoles @@ -196,7 +197,7 @@ var permissionRegistry = map[string]Permissions{ "set_role_color": PermissionSetRoleColor, "set_role_permissions": PermissionSetRolePermissions, "self_role_remove": PermissionUserSelfRoleRemove, - "add_channel": PermissionAddChannel, + "add_channel": PermissionCreateChannel, "remove_channel": PermissionRemoveChannel, "set_channel_name": PermissionSetChannelName, "set_channel_icon": PermissionSetChannelIcon, @@ -233,10 +234,10 @@ type HubBoundRoles [3]uint64 const HubBoundRolesMax uint8 = 191 -func (r *HubBoundRoles) Add(bit uint8) { r[bit>>6] |= 1 << (bit & 63) } -func (r *HubBoundRoles) Remove(bit uint8) { r[bit>>6] &^= 1 << (bit & 63) } -func (r *HubBoundRoles) Has(bit uint8) bool { return r[bit>>6]>>(bit&63)&1 == 1 } -func (r *HubBoundRoles) HasSameId(against HubBoundRoles) bool { +func (r *HubBoundRoles) Add(bit uint8) { r[bit>>6] |= 1 << (bit & 63) } +func (r *HubBoundRoles) Remove(bit uint8) { r[bit>>6] &^= 1 << (bit & 63) } +func (r *HubBoundRoles) ContainsRoleId(bit uint8) bool { return r[bit>>6]>>(bit&63)&1 == 1 } +func (r *HubBoundRoles) DoesIntersect(against HubBoundRoles) bool { return against[0]&r[0] != 0 || against[1]&r[1] != 0 || against[2]&r[2] != 0 } @@ -263,25 +264,24 @@ func (p *CachedUserPermissions) ClearCanMessage() { *p &^= CachedUserCanMessage func (p CachedUserPermissions) CanMessage() bool { return p&CachedUserCanMessage != 0 } type Hub struct { - Mu sync.RWMutex `json:"-"` - CreatedAt time.Time `json:"createdAt"` - Roles [256]*HubRole `json:"-"` - Users map[uuid.UUID]*HubUser `json:"-"` - Channels map[uuid.UUID]*HubChannel `json:"-"` - Name string `json:"name"` - IconUrl string `json:"iconUrl"` - BgUrl string `json:"backgroundUrl"` - JoinRole *HubRole `json:"joinRole"` - Id uuid.UUID `json:"id"` - Creator uuid.UUID `json:"creator"` - Color Rgba `json:"color"` - UserColorAllowed bool `json:"userColorAllowed"` + Mu sync.RWMutex `json:"-"` + CreatedAt time.Time `json:"createdAt"` + Roles [256]*HubRole `json:"-"` + Users map[uuid.UUID]*HubUser `json:"-"` + Channels [256]*HubChannel `json:"-"` + Name string `json:"name"` + IconUrl string `json:"iconUrl"` + BgUrl string `json:"backgroundUrl"` + JoinRole *HubRole `json:"joinRole"` + Id uuid.UUID `json:"id"` + Creator uuid.UUID `json:"creator"` + Color Rgba `json:"color"` + UserColorAllowed bool `json:"userColorAllowed"` } func NewHub() *Hub { return &Hub{ - Users: make(map[uuid.UUID]*HubUser), - Channels: make(map[uuid.UUID]*HubChannel), + Users: make(map[uuid.UUID]*HubUser), } } @@ -330,7 +330,6 @@ type HubChannel struct { UsersCachedPermissions map[uuid.UUID]CachedUserPermissions `json:"-"` NextBuffIdx uint32 `json:"-"` Id uuid.UUID `json:"id"` - Position uint8 `json:"position"` HaveOverflowed bool `json:"-"` }