add join role endpoint and persistency for hubs

This commit is contained in:
2026-05-06 19:08:18 +02:00
parent 03c13a6e8a
commit f68a249268
12 changed files with 991 additions and 206 deletions
+263 -2
View File
@@ -127,7 +127,7 @@ func HandleSetUserAvatar(response http.ResponseWriter, request *http.Request) {
}
}
user.AvatarKey = key
err = postgresql.UserUpdateProfile(ctx, user, &types.UserProfileUpdateList{Avatar: true})
err = postgresql.UserUpdateProfile(ctx, user, &types.UserProfileUpdate{Avatar: true})
if err != nil {
http.Error(response, "failed to update user avatar", http.StatusInternalServerError)
minio.Delete(ctx, user.AvatarKey)
@@ -249,7 +249,7 @@ func HandleSetUserProfileBg(response http.ResponseWriter, request *http.Request)
}
}
user.ProfileBgKey = key
err = postgresql.UserUpdateProfile(ctx, user, &types.UserProfileUpdateList{ProfileBg: true})
err = postgresql.UserUpdateProfile(ctx, user, &types.UserProfileUpdate{ProfileBg: true})
if err != nil {
http.Error(response, "failed to update user profile background", http.StatusInternalServerError)
minio.Delete(ctx, user.ProfileBgKey)
@@ -324,6 +324,267 @@ func HandleGetUserProfileBg(response http.ResponseWriter, request *http.Request)
response.Write(profileBgData)
}
func HandleHubSetIcon(response http.ResponseWriter, request *http.Request) {
_, hub, ctx, _, ok := hubPermissionContext(response, request, hubIcon, types.PermissionSetHubIcon)
if !ok {
return
}
file, header, err := request.FormFile("file")
if err != nil {
http.Error(response, "missing file", http.StatusBadRequest)
return
}
defer file.Close()
isImg, contentType, err := isImage(file)
if err != nil || !isImg {
http.Error(response, "invalid file", http.StatusBadRequest)
return
}
key := minio.GetKey(&minio.GetKeyOptions{
MimeType: contentType,
UploadType: minio.HubIcon,
HubId: hub.Id,
})
if err = minio.Upload(ctx, key, file, header.Size, contentType, map[string]string{
"originalName": header.Filename,
}); err != nil {
http.Error(response, "upload failed", http.StatusInternalServerError)
return
}
if hub.IconUrl != "" {
if err = minio.Delete(ctx, hub.IconUrl); err != nil {
minio.Delete(ctx, key)
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
}
hub.IconUrl = key
response.WriteHeader(http.StatusCreated)
}
func HandleHubSetBg(response http.ResponseWriter, request *http.Request) {
_, hub, ctx, _, ok := hubPermissionContext(response, request, hubBackground, types.PermissionSetHubBg)
if !ok {
return
}
file, header, err := request.FormFile("file")
if err != nil {
http.Error(response, "missing file", http.StatusBadRequest)
return
}
defer file.Close()
isImg, contentType, err := isImage(file)
if err != nil || !isImg {
http.Error(response, "invalid file", http.StatusBadRequest)
return
}
key := minio.GetKey(&minio.GetKeyOptions{
MimeType: contentType,
UploadType: minio.HubBackground,
HubId: hub.Id,
})
if err = minio.Upload(ctx, key, file, header.Size, contentType, map[string]string{
"originalName": header.Filename,
}); err != nil {
http.Error(response, "upload failed", http.StatusInternalServerError)
return
}
if hub.BgUrl != "" {
if err = minio.Delete(ctx, hub.BgUrl); err != nil {
minio.Delete(ctx, key)
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
}
hub.BgUrl = key
response.WriteHeader(http.StatusCreated)
}
func HandleGetHubIcon(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
}
if hub.IconUrl == "" {
http.Error(response, "hub has no icon", http.StatusNoContent)
return
}
url, meta, err := minio.GetDownloadUrlAndMetadata(ctx, hub.IconUrl)
if err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
iconData, err := json.Marshal(map[string]any{
"url": url.String(),
"metadata": meta,
})
if err != nil {
http.Error(response, "json error", http.StatusInternalServerError)
return
}
response.WriteHeader(http.StatusOK)
response.Write(iconData)
}
func HandleGetHubBg(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
}
if hub.BgUrl == "" {
http.Error(response, "hub has no background", http.StatusNoContent)
return
}
url, meta, err := minio.GetDownloadUrlAndMetadata(ctx, hub.BgUrl)
if err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
bgData, err := json.Marshal(map[string]any{
"url": url.String(),
"metadata": meta,
})
if err != nil {
http.Error(response, "json error", http.StatusInternalServerError)
return
}
response.WriteHeader(http.StatusOK)
response.Write(bgData)
}
func HandleChannelSetIcon(response http.ResponseWriter, request *http.Request) {
_, hub, ctx, _, ok := hubPermissionContext(response, request, channelIcon, types.PermissionSetChannelIcon)
if !ok {
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, "channel not found", http.StatusNotFound)
return
}
file, header, err := request.FormFile("file")
if err != nil {
http.Error(response, "missing file", http.StatusBadRequest)
return
}
defer file.Close()
isImg, contentType, err := isImage(file)
if err != nil || !isImg {
http.Error(response, "invalid file", http.StatusBadRequest)
return
}
key := minio.GetKey(&minio.GetKeyOptions{
MimeType: contentType,
UploadType: minio.ChannelIcon,
ChannelId: channel.Id,
})
if err = minio.Upload(ctx, key, file, header.Size, contentType, map[string]string{
"originalName": header.Filename,
}); err != nil {
http.Error(response, "upload failed", http.StatusInternalServerError)
return
}
if channel.IconUrl != "" {
if err = minio.Delete(ctx, channel.IconUrl); err != nil {
minio.Delete(ctx, key)
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
}
channel.IconUrl = key
response.WriteHeader(http.StatusCreated)
}
func HandleGetChannelIcon(response http.ResponseWriter, request *http.Request) {
if !validCheckWithResponseOnFail(response, request, normal) {
return
}
ctx := request.Context()
_, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
if err != nil {
return
}
channelId, err := convertions.StringToUuid(request.URL.Query().Get("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, "channel not found", http.StatusNotFound)
return
}
if !haveHubUserCachedPermissions(types.CachedUserCanView, hubUser, channel) {
http.Error(response, "forbidden", http.StatusForbidden)
return
}
if channel.IconUrl == "" {
http.Error(response, "channel has no icon", http.StatusNoContent)
return
}
url, meta, err := minio.GetDownloadUrlAndMetadata(ctx, channel.IconUrl)
if err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
iconData, err := json.Marshal(map[string]any{
"url": url.String(),
"metadata": meta,
})
if err != nil {
http.Error(response, "json error", http.StatusInternalServerError)
return
}
response.WriteHeader(http.StatusOK)
response.Write(iconData)
}
func HandleAttachmentFileDownload(response http.ResponseWriter, request *http.Request) {
if !validCheckWithResponseOnFail(response, request, normal) {
return