split http across files
This commit is contained in:
+431
@@ -0,0 +1,431 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
json2 "encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func isOwnerOfGroup(user *User, group *Group) bool {
|
||||
if group.OwnerId == user.Id {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getIfOwnerUserAndGroup(ctx context.Context, response *http.ResponseWriter, request *http.Request) (*User, *Group, error) {
|
||||
user, err := GetUserByToken(ctx, request.FormValue("token"))
|
||||
if err != nil {
|
||||
http.Error(*response, "invalid token", http.StatusUnauthorized)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
affectedGroupId, err := ConvertStringUint32(request.FormValue("groupid"))
|
||||
if err != nil {
|
||||
http.Error(*response, "no such group", http.StatusUnauthorized)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
group, err := GetGroup(ctx, affectedGroupId)
|
||||
if err != nil {
|
||||
http.Error(*response, "no such group", http.StatusUnauthorized)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !isOwnerOfGroup(user, group) {
|
||||
http.Error(*response, "no such group", http.StatusUnauthorized)
|
||||
return nil, nil, errors.New("not an owner")
|
||||
}
|
||||
return user, group, nil
|
||||
}
|
||||
|
||||
func HttpHandeGroupCreate(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
|
||||
user, err := GetUserByToken(ctx, request.FormValue("token"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
name := request.FormValue("name")
|
||||
if name == "" {
|
||||
name = "Best group ever"
|
||||
}
|
||||
|
||||
colorString := request.FormValue("color")
|
||||
color, err := ConvertStringToRgb(colorString)
|
||||
if err != nil {
|
||||
http.Error(response, "invalid color", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
group := Group{
|
||||
Name: name,
|
||||
CreatedAt: time.Now(),
|
||||
OwnerId: user.Id,
|
||||
CreatorId: user.Id,
|
||||
Color: color,
|
||||
Users: map[uint32]struct{}{user.Id: {}},
|
||||
}
|
||||
|
||||
enableUserColors := request.FormValue("enableUserColors")
|
||||
if enableUserColors == "1" {
|
||||
group.EnableUserColors = true
|
||||
}
|
||||
|
||||
err = DbGroupSave(ctx, &group)
|
||||
if err != nil {
|
||||
http.Error(response, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusCreated)
|
||||
fmt.Fprintf(response, "%d", group.Id)
|
||||
}
|
||||
|
||||
func HttpHandleGroupDelete(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
_, group, err := getIfOwnerUserAndGroup(ctx, &response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = DbGroupDelete(ctx, group)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
CacheDeleteGroup(group.Id)
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HttpHandleGroupAddUsers(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
|
||||
_, group, err := getIfOwnerUserAndGroup(ctx, &response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
usersString := request.FormValue("users")
|
||||
var remainingUsersCount = int(MaxUsersInGroup) - len(group.Users)
|
||||
if remainingUsersCount < 1 {
|
||||
http.Error(response, "max users", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
usersStringSlice := strings.SplitN(usersString, ",", remainingUsersCount+1)
|
||||
if len(usersStringSlice) == 0 {
|
||||
http.Error(response, "no users to add", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var ids [MaxUsersInGroup]uint32
|
||||
var idx uint32 = 0
|
||||
for _, s := range usersStringSlice {
|
||||
if idx >= MaxUsersInGroup {
|
||||
break
|
||||
}
|
||||
id, err := ConvertStringUint32(strings.TrimSpace(s))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids[idx] = id
|
||||
idx++
|
||||
}
|
||||
if idx == 0 {
|
||||
http.Error(response, "no valid users", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = DbGroupAddUsers(ctx, group.Id, &ids)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
for i := uint32(0); i < idx; i++ {
|
||||
group.Users[ids[i]] = struct{}{}
|
||||
if cachedUser, err := CacheGetUserById(ids[i]); err == nil {
|
||||
cachedUser.Mu.Lock()
|
||||
cachedUser.Groups[group.Id] = struct{}{}
|
||||
cachedUser.Mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HttpHandleGroupRemoveUser(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
|
||||
_, group, err := getIfOwnerUserAndGroup(ctx, &response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
usersString := request.FormValue("users")
|
||||
|
||||
usersStringSlice := strings.SplitN(usersString, ",", int(MaxUsersInGroup)+1)
|
||||
|
||||
var ids [MaxUsersInGroup]uint32
|
||||
var idx uint32 = 0
|
||||
for _, s := range usersStringSlice {
|
||||
if idx >= MaxUsersInGroup {
|
||||
break
|
||||
}
|
||||
id, err := ConvertStringUint32(strings.TrimSpace(s))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids[idx] = id
|
||||
idx++
|
||||
}
|
||||
if idx == 0 {
|
||||
http.Error(response, "no valid users", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
count, err := DbGroupRemoveUsers(ctx, group.Id, &ids)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
for i := uint32(0); i < idx; i++ {
|
||||
delete(group.Users, ids[i])
|
||||
if cachedUser, err := CacheGetUserById(ids[i]); err == nil {
|
||||
cachedUser.Mu.Lock()
|
||||
delete(cachedUser.Groups, group.Id)
|
||||
cachedUser.Mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write([]byte(strconv.Itoa(count)))
|
||||
}
|
||||
|
||||
func HttpHandleGroupChangeColor(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
_, group, err := getIfOwnerUserAndGroup(ctx, &response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
color, err := ConvertStringToRgb(request.FormValue("color"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid color", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
group.Color = color
|
||||
err = DbGroupSetColor(ctx, group)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write([]byte("changed"))
|
||||
}
|
||||
|
||||
func HttpHandleGroupChangeOwner(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
_, group, err := getIfOwnerUserAndGroup(ctx, &response, request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
newOwnerName := request.FormValue("newOwner")
|
||||
|
||||
newOwner, err := CacheGetUserByName(newOwnerName)
|
||||
if err != nil {
|
||||
newOwner = &User{Name: newOwnerName}
|
||||
err = DbUserGetStandardInfoByName(ctx, newOwner)
|
||||
if err != nil {
|
||||
http.Error(response, "user not in group", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err = DbGetWholeUser(ctx, newOwner); err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, ok := group.Users[newOwner.Id]
|
||||
if !ok {
|
||||
http.Error(response, "user not in group", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
group.OwnerId = newOwner.Id
|
||||
err = DbGroupSetOwnerId(ctx, group)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HttpHandleGroupMessage(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
|
||||
user, err := GetUserByToken(ctx, request.FormValue("token"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid token", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
groupIdStr := request.FormValue("groupid")
|
||||
groupId, err := ConvertStringUint32(groupIdStr)
|
||||
if err != nil {
|
||||
http.Error(response, "no such group", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
group, err := GetGroup(ctx, groupId)
|
||||
if err != nil {
|
||||
http.Error(response, "no such group", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
content := request.FormValue("content")
|
||||
if content == "" {
|
||||
http.Error(response, "empty message", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := group.Users[user.Id]
|
||||
if !ok {
|
||||
http.Error(response, "no such group", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err = WsSendToGroup(group, user, content)
|
||||
if err != nil {
|
||||
http.Error(response, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func HttpHandleGroupsGetWithoutMembers(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
|
||||
user, err := GetUserByToken(ctx, request.FormValue("token"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
user.Mu.RLock()
|
||||
groupIds := make([]uint32, 0, len(user.Groups))
|
||||
for groupId := range user.Groups {
|
||||
groupIds = append(groupIds, groupId)
|
||||
}
|
||||
user.Mu.RUnlock()
|
||||
|
||||
groups := make(map[uint32]*Group, len(groupIds))
|
||||
for _, groupId := range groupIds {
|
||||
group, err := GetGroup(ctx, groupId)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
groups[groupId] = group
|
||||
}
|
||||
|
||||
json, err := json2.Marshal(groups)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write(json)
|
||||
}
|
||||
|
||||
func HttpHandleGroupMembersGet(response http.ResponseWriter, request *http.Request) {
|
||||
if !HttpMethodAllowed(&response, request) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.Context()
|
||||
user, err := GetUserByToken(ctx, request.FormValue("token"))
|
||||
if err != nil {
|
||||
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
groupStr := request.FormValue("group")
|
||||
groupId, err := ConvertStringUint32(groupStr)
|
||||
if err != nil {
|
||||
http.Error(response, "invalid group", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user.Mu.RLock()
|
||||
_, ok := user.Groups[groupId]
|
||||
user.Mu.RUnlock()
|
||||
if !ok {
|
||||
http.Error(response, "no such group", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
group, err := GetGroup(ctx, groupId)
|
||||
if err != nil {
|
||||
http.Error(response, "no such group", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
groupMembers := slices.Collect(maps.Keys(group.Users))
|
||||
|
||||
json, err := json2.Marshal(groupMembers)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write(json)
|
||||
}
|
||||
Reference in New Issue
Block a user