diff --git a/packages/config/config.go b/packages/config/config.go index 898f830..4a60011 100644 --- a/packages/config/config.go +++ b/packages/config/config.go @@ -13,7 +13,6 @@ var ( Port uint32 = 8080 MaxDirectMsgCache uint32 = 32 MaxHubChannelMsgCache uint32 = 16 - MaxUserHubRoles uint8 = 64 FileStorageBucketName string = "communicator" MaxRequestBytes uint32 = 4 << 10 MaxRequestWithFileBytes uint32 = 1 << 30 @@ -28,8 +27,6 @@ type configFile struct { Port uint32 `toml:"port"` MaxDirectMsgCache uint32 `toml:"max_direct_messages_cache"` MaxHubChannelMsgCache uint32 `toml:"max_hub_channel_msg_cache"` - MaxUserHubRoles uint8 `toml:"max_hub_roles"` - FileStorageBucketName string `toml:"file_storage_bucket_name"` MaxRequestBytes uint32 `toml:"max_request_bytes"` MaxRequestWithFileBytes uint32 `toml:"max_request_with_file_bytes"` MaxRequestWithAvatarBytes uint32 `toml:"max_request_with_avatar_bytes"` diff --git a/packages/httpRequest/get.go b/packages/httpRequest/get.go index d7dd1a6..cc152d9 100644 --- a/packages/httpRequest/get.go +++ b/packages/httpRequest/get.go @@ -103,7 +103,7 @@ func getHubChannelIfValidWithResponseOnFail(ctx context.Context, response http.R return nil, errors.New("invalid channelid") } - if !haveUserPermissionsOnChannel(types.CachedUserCanView, hubUser, channel) { + if !haveHubUserPermissionsOnChannel(types.CachedUserCanView, hubUser, channel) { return nil, errors.New("invalid channelid") } diff --git a/packages/httpRequest/hubs.go b/packages/httpRequest/hubs.go index 167f40e..3381788 100644 --- a/packages/httpRequest/hubs.go +++ b/packages/httpRequest/hubs.go @@ -1,25 +1,61 @@ package httpRequest import ( - "go-socket/packages/Enums/WsEventType" - "go-socket/packages/cache" "net/http" "time" + "go-socket/packages/Enums/WsEventType" + "go-socket/packages/cache" "go-socket/packages/types" "go-socket/packages/wsServer" "github.com/google/uuid" ) -func haveUserPermissionsOnChannel(permissions types.CachedUserPermissions, user *types.HubUser, channel *types.HubChannel) bool { +func haveHubUserPermissionsOnChannel(permissions types.CachedUserPermissions, user *types.HubUser, channel *types.HubChannel) bool { + channel.Mu.RLock() checkAgainst, ok := channel.UsersCachedPermissions[user.OriginalId] - if !ok || (permissions&checkAgainst) == checkAgainst { + channel.Mu.RUnlock() + if !ok || (permissions&checkAgainst) != permissions { return false } return true } +func addHubUserToPermissionCache(hub *types.Hub, user *types.HubUser) { + user.Mu.RLock() + roles := user.Roles + userId := user.OriginalId + user.Mu.RUnlock() + + for _, group := range hub.Groups { + if group == nil { + continue + } + if !roles.HasSameId(group.RolesCanView) { + continue + } + group.UsersCachedPermissions[userId] = types.CachedUserCanView + + for _, channel := range group.Channels { + var perms types.CachedUserPermissions + + if roles.HasSameId(channel.RolesCanView) { + perms |= types.CachedUserCanView + } + if roles.HasSameId(channel.RolesCanReadHistory) { + perms |= types.CachedUserCanReadHistory + } + if roles.HasSameId(channel.RolesCanMessage) { + perms |= types.CachedUserCanMessage + } + channel.Mu.Lock() + channel.UsersCachedPermissions[userId] = perms + channel.Mu.Unlock() + } + } +} + func HandleHubCreate(response http.ResponseWriter, request *http.Request) { if !validCheckWithResponseOnFail(&response, request, normal) { return @@ -93,7 +129,9 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) { channel.RolesCanReadHistory.Add(rootGroup.Id) channel.RolesCanReadHistory.Add(memberRole.Id) channel.UsersCachedPermissions[creator.OriginalId] = types.CachedUserPermissionsAll - hub.Channels[channel.Id] = channel + rootGroup.Channels[channel.Id] = channel + + cache.SaveHub(hub) } func HandleChannelSendMessage(response http.ResponseWriter, request *http.Request) { @@ -119,25 +157,30 @@ func HandleChannelSendMessage(response http.ResponseWriter, request *http.Reques return } - if !haveUserPermissionsOnChannel(types.CachedUserCanMessage, hubUser, channel) { + if !haveHubUserPermissionsOnChannel(types.CachedUserCanMessage, hubUser, channel) { http.Error(response, "cannot send messages here", http.StatusUnauthorized) return } + message := &types.Message{ + Id: uuid.New(), + AttachedFile: "", + Content: msgContent, + Sender: user.Id, + Receiver: channel.Id, + CreatedAt: time.Now(), + } + + channel.Mu.RLock() + recipients := make([]uuid.UUID, 0, len(channel.UsersCachedPermissions)) for id, userCachedPerms := range channel.UsersCachedPermissions { - if !userCachedPerms.CanReadHistory() || id == user.Id { - continue - } - - message := &types.Message{ - Id: uuid.New(), - AttachedFile: "", - Content: msgContent, - Sender: user.Id, - Receiver: channel.Id, - CreatedAt: time.Now(), + if userCachedPerms.CanReadHistory() && id != user.Id { + recipients = append(recipients, id) } + } + channel.Mu.RUnlock() + for _, id := range recipients { targetUser, err := cache.GetUserById(id) if err != nil { // todo Add to postgres in future @@ -149,3 +192,27 @@ func HandleChannelSendMessage(response http.ResponseWriter, request *http.Reques }) } } + +func HandleHubJoin(response http.ResponseWriter, request *http.Request) { + if !validCheckWithResponseOnFail(&response, request, normal) { + return + } + ctx := request.Context() + user, err := getUserByToken(ctx, request.Header.Get("token")) + if err != nil { + http.Error(response, "invalid token", http.StatusBadRequest) + return + } + hub, err := getHubByIdStr(ctx, request.Header.Get("hubid")) + if err != nil { + http.Error(response, "invalid hubid", http.StatusBadRequest) + return + } + + hubUser := types.NewHubUser() + hubUser.OriginalId = user.Id + hubUser.Roles.Add(hub.JoinRole.Id) + hubUser.CreatedAt = time.Now() + hub.Users[hubUser.OriginalId] = hubUser + addHubUserToPermissionCache(hub, hubUser) +} diff --git a/packages/types/types.go b/packages/types/types.go index 5dff847..f182630 100644 --- a/packages/types/types.go +++ b/packages/types/types.go @@ -221,26 +221,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:"-"` - Groups [256]*HubGroup `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:"-"` + Groups [256]*HubGroup `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), } } @@ -282,12 +280,14 @@ type HubGroup struct { Color Rgba `json:"color"` RolesCanView HubBoundRoles `json:"rolesCanView"` UsersCachedPermissions map[uuid.UUID]CachedUserPermissions `json:"-"` + Channels map[uuid.UUID]*HubChannel `json:"channels"` Id uint8 `json:"id"` // Id 0 for unused } func NewHubGroup() *HubGroup { return &HubGroup{ UsersCachedPermissions: make(map[uuid.UUID]CachedUserPermissions), + Channels: make(map[uuid.UUID]*HubChannel), } }