|
|
|
@@ -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)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|