fix hub bugs, add channel role permission endpoints
Covers: snake_case param renames, mutex RLock/Unlock mismatches, user.Hubs keyed by hub.Id, hub color using new_name, DELETE params sent as query, delete(target.Hubs, hub.Id), root/member role Id swap, and the three new PATCH /hub/channel/roles/* handlers.
This commit is contained in:
+298
-159
@@ -3,9 +3,7 @@ package httpRequest
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"maps"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -57,25 +55,24 @@ func hubUserHighestRoleId(u *types.HubUser, h *types.Hub) (id uint8) {
|
||||
func updateChannelCacheForSpecUserAndChannel(u *types.HubUser, c *types.HubChannel) {
|
||||
c.Mu.Lock()
|
||||
defer c.Mu.Unlock()
|
||||
|
||||
if u == nil {
|
||||
delete(c.UsersCachedPermissions, c.Id)
|
||||
return
|
||||
}
|
||||
if u.Roles.DoesIntersect(c.RolesCanView) {
|
||||
c.UsersCachedPermissions[u.OriginalId] |= types.CachedUserCanView
|
||||
} else {
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,17 +88,23 @@ func updateChannelCacheForSpecUser(u *types.HubUser, h *types.Hub) {
|
||||
h.Mu.RLock()
|
||||
defer h.Mu.RUnlock()
|
||||
for _, c := range h.Channels {
|
||||
if c == nil {
|
||||
continue
|
||||
}
|
||||
updateChannelCacheForSpecUserAndChannel(u, c)
|
||||
}
|
||||
}
|
||||
|
||||
func updateChannelCacheForSpecRole(r *types.HubRole, h *types.Hub) {
|
||||
h.Mu.Lock()
|
||||
defer h.Mu.Unlock()
|
||||
h.Mu.RLock()
|
||||
var users []*types.HubUser
|
||||
for _, u := range h.Users {
|
||||
if !u.Roles.ContainsRoleId(r.Id) {
|
||||
continue
|
||||
if u.Roles.ContainsRoleId(r.Id) {
|
||||
users = append(users, u)
|
||||
}
|
||||
}
|
||||
h.Mu.RUnlock()
|
||||
for _, u := range users {
|
||||
updateChannelCacheForSpecUser(u, h)
|
||||
}
|
||||
}
|
||||
@@ -128,7 +131,7 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
hubName := request.FormValue("hubname")
|
||||
hubName := request.FormValue("hub_name")
|
||||
if hubName == "" {
|
||||
http.Error(response, "hub name is required", http.StatusBadRequest)
|
||||
return
|
||||
@@ -140,7 +143,7 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
|
||||
hub.Id = uuid.New()
|
||||
hub.Creator = user.Id
|
||||
hub.CreatedAt = time.Now()
|
||||
user.Hubs[user.Id] = hub
|
||||
user.Hubs[hub.Id] = hub
|
||||
|
||||
creator := types.NewHubUser()
|
||||
creator.OriginalId = user.Id
|
||||
@@ -148,7 +151,7 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
|
||||
hub.Users[creator.OriginalId] = creator
|
||||
|
||||
rootRole := &types.HubRole{
|
||||
Id: uint8(0),
|
||||
Id: types.HubBoundRolesMax,
|
||||
Permissions: types.PermissionAll(),
|
||||
Name: "root",
|
||||
Color: types.RandomRgba(),
|
||||
@@ -158,7 +161,7 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
|
||||
creator.Roles.Add(rootRole.Id)
|
||||
|
||||
memberRole := &types.HubRole{
|
||||
Id: types.HubBoundRolesMax,
|
||||
Id: uint8(0),
|
||||
Name: "member",
|
||||
Color: types.RandomRgba(),
|
||||
CreatedAt: hub.CreatedAt,
|
||||
@@ -179,9 +182,13 @@ 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[0] = channel
|
||||
channel.Position = 0
|
||||
hub.Channels[channel.Id] = channel
|
||||
|
||||
cache.SaveHub(hub)
|
||||
|
||||
response.WriteHeader(http.StatusCreated)
|
||||
response.Write([]byte(hub.Id.String()))
|
||||
}
|
||||
|
||||
func HandleHubJoin(response http.ResponseWriter, request *http.Request) {
|
||||
@@ -194,12 +201,19 @@ func HandleHubJoin(response http.ResponseWriter, request *http.Request) {
|
||||
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
hub, err := getHubByIdStr(ctx, request.Header.Get("hubid"))
|
||||
hub, err := getHubByIdStr(ctx, request.Header.Get("hub_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid hubid", http.StatusBadRequest)
|
||||
http.Error(response, "invalid hub_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := hub.Users[user.Id]
|
||||
if ok {
|
||||
http.Error(response, "hub already joined", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user.Hubs[hub.Id] = hub
|
||||
hubUser := types.NewHubUser()
|
||||
hubUser.OriginalId = user.Id
|
||||
if hub.JoinRole != nil {
|
||||
@@ -208,6 +222,8 @@ func HandleHubJoin(response http.ResponseWriter, request *http.Request) {
|
||||
hubUser.CreatedAt = time.Now()
|
||||
hub.Users[hubUser.OriginalId] = hubUser
|
||||
updateChannelCacheForSpecUser(hubUser, hub)
|
||||
|
||||
response.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
@@ -219,7 +235,7 @@ func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
channel, err := getHubChannelIfValidWithResponseOnFail(ctx, response, hub, hubUser, request.Header.Get("channelid"))
|
||||
channel, err := getHubChannelIfValidWithResponseOnFail(ctx, response, hub, hubUser, request.Header.Get("channel_id"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -229,8 +245,8 @@ func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
msgContent := request.FormValue("msgContent")
|
||||
attachedFile := request.FormValue("attachedFile")
|
||||
msgContent := request.FormValue("msg_content")
|
||||
attachedFile := request.FormValue("attached_file")
|
||||
|
||||
if msgContent == "" && attachedFile == "" {
|
||||
http.Error(response, "empty msgContent", http.StatusBadRequest)
|
||||
@@ -266,69 +282,10 @@ func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
wsServer.WsSendMessageCloseIfTimeout(target, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func HandleGetHubs(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
|
||||
}
|
||||
|
||||
user.Mu.RLock()
|
||||
hubs := slices.Collect(maps.Values(user.Hubs))
|
||||
user.Mu.RUnlock()
|
||||
if len(hubs) == 0 {
|
||||
response.WriteHeader(http.StatusNoContent)
|
||||
response.Write([]byte("no hubs found"))
|
||||
return
|
||||
}
|
||||
converted, err := json.Marshal(hubs)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(converted)
|
||||
response.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
func HandleGetChannels(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, _, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
channelMap := make(map[uint8]*types.HubChannel)
|
||||
hub.Mu.RLock()
|
||||
for i, channel := range hub.Channels {
|
||||
if channel == nil {
|
||||
continue
|
||||
}
|
||||
channelMap[uint8(i)] = channel
|
||||
}
|
||||
hub.Mu.Unlock()
|
||||
if len(channelMap) == 0 {
|
||||
response.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
channels, err := json.Marshal(channelMap)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(channels)
|
||||
}
|
||||
|
||||
func HandleGetHubUsers(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||
return
|
||||
}
|
||||
@@ -337,27 +294,129 @@ func HandleGetHubUsers(response http.ResponseWriter, request *http.Request) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users := make([]*types.HubUser, 0)
|
||||
channels := make([]uuid.UUID, 0)
|
||||
hub.Mu.RLock()
|
||||
for userId, user := range hub.Users {
|
||||
if userId == requestor.OriginalId {
|
||||
for _, channel := range hub.Channels {
|
||||
if channel == nil || !haveHubUserCachedPermissions(types.CachedUserCanView, requestor, channel) {
|
||||
continue
|
||||
}
|
||||
users = append(users, user)
|
||||
channels = append(channels, channel.Id)
|
||||
}
|
||||
hub.Mu.Unlock()
|
||||
if len(users) == 0 {
|
||||
hub.Mu.RUnlock()
|
||||
if len(channels) == 0 {
|
||||
response.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
channels, err := json.Marshal(users)
|
||||
marshal, err := json.Marshal(channels)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(channels)
|
||||
response.Write(marshal)
|
||||
}
|
||||
|
||||
func HandleGetHubUsers(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, _, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users := make([]*types.HubUser, 0)
|
||||
hub.Mu.RLock()
|
||||
for _, user := range hub.Users {
|
||||
users = append(users, user)
|
||||
}
|
||||
hub.Mu.RUnlock()
|
||||
if len(users) == 0 {
|
||||
response.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
marshal, err := json.Marshal(users)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(marshal)
|
||||
}
|
||||
|
||||
func GetRoles(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, _, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
roles := make([]*types.HubRole, 0)
|
||||
for _, role := range hub.Roles {
|
||||
if role == nil {
|
||||
continue
|
||||
}
|
||||
roles = append(roles, role)
|
||||
}
|
||||
hub.Mu.RUnlock()
|
||||
marshal, err := json.Marshal(roles)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(marshal)
|
||||
}
|
||||
|
||||
func GetHubData(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, _, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
marshal, err := json.Marshal(hub)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(marshal)
|
||||
}
|
||||
func GetChannelData(response http.ResponseWriter, request *http.Request) {
|
||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||
return
|
||||
}
|
||||
ctx := request.Context()
|
||||
_, _, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
channelId, err := convertions.StringToUuid(request.FormValue("channel_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid channel_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
channel, ok := hub.Channels[channelId]
|
||||
hub.Mu.RUnlock()
|
||||
if !ok {
|
||||
http.Error(response, "no such channel", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
marshal, err := json.Marshal(channel)
|
||||
if err != nil {
|
||||
http.Error(response, "json error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(marshal)
|
||||
}
|
||||
|
||||
func hubPermissionContext(response http.ResponseWriter, request *http.Request, rt bodyLimit, needed types.Permissions) (*types.HubUser, *types.Hub, context.Context, uint8, bool) {
|
||||
@@ -384,7 +443,7 @@ func HandleHubSetName(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
newName := request.FormValue("newname")
|
||||
newName := request.FormValue("new_name")
|
||||
if newName == "" {
|
||||
http.Error(response, "empty name", http.StatusBadRequest)
|
||||
return
|
||||
@@ -398,7 +457,7 @@ func HandleHubSetColor(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
color, err := convertions.StringToRgba(request.FormValue("newname"))
|
||||
color, err := convertions.StringToRgba(request.FormValue("new_color"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad color", http.StatusBadRequest)
|
||||
return
|
||||
@@ -430,28 +489,37 @@ func HandleHubUserRemove(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("targetid"))
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad targetid", http.StatusBadRequest)
|
||||
http.Error(response, "bad target_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
target, exists := hub.Users[targetId]
|
||||
hubTarget, exists := hub.Users[targetId]
|
||||
hub.Mu.RUnlock()
|
||||
if !exists {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "user not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
hub.Mu.RUnlock()
|
||||
|
||||
if usedRoleId <= hubUserHighestRoleId(target, hub) {
|
||||
if usedRoleId <= hubUserHighestRoleId(hubTarget, hub) {
|
||||
http.Error(response, "target higher in hierarchy", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
target, err := cache.GetUserById(targetId)
|
||||
if err != nil {
|
||||
http.Error(response, "target not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
target.Mu.Lock()
|
||||
delete(target.Hubs, hub.Id)
|
||||
target.Mu.Unlock()
|
||||
|
||||
hub.Mu.Lock()
|
||||
delete(hub.Users, targetId)
|
||||
updateChannelCacheForSpecUser(target, hub)
|
||||
hub.Mu.Unlock()
|
||||
updateChannelCacheForSpecUser(hubTarget, hub)
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
@@ -460,27 +528,25 @@ func HandleHubRenameUser(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
newName := request.FormValue("newname")
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("targetid"))
|
||||
newName := request.FormValue("new_name")
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad targetid", http.StatusBadRequest)
|
||||
http.Error(response, "bad target_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
target, exists := hub.Users[targetId]
|
||||
hub.Mu.RUnlock()
|
||||
if !exists {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "user not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
hub.Mu.RUnlock()
|
||||
|
||||
if usedRoleId <= hubUserHighestRoleId(target, hub) {
|
||||
http.Error(response, "target higher in hierarchy", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
target.Name = newName
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
@@ -489,7 +555,7 @@ func HandleHubRenameSelf(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
requestor.Name = request.FormValue("newname")
|
||||
requestor.Name = request.FormValue("new_name")
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
@@ -498,25 +564,23 @@ func HandleHubToggleMuteUser(response http.ResponseWriter, request *http.Request
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("targetid"))
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad targetid", http.StatusBadRequest)
|
||||
http.Error(response, "bad target_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
target, exists := hub.Users[targetId]
|
||||
hub.Mu.RUnlock()
|
||||
if !exists {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "user not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
hub.Mu.RUnlock()
|
||||
|
||||
if usedRoleId <= hubUserHighestRoleId(target, hub) {
|
||||
http.Error(response, "target higher in hierarchy", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
hub.Mu.RLock()
|
||||
target.IsMuted = !target.IsMuted
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
@@ -526,14 +590,14 @@ func HandleHubUserAddRole(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("targetid"))
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad targetid", http.StatusBadRequest)
|
||||
http.Error(response, "bad target_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("roleid"))
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad roleid", http.StatusBadRequest)
|
||||
http.Error(response, "bad role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if roleId > usedRoleId {
|
||||
@@ -563,14 +627,14 @@ func HandleHubUserRemoveRole(response http.ResponseWriter, request *http.Request
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("targetid"))
|
||||
targetId, err := convertions.StringToUuid(request.FormValue("target_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad targetid", http.StatusBadRequest)
|
||||
http.Error(response, "bad target_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("roleid"))
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad roleid", http.StatusBadRequest)
|
||||
http.Error(response, "bad role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if roleId > usedRoleId {
|
||||
@@ -630,9 +694,9 @@ func HandleHubRemoveRole(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
targetRoleId, err := convertions.StringToUint8(request.FormValue("roleid"))
|
||||
targetRoleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad roleid", http.StatusBadRequest)
|
||||
http.Error(response, "bad role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if targetRoleId == 0 {
|
||||
@@ -660,16 +724,16 @@ func HandleRoleSetName(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("roleid"))
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad roleid", http.StatusBadRequest)
|
||||
http.Error(response, "bad role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if roleId > usedRoleId {
|
||||
http.Error(response, "target role higher in hierarchy", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
newName := request.FormValue("newname")
|
||||
newName := request.FormValue("new_name")
|
||||
if newName == "" {
|
||||
http.Error(response, "name empty", http.StatusBadRequest)
|
||||
return
|
||||
@@ -678,6 +742,7 @@ func HandleRoleSetName(response http.ResponseWriter, request *http.Request) {
|
||||
hub.Mu.Lock()
|
||||
role := hub.Roles[roleId]
|
||||
if role == nil {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "no such role", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
@@ -691,16 +756,16 @@ func HandleRoleSetColor(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("roleid"))
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad roleid", http.StatusBadRequest)
|
||||
http.Error(response, "bad role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if roleId > usedRoleId {
|
||||
http.Error(response, "target role higher in hierarchy", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
color, err := convertions.StringToRgba(request.FormValue("newcolor"))
|
||||
color, err := convertions.StringToRgba(request.FormValue("new_color"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid newcolor", http.StatusBadRequest)
|
||||
return
|
||||
@@ -709,6 +774,7 @@ func HandleRoleSetColor(response http.ResponseWriter, request *http.Request) {
|
||||
hub.Mu.Lock()
|
||||
role := hub.Roles[roleId]
|
||||
if role == nil {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "no such role", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
@@ -722,9 +788,9 @@ func HandleRoleSetPermissions(response http.ResponseWriter, request *http.Reques
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
targetRoleId, err := convertions.StringToUint8(request.FormValue("roleid"))
|
||||
targetRoleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "bad roleid", http.StatusBadRequest)
|
||||
http.Error(response, "bad role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if targetRoleId > usedRoleId {
|
||||
@@ -814,13 +880,16 @@ func HandleChannelCreate(response http.ResponseWriter, request *http.Request) {
|
||||
newHubChannel.RolesCanReadHistory.Add(types.HubBoundRolesMax)
|
||||
}
|
||||
hub.Mu.Lock()
|
||||
for i, channel := range hub.Channels {
|
||||
if channel != nil {
|
||||
continue
|
||||
}
|
||||
hub.Channels[i] = newHubChannel
|
||||
break
|
||||
usedPositions := make(map[uint8]bool, len(hub.Channels))
|
||||
for _, ch := range hub.Channels {
|
||||
usedPositions[ch.Position] = true
|
||||
}
|
||||
var position uint8
|
||||
for usedPositions[position] {
|
||||
position++
|
||||
}
|
||||
newHubChannel.Position = position
|
||||
hub.Channels[newHubChannel.Id] = newHubChannel
|
||||
hub.Mu.Unlock()
|
||||
|
||||
updateChannelCacheForSpecChannel(newHubChannel, hub)
|
||||
@@ -832,14 +901,19 @@ func HandleChannelRemove(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
channelId, err := convertions.StringToUint8(request.FormValue("id"))
|
||||
channelId, err := convertions.StringToUuid(request.FormValue("channel_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid channel id", http.StatusBadRequest)
|
||||
http.Error(response, "invalid channel_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Mu.Lock()
|
||||
hub.Channels[channelId] = nil
|
||||
if _, ok := hub.Channels[channelId]; !ok {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "no such channel", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
delete(hub.Channels, channelId)
|
||||
hub.Mu.Unlock()
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
@@ -848,26 +922,26 @@ func HandleChannelSetName(response http.ResponseWriter, request *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
newName := request.FormValue("newname")
|
||||
newName := request.FormValue("new_name")
|
||||
if newName == "" {
|
||||
http.Error(response, "newname empty", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
channelId, err := convertions.StringToUint8(request.FormValue("id"))
|
||||
channelId, err := convertions.StringToUuid(request.FormValue("channel_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid channel id", http.StatusBadRequest)
|
||||
http.Error(response, "invalid channel_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Mu.Lock()
|
||||
channel := hub.Channels[channelId]
|
||||
if channel == nil {
|
||||
channel, ok := hub.Channels[channelId]
|
||||
if !ok {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "no such channel", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
channel.Name = newName
|
||||
hub.Mu.Unlock()
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
@@ -877,20 +951,85 @@ func HandleChannelSetDescription(response http.ResponseWriter, request *http.Req
|
||||
return
|
||||
}
|
||||
newDescription := request.FormValue("description")
|
||||
channelId, err := convertions.StringToUint8(request.FormValue("id"))
|
||||
channelId, err := convertions.StringToUuid(request.FormValue("channel_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid channel id", http.StatusBadRequest)
|
||||
http.Error(response, "invalid channel_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hub.Mu.Lock()
|
||||
channel := hub.Channels[channelId]
|
||||
if channel == nil {
|
||||
channel, ok := hub.Channels[channelId]
|
||||
if !ok {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "no such channel", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
channel.Description = newDescription
|
||||
hub.Mu.Unlock()
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func handleChannelRolePermission(response http.ResponseWriter, request *http.Request, perm types.Permissions, modify func(*types.HubChannel, uint8, bool)) {
|
||||
_, hub, _, usedRoleId, ok := hubPermissionContext(response, request, normal, perm)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
channelId, err := convertions.StringToUuid(request.FormValue("channel_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid channel_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
roleId, err := convertions.StringToUint8(request.FormValue("role_id"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid role_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if roleId > usedRoleId {
|
||||
http.Error(response, "target role higher in hierarchy", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
allow := convertions.StringToBool(request.URL.Query().Get("allow"))
|
||||
|
||||
hub.Mu.Lock()
|
||||
channel, ok := hub.Channels[channelId]
|
||||
if !ok {
|
||||
hub.Mu.Unlock()
|
||||
http.Error(response, "channel not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
modify(channel, roleId, allow)
|
||||
hub.Mu.Unlock()
|
||||
|
||||
updateChannelCacheForSpecChannel(channel, hub)
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HandleChannelSetPermittedVisibleRole(response http.ResponseWriter, request *http.Request) {
|
||||
handleChannelRolePermission(response, request, types.PermissionSetChannelPermittedVisibleRoles, func(c *types.HubChannel, roleId uint8, allow bool) {
|
||||
if allow {
|
||||
c.RolesCanView.Add(roleId)
|
||||
} else {
|
||||
c.RolesCanView.Remove(roleId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func HandleChannelSetPermittedSendRole(response http.ResponseWriter, request *http.Request) {
|
||||
handleChannelRolePermission(response, request, types.PermissionSetChannelPermittedSendMessageRoles, func(c *types.HubChannel, roleId uint8, allow bool) {
|
||||
if allow {
|
||||
c.RolesCanMessage.Add(roleId)
|
||||
} else {
|
||||
c.RolesCanMessage.Remove(roleId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func HandleChannelSetPermittedHistoryRole(response http.ResponseWriter, request *http.Request) {
|
||||
handleChannelRolePermission(response, request, types.PermissionSetChannelPermittedReadHistoryRoles, func(c *types.HubChannel, roleId uint8, allow bool) {
|
||||
if allow {
|
||||
c.RolesCanReadHistory.Add(roleId)
|
||||
} else {
|
||||
c.RolesCanReadHistory.Remove(roleId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user