diff --git a/modules/structs/users.go b/modules/structs/users.go index edc839c..606c463 100644 --- a/modules/structs/users.go +++ b/modules/structs/users.go @@ -23,6 +23,7 @@ type TeamMember struct { Email string RoleId string ProfilePictureUrl string + Online bool `gorm:"-"` } type CreateTeamMemberRequest struct { @@ -32,3 +33,11 @@ type CreateTeamMemberRequest struct { RoleId string Password string } + +type TeamMemberUserIdParam struct { + MemberId string +} + +type UpdateTeamMemberRoleRequest struct { + RoleId string +} diff --git a/modules/utils/globals.go b/modules/utils/globals.go index 4b9e9d5..113e94b 100644 --- a/modules/utils/globals.go +++ b/modules/utils/globals.go @@ -20,6 +20,9 @@ const ( MaxImageSize = 25 * 1024 * 1024 // 25MB MaxVideoSize = 50 * 1024 * 1024 // 50MB + + ConnectionStateOffline = 0 + ConnectionStateOnline = 1 ) var ( @@ -82,6 +85,8 @@ const ( SendCmdSettingsUpdatedBanner = 3 SendCmdSettingsUpdatedSubdomain = 4 SendCmdTeamAddedMember = 5 + SendCmdTeamUpdatedMemberRole = 6 + SendCmdTeamDeletedMember = 7 ) // commands received from websocket clients diff --git a/routers/router/api/v1/organization/settings.go b/routers/router/api/v1/organization/settings.go index 4082470..b21546e 100644 --- a/routers/router/api/v1/organization/settings.go +++ b/routers/router/api/v1/organization/settings.go @@ -86,7 +86,9 @@ func UpdateOrganizationSettings(c *fiber.Ctx) error { }, ) - return c.SendStatus(fiber.StatusOK) + return c.JSON(fiber.Map{ + "status": "success", + }) } func UpdateOrganizationFile(c *fiber.Ctx) error { diff --git a/routers/router/api/v1/organization/team.go b/routers/router/api/v1/organization/team.go index 0784ce0..cc0caf4 100644 --- a/routers/router/api/v1/organization/team.go +++ b/routers/router/api/v1/organization/team.go @@ -41,6 +41,10 @@ func GetTeamMembers(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusInternalServerError) } + for i, user := range users { + users[i].Online = socketclients.IsUserConnected(user.Id) + } + return c.JSON(users) } @@ -133,3 +137,113 @@ func CreateTeamMember(c *fiber.Ctx) error { "message": "Team member created successfully", }) } + +func UpdateTeamMemberRole(c *fiber.Ctx) error { + // swagger:operation PATCH /organization/team/members/{memberId}/role organization updateTeamMemberRole + // --- + // summary: Update team member role + // consumes: + // - application/json + // produces: + // - application/json + // parameters: + // - name: body + // in: body + // schema: + // "$ref": "#/definitions/UpdateTeamMemberRoleRequest" + // responses: + // '200': + // description: Team member role updated successfully + // '400': + // description: Invalid request body + // '500': + // description: Failed to update team member role + + var params structs.TeamMemberUserIdParam + + if err := rsutils.ParamsParserHelper(c, ¶ms); err != nil { + return c.SendStatus(fiber.StatusBadRequest) + } + + var body structs.UpdateTeamMemberRoleRequest + + if err := rsutils.BodyParserHelper(c, &body); err != nil { + return c.SendStatus(fiber.StatusBadRequest) + } + + if params.MemberId == c.Locals("userId").(string) { + return c.SendStatus(fiber.StatusBadRequest) + } + + if err := database.DB.Model(&models.User{}). + Where("id = ?", params.MemberId). + Where("organization_id = ?", c.Locals("organizationId").(string)). + Update("role_id", body.RoleId).Error; err != nil { + return c.SendStatus(fiber.StatusInternalServerError) + } + + socketclients.BroadcastMessageToTopic( + c.Locals("organizationId").(string), + utils.SubscribedTopicTeam, + structs.SendSocketMessage{ + Cmd: utils.SendCmdTeamUpdatedMemberRole, + Body: struct { + MemberId string + RoleId string + }{ + MemberId: params.MemberId, + RoleId: body.RoleId, + }, + }, + ) + + return c.JSON(fiber.Map{ + "message": "Team member role updated successfully", + }) +} + +func DeleteTeamMember(c *fiber.Ctx) error { + // swagger:operation DELETE /organization/team/members/{memberId} organization deleteTeamMember + // --- + // summary: Delete team member + // consumes: + // - application/json + // produces: + // - application/json + // responses: + // '200': + // description: Team member deleted successfully + // '400': + // description: Invalid request body + // '500': + // description: Failed to delete team member + + var params structs.TeamMemberUserIdParam + + if err := rsutils.ParamsParserHelper(c, ¶ms); err != nil { + return c.SendStatus(fiber.StatusBadRequest) + } + + if params.MemberId == c.Locals("userId").(string) { + return c.SendStatus(fiber.StatusBadRequest) + } + + if err := database.DB.Where("id = ?", params.MemberId). + Where("organization_id = ?", c.Locals("organizationId").(string)). + Delete(&models.User{}).Error; err != nil { + return c.SendStatus(fiber.StatusInternalServerError) + } + + socketclients.BroadcastMessageToTopic( + c.Locals("organizationId").(string), + utils.SubscribedTopicTeam, + structs.SendSocketMessage{ + Cmd: utils.SendCmdTeamDeletedMember, + Body: params.MemberId, + }, + ) + + return c.JSON(fiber.Map{ + "message": "Team member deleted successfully", + }) +} diff --git a/routers/router/router.go b/routers/router/router.go index 1d3100d..4c0d44d 100644 --- a/routers/router/router.go +++ b/routers/router/router.go @@ -23,6 +23,8 @@ func SetupRoutes(app *fiber.App) { o.Post("/", organization.CreateOrganization) o.Get("/team/members", handleOrganizationSubdomain, requestAccessValidation, organization.GetTeamMembers) o.Post("/team/members", handleOrganizationSubdomain, requestAccessValidation, organization.CreateTeamMember) + o.Patch("/team/members/:memberId/role", handleOrganizationSubdomain, requestAccessValidation, organization.UpdateTeamMemberRole) + o.Delete("/team/members/:memberId", handleOrganizationSubdomain, requestAccessValidation, organization.DeleteTeamMember) o.Get("/settings", handleOrganizationSubdomain, requestAccessValidation, organization.GetOrganizationSettings) o.Patch("/settings", handleOrganizationSubdomain, requestAccessValidation, organization.UpdateOrganizationSettings) o.Post("/file/:type", handleOrganizationSubdomain, requestAccessValidation, organization.UpdateOrganizationFile) diff --git a/socketclients/socketclients.go b/socketclients/socketclients.go index 9e4562a..44105f5 100644 --- a/socketclients/socketclients.go +++ b/socketclients/socketclients.go @@ -42,3 +42,14 @@ func BroadcastMessageToTopicExceptBrowserTabSession(organizationId string, topic func hasClientSubscribedToTopic(topic string, clientTopic string) bool { return clientTopic == topic || strings.HasPrefix(clientTopic, topic) } + +// Used to determine if a user is connected regardless of the session used +func IsUserConnected(userId string) bool { + for _, socketClient := range cache.GetSocketClients() { + if socketClient.UserId == userId { + return true + } + } + + return false +}