rework of hubs
This commit is contained in:
+55
-283
@@ -2,7 +2,6 @@ package httpRequest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"go-socket/packages/convertions"
|
||||
"maps"
|
||||
"net/http"
|
||||
"slices"
|
||||
@@ -16,7 +15,24 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func haveHubUserPermissionsOnChannel(needed types.CachedUserPermissions, user *types.HubUser, channel *types.HubChannel) bool {
|
||||
func haveHubUserPermission(u *types.HubUser, h *types.Hub, needed types.Permissions) bool {
|
||||
h.Mu.Lock()
|
||||
defer h.Mu.Unlock()
|
||||
for _, role := range h.Roles {
|
||||
if role == nil {
|
||||
continue
|
||||
}
|
||||
if !u.Roles.Has(role.Id) {
|
||||
continue
|
||||
}
|
||||
if (needed & role.Permissions) == needed {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func haveHubUserCachedPermissions(needed types.CachedUserPermissions, user *types.HubUser, channel *types.HubChannel) bool {
|
||||
channel.Mu.RLock()
|
||||
checkAgainst, ok := channel.UsersCachedPermissions[user.OriginalId]
|
||||
channel.Mu.RUnlock()
|
||||
@@ -26,61 +42,6 @@ func haveHubUserPermissionsOnChannel(needed types.CachedUserPermissions, user *t
|
||||
return true
|
||||
}
|
||||
|
||||
func haveUserPermissions(needed types.Permissions, scope uint8, hu *types.HubUser, h *types.Hub) bool {
|
||||
h.Mu.RLock()
|
||||
defer h.Mu.RUnlock()
|
||||
|
||||
for _, role := range h.Roles {
|
||||
if role == nil {
|
||||
continue
|
||||
}
|
||||
if scope != 0 && role.BoundedGroup != scope {
|
||||
continue
|
||||
}
|
||||
if !hu.Roles.Has(role.Id) {
|
||||
continue
|
||||
}
|
||||
if (needed & role.Permissions) != needed {
|
||||
return true
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -132,31 +93,20 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
|
||||
hub.Roles[memberRole.Id] = memberRole
|
||||
creator.Roles.Add(memberRole.Id)
|
||||
|
||||
rootGroup := types.NewHubGroup()
|
||||
rootGroup.Name = "root"
|
||||
rootGroup.Id = uint8(1)
|
||||
rootGroup.Color = types.Rgba{}.GetRandom()
|
||||
rootGroup.CreatedAt = hub.CreatedAt
|
||||
rootGroup.RolesCanView.Add(rootRole.Id)
|
||||
rootGroup.RolesCanView.Add(memberRole.Id)
|
||||
hub.Groups[rootGroup.Id] = rootGroup
|
||||
|
||||
channel := types.NewHubChannel()
|
||||
channel.Name = "main channel"
|
||||
channel.Position = uint8(0)
|
||||
channel.Id = uuid.New()
|
||||
channel.ParentId = rootGroup.Id
|
||||
channel.Description = "The fist channel!"
|
||||
channel.CreatedAt = hub.CreatedAt
|
||||
channel.RolesCanMessage.Add(rootGroup.Id)
|
||||
channel.RolesCanMessage.Add(rootRole.Id)
|
||||
channel.RolesCanMessage.Add(memberRole.Id)
|
||||
channel.RolesCanView.Add(rootGroup.Id)
|
||||
channel.RolesCanView.Add(rootRole.Id)
|
||||
channel.RolesCanView.Add(memberRole.Id)
|
||||
channel.RolesCanReadHistory.Add(rootGroup.Id)
|
||||
channel.RolesCanReadHistory.Add(rootRole.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)
|
||||
}
|
||||
@@ -182,7 +132,6 @@ func HandleHubJoin(response http.ResponseWriter, request *http.Request) {
|
||||
hubUser.Roles.Add(hub.JoinRole.Id)
|
||||
hubUser.CreatedAt = time.Now()
|
||||
hub.Users[hubUser.OriginalId] = hubUser
|
||||
addHubUserToPermissionCache(hub, hubUser)
|
||||
}
|
||||
|
||||
func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
@@ -190,7 +139,7 @@ func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
user, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
user, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -199,7 +148,7 @@ func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if hubUser.IsGlobalMuted {
|
||||
if hubUser.IsMuted {
|
||||
http.Error(response, "muted", http.StatusForbidden)
|
||||
}
|
||||
|
||||
@@ -269,215 +218,38 @@ func HandleGetHubs(response http.ResponseWriter, request *http.Request) {
|
||||
response.Write(converted)
|
||||
}
|
||||
|
||||
func HandleHubPermissionActionCore(
|
||||
response http.ResponseWriter, request *http.Request,
|
||||
takenVarName string, rt requestType, needed types.Permissions,
|
||||
performedAction func(usr *types.HubUser, hub *types.Hub, takenVar *string)) {
|
||||
if !validCheckWithResponseOnFail(&response, request, rt) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !haveHubUserPermission(hubUser, hub, needed) {
|
||||
http.Error(response, "", http.StatusForbidden)
|
||||
}
|
||||
|
||||
var takenVar *string = nil
|
||||
|
||||
if takenVarName != "" {
|
||||
takenVar = new(request.FormValue(takenVarName))
|
||||
}
|
||||
performedAction(hubUser, hub, takenVar)
|
||||
}
|
||||
|
||||
func HandleHubSetName(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
newName := request.FormValue("name")
|
||||
if newName == "" {
|
||||
http.Error(response, "empty name", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !haveUserPermissions(types.PermissionSetHubName, 0, hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Name = newName
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HandleHubSetColor(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
newColor, err := convertions.StringToRgba(request.FormValue("color"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad color", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !haveUserPermissions(types.PermissionSetHubColor, 0, hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Color = newColor
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HandleHubRemove(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !haveUserPermissions(types.PermissionRemoveHub, 0, hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
cache.DeleteHub(hub)
|
||||
}
|
||||
|
||||
func HandleHubSetAllowUserColor(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !haveUserPermissions(types.PermissionSetUserColorAllowed, 0, hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
cache.DeleteHub(hub)
|
||||
}
|
||||
|
||||
func HandleHubRemoveUser(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid targetid", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
_, ok := hub.Users[targetId]
|
||||
if !ok {
|
||||
http.Error(response, "target not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if !haveUserPermissions(types.PermissionRemoveUser, 0, hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Mu.Lock()
|
||||
delete(hub.Users, targetId)
|
||||
hub.Mu.Unlock()
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HandleHubMuteUserToggle(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid targetid", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scope, err := convertions.StringToUint32(request.FormValue("scope"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid scope (set 0 for no scope)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Mu.RLock()
|
||||
target, ok := hub.Users[targetId]
|
||||
hub.Mu.RUnlock()
|
||||
if !ok {
|
||||
http.Error(response, "target not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if !haveUserPermissions(types.PermissionMuteUser, uint8(scope), hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if scope == 0 {
|
||||
target.IsGlobalMuted = !target.IsGlobalMuted
|
||||
} else {
|
||||
hub.Mu.Lock()
|
||||
users := hub.Groups[scope].MutedUsers
|
||||
_, ok = users[targetId]
|
||||
if ok {
|
||||
delete(users, targetId)
|
||||
} else {
|
||||
users[targetId] = struct{}{}
|
||||
HandleHubPermissionActionCore(response, request, "newname", normal, types.PermissionSetHubName, func(usr *types.HubUser, hub *types.Hub, takenVar *string) {
|
||||
newName := *takenVar
|
||||
if newName == "" {
|
||||
http.Error(response, "empty name", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func HandleHubMuteUserToggle(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request.Header.Get("token"), request.FormValue("hubid"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid targetid", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scope, err := convertions.StringToUint32(request.FormValue("scope"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid scope (set 0 for no scope)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Mu.RLock()
|
||||
target, ok := hub.Users[targetId]
|
||||
hub.Mu.RUnlock()
|
||||
if !ok {
|
||||
http.Error(response, "target not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if !haveUserPermissions(types.PermissionMuteUser, uint8(scope), hubUser, hub) {
|
||||
http.Error(response, "no permission", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if scope == 0 {
|
||||
target.IsGlobalMuted = !target.IsGlobalMuted
|
||||
} else {
|
||||
hub.Mu.Lock()
|
||||
users := hub.Groups[scope].MutedUsers
|
||||
_, ok = users[targetId]
|
||||
if ok {
|
||||
delete(users, targetId)
|
||||
} else {
|
||||
users[targetId] = struct{}{}
|
||||
}
|
||||
}
|
||||
hub.Name = newName
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user