From 3a6b51da97d1b61d2043925b7ad3269854937118 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 5 May 2024 01:04:14 +0800 Subject: [PATCH] :sparkles: Channels with realm basis --- pkg/server/channels_api.go | 75 ++++++++++++++++++++++++++++++++------ pkg/server/realms_api.go | 21 +++++++++++ pkg/server/startup.go | 2 +- pkg/services/channels.go | 27 ++++++++++---- 4 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 pkg/server/realms_api.go diff --git a/pkg/server/channels_api.go b/pkg/server/channels_api.go index 3d0b038..9e4dbaa 100644 --- a/pkg/server/channels_api.go +++ b/pkg/server/channels_api.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "git.solsynth.dev/hydrogen/messaging/pkg/database" "git.solsynth.dev/hydrogen/messaging/pkg/models" "git.solsynth.dev/hydrogen/messaging/pkg/services" @@ -10,7 +11,13 @@ import ( func getChannel(c *fiber.Ctx) error { alias := c.Params("channel") - channel, err := services.GetChannelWithAlias(alias) + var err error + var channel models.Channel + if val, ok := c.Locals("realm").(models.Realm); ok { + channel, err = services.GetChannelWithAlias(alias, val.ID) + } else { + channel, err = services.GetChannelWithAlias(alias) + } if err != nil { return fiber.NewError(fiber.StatusNotFound, err.Error()) } @@ -19,7 +26,13 @@ func getChannel(c *fiber.Ctx) error { } func listChannel(c *fiber.Ctx) error { - channels, err := services.ListChannel() + var err error + var channels []models.Channel + if val, ok := c.Locals("realm").(models.Realm); ok { + channels, err = services.ListChannel(val.ID) + } else { + channels, err = services.ListChannel() + } if err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } @@ -64,7 +77,25 @@ func createChannel(c *fiber.Ctx) error { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } - channel, err := services.NewChannel(user, data.Alias, data.Name, data.Description) + var realm *models.Realm + if val, ok := c.Locals("realm").(models.Realm); ok { + if info, err := services.GetRealmMember(val.ID, user.ExternalID); err != nil { + return fmt.Errorf("you must be a part of that realm then can create channel related to it") + } else if info.GetPowerLevel() < 50 { + return fmt.Errorf("you must be a moderator of that realm then can create channel related to it") + } else { + realm = &val + } + } + + var err error + var channel models.Channel + if realm != nil { + channel, err = services.NewChannel(user, data.Alias, data.Name, data.Description, realm.ID) + } else { + channel, err = services.NewChannel(user, data.Alias, data.Name, data.Description) + } + if err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } @@ -86,11 +117,22 @@ func editChannel(c *fiber.Ctx) error { return err } + tx := database.C.Where(&models.Channel{BaseModel: models.BaseModel{ID: uint(id)}}) + + if val, ok := c.Locals("realm").(models.Realm); ok { + if info, err := services.GetRealmMember(val.ID, user.ExternalID); err != nil { + return fmt.Errorf("you must be a part of that realm then can edit channel related to it") + } else if info.GetPowerLevel() < 50 { + return fmt.Errorf("you must be a moderator of that realm then can edit channel related to it") + } else { + tx = tx.Where("realm_id = ?", val.ID) + } + } else { + tx = tx.Where("account_id = ? AND realm_id IS NULL", user.ID) + } + var channel models.Channel - if err := database.C.Where(&models.Channel{ - BaseModel: models.BaseModel{ID: uint(id)}, - AccountID: user.ID, - }).First(&channel).Error; err != nil { + if err := tx.First(&channel).Error; err != nil { return fiber.NewError(fiber.StatusNotFound, err.Error()) } @@ -106,11 +148,22 @@ func deleteChannel(c *fiber.Ctx) error { user := c.Locals("principal").(models.Account) id, _ := c.ParamsInt("channelId", 0) + tx := database.C.Where(&models.Channel{BaseModel: models.BaseModel{ID: uint(id)}}) + + if val, ok := c.Locals("realm").(models.Realm); ok { + if info, err := services.GetRealmMember(val.ID, user.ExternalID); err != nil { + return fmt.Errorf("you must be a part of that realm then can delete channel related to it") + } else if info.GetPowerLevel() < 50 { + return fmt.Errorf("you must be a moderator of that realm then can delete channel related to it") + } else { + tx = tx.Where("realm_id = ?", val.ID) + } + } else { + tx = tx.Where("account_id = ? AND realm_id IS NULL", user.ID) + } + var channel models.Channel - if err := database.C.Where(&models.Channel{ - BaseModel: models.BaseModel{ID: uint(id)}, - AccountID: user.ID, - }).First(&channel).Error; err != nil { + if err := tx.First(&channel).Error; err != nil { return fiber.NewError(fiber.StatusNotFound, err.Error()) } diff --git a/pkg/server/realms_api.go b/pkg/server/realms_api.go new file mode 100644 index 0000000..970bf89 --- /dev/null +++ b/pkg/server/realms_api.go @@ -0,0 +1,21 @@ +package server + +import ( + "fmt" + "git.solsynth.dev/hydrogen/messaging/pkg/services" + "github.com/gofiber/fiber/v2" +) + +func realmMiddleware(c *fiber.Ctx) error { + realmAlias := c.Params("realm") + if len(realmAlias) > 0 && realmAlias != "global" { + realm, err := services.GetRealmWithAlias(realmAlias) + if err != nil { + return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("requested channel with realm, but realm was not found: %v", err)) + } else { + c.Locals("realm", realm) + } + } + + return c.Next() +} diff --git a/pkg/server/startup.go b/pkg/server/startup.go index cf328cf..6b17b7c 100644 --- a/pkg/server/startup.go +++ b/pkg/server/startup.go @@ -75,7 +75,7 @@ func NewServer() { api.Post("/attachments", authMiddleware, uploadAttachment) api.Delete("/attachments/:id", authMiddleware, deleteAttachment) - channels := api.Group("/channels").Name("Channels API") + channels := api.Group("/channels/:realm").Use(realmMiddleware).Name("Channels API") { channels.Get("/", listChannel) channels.Get("/:channel", getChannel) diff --git a/pkg/services/channels.go b/pkg/services/channels.go index e1d2a91..1b5bae4 100644 --- a/pkg/services/channels.go +++ b/pkg/services/channels.go @@ -27,11 +27,15 @@ func GetChannel(id uint) (models.Channel, error) { return channel, nil } -func GetChannelWithAlias(alias string) (models.Channel, error) { +func GetChannelWithAlias(alias string, realmId ...uint) (models.Channel, error) { var channel models.Channel - if err := database.C.Where(models.Channel{ - Alias: alias, - }).Preload("Account").First(&channel).Error; err != nil { + tx := database.C.Where(models.Channel{Alias: alias}).Preload("Account") + if len(realmId) > 0 { + tx = tx.Where("realm_id = ?", realmId) + } else { + tx = tx.Where("realm_id IS NULL") + } + if err := tx.First(&channel).Error; err != nil { return channel, err } @@ -74,9 +78,15 @@ func GetAvailableChannel(id uint, user models.Account) (models.Channel, models.C return channel, member, nil } -func ListChannel() ([]models.Channel, error) { +func ListChannel(realmId ...uint) ([]models.Channel, error) { var channels []models.Channel - if err := database.C.Preload("Account").Find(&channels).Error; err != nil { + tx := database.C.Preload("Account") + if len(realmId) > 0 { + tx = tx.Where("realm_id = ?", realmId) + } else { + tx = tx.Where("realm_id IS NULL") + } + if err := tx.Find(&channels).Error; err != nil { return channels, err } @@ -112,7 +122,7 @@ func ListChannelIsAvailable(user models.Account) ([]models.Channel, error) { return channels, nil } -func NewChannel(user models.Account, alias, name, description string) (models.Channel, error) { +func NewChannel(user models.Account, alias, name, description string, realmId ...uint) (models.Channel, error) { channel := models.Channel{ Alias: alias, Name: name, @@ -122,6 +132,9 @@ func NewChannel(user models.Account, alias, name, description string) (models.Ch {AccountID: user.ID}, }, } + if len(realmId) > 0 { + channel.RealmID = &realmId[0] + } err := database.C.Save(&channel).Error