notifications
parent
e8a81ec85e
commit
6dbfcec0c5
|
@ -44,4 +44,5 @@ func InitDatabase() {
|
|||
db.AutoMigrate(&structs.RolePermission{})
|
||||
db.AutoMigrate(&structs.UserApiKey{})
|
||||
db.AutoMigrate(&structs.EquipmentDocumentation{})
|
||||
db.AutoMigrate(&structs.Notification{})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
package notification
|
||||
|
||||
import (
|
||||
"jannex/admin-dashboard-backend/modules/database"
|
||||
"jannex/admin-dashboard-backend/modules/structs"
|
||||
"jannex/admin-dashboard-backend/modules/utils"
|
||||
"jannex/admin-dashboard-backend/socketclients"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func GetTotalNotifications(userId string) int {
|
||||
var totalNotifications int64
|
||||
|
||||
database.DB.Model(&structs.Notification{}).Where("user_id = ?", userId).Count(&totalNotifications)
|
||||
|
||||
return int(totalNotifications)
|
||||
}
|
||||
|
||||
func GetNotifications(userId string) []structs.Notification {
|
||||
var notifications []structs.Notification
|
||||
|
||||
database.DB.Model(&structs.Notification{}).Where("user_id = ?", userId).Find(¬ifications)
|
||||
|
||||
return notifications
|
||||
}
|
||||
|
||||
func AddNotification(c *fiber.Ctx, body structs.AddNotificationRequest) error {
|
||||
log.Info().Msgf("body %v", body)
|
||||
|
||||
var userIds []string
|
||||
|
||||
if len(body.UserIds) == 0 && body.NeededPermission == "" && len(body.RoleIds) == 0 {
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(body.UserIds) > 0 {
|
||||
// check if user with provided user id in body.UserIds exist in database and add to userIds
|
||||
database.DB.Model(&structs.User{}).Where("id IN ?", body.UserIds).Select("id").Find(&userIds)
|
||||
}
|
||||
|
||||
var roleIds []string
|
||||
|
||||
if body.NeededPermission != "" {
|
||||
// fetch all role_ids from role_permissions and use the role_id to get all users which are in the role from database which have the permission provided in body.NeededPermission and add to userIds
|
||||
database.DB.Model(&structs.RolePermission{}).Where("permission_id = ?", body.NeededPermission).Select("role_id").Find(&roleIds)
|
||||
|
||||
var userIdsTemp []string
|
||||
|
||||
database.DB.Model(&structs.User{}).Where("role_id IN ?", roleIds).Select("id").Find(&userIdsTemp)
|
||||
|
||||
userIds = append(userIds, userIdsTemp...)
|
||||
}
|
||||
|
||||
if len(body.RoleIds) > 0 {
|
||||
var userIdsTemp []string
|
||||
|
||||
database.DB.Model(&structs.User{}).Where("role_id IN ?", body.RoleIds).Select("id").Find(&userIdsTemp)
|
||||
|
||||
userIds = append(userIds, userIdsTemp...)
|
||||
}
|
||||
|
||||
// no users found
|
||||
if len(userIds) == 0 {
|
||||
return c.SendStatus(fiber.StatusUnprocessableEntity)
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
userIds = unique(userIds)
|
||||
|
||||
// add notification to database
|
||||
for _, userId := range userIds {
|
||||
notify := structs.Notification{
|
||||
Id: uuid.New().String(),
|
||||
UserId: userId,
|
||||
Type: body.Type,
|
||||
Title: body.Title,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
database.DB.Create(¬ify)
|
||||
|
||||
// send notification to user
|
||||
socketclients.SendMessageToUser(userId, "", structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdNewNotification,
|
||||
Body: notify,
|
||||
})
|
||||
}
|
||||
|
||||
log.Info().Msgf("ids %v", userIds)
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func unique(slice []string) []string {
|
||||
keys := make(map[string]bool)
|
||||
list := []string{}
|
||||
|
||||
for _, entry := range slice {
|
||||
if _, value := keys[entry]; !value {
|
||||
keys[entry] = true
|
||||
list = append(list, entry)
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
func DeleteAllNotifications(userId string) {
|
||||
database.DB.Delete(&structs.Notification{}, "user_id = ?", userId)
|
||||
|
||||
socketclients.SendMessageToUser(userId, "", structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdAllNotificationsDeleted,
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteOneNotification(userId string, notificationId string) {
|
||||
database.DB.Delete(&structs.Notification{}, "user_id = ? AND id = ?", userId, notificationId)
|
||||
|
||||
socketclients.SendMessageToUser(userId, "", structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdOneNotificationDeleted,
|
||||
Body: notificationId,
|
||||
})
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package structs
|
||||
|
||||
import "time"
|
||||
|
||||
type Notification struct {
|
||||
Id string
|
||||
// success = 1, info = 2, warning = 3, error = 4
|
||||
Type uint8
|
||||
UserId string
|
||||
Title string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// swagger:model AddNotificationRequest
|
||||
type AddNotificationRequest struct {
|
||||
Type uint8
|
||||
// send notification to specific users
|
||||
UserIds []string
|
||||
// send notification to users with specific permission
|
||||
NeededPermission string
|
||||
// send notification to users with specific role
|
||||
RoleIds []string
|
||||
Title string
|
||||
}
|
||||
|
||||
// swagger:model NotificationsResponse
|
||||
type NotificationsResponse struct {
|
||||
Notifications []Notification
|
||||
}
|
|
@ -64,6 +64,7 @@ type UserInfoResponse struct {
|
|||
Permissions []string
|
||||
AvailableCategoryGroups []string
|
||||
Users []AllUsers
|
||||
TotalNotifications int
|
||||
}
|
||||
|
||||
// swagger:model UserProfileResponse
|
||||
|
|
|
@ -90,6 +90,9 @@ const (
|
|||
SentCmdInstallingGlobalPythonPackagesFinished = 38
|
||||
SentCmdUpdateUsers = 39
|
||||
SentCmdCheckingForGroupTasksCategoryGroupChanges = 40
|
||||
SentCmdNewNotification = 41
|
||||
SentCmdAllNotificationsDeleted = 42
|
||||
SentCmdOneNotificationDeleted = 43
|
||||
)
|
||||
|
||||
// commands received from web clients
|
||||
|
@ -117,6 +120,8 @@ const (
|
|||
ReceivedCmdGroupTasksInstallPythonPackages = 21
|
||||
ReceivedCmdGroupTasksInstallGlobalPythonPackages = 22
|
||||
ReceivedCmdSubscribeToTopic = 23
|
||||
ReceivedCmdDeleteAllNotifications = 24
|
||||
ReceivedCmdDeleteOneNotification = 25
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -416,6 +416,86 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/notifications": {
|
||||
"get": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"notifications"
|
||||
],
|
||||
"summary": "Get notifications",
|
||||
"operationId": "notificationsGetNotifications",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "You can create a new api key in your user profile",
|
||||
"name": "X-Api-Key",
|
||||
"in": "header"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Notifications",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotificationsResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "No permissions"
|
||||
},
|
||||
"500": {
|
||||
"description": "Failed to get notifications"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"notifications"
|
||||
],
|
||||
"summary": "Add a new notification",
|
||||
"operationId": "notificationsAddNotification",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "You can create a new api key in your user profile",
|
||||
"name": "X-Api-Key",
|
||||
"in": "header"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AddNotificationRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "New notification added successfully"
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid request body"
|
||||
},
|
||||
"401": {
|
||||
"description": "No permissions"
|
||||
},
|
||||
"422": {
|
||||
"description": "No users found"
|
||||
},
|
||||
"500": {
|
||||
"description": "Failed to add notification"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/auth/login": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
|
@ -686,6 +766,37 @@
|
|||
}
|
||||
},
|
||||
"definitions": {
|
||||
"AddNotificationRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"NeededPermission": {
|
||||
"description": "send notification to users with specific permission",
|
||||
"type": "string"
|
||||
},
|
||||
"RoleIds": {
|
||||
"description": "send notification to users with specific role",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"Title": {
|
||||
"type": "string"
|
||||
},
|
||||
"Type": {
|
||||
"type": "integer",
|
||||
"format": "uint8"
|
||||
},
|
||||
"UserIds": {
|
||||
"description": "send notification to specific users",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-go-package": "jannex/admin-dashboard-backend/modules/structs"
|
||||
},
|
||||
"AdminAreaRolesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -1058,6 +1169,42 @@
|
|||
"x-go-name": "GroupTaskStepsRequest",
|
||||
"x-go-package": "jannex/admin-dashboard-backend/modules/structs"
|
||||
},
|
||||
"Notification": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"CreatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"Id": {
|
||||
"type": "string"
|
||||
},
|
||||
"Title": {
|
||||
"type": "string"
|
||||
},
|
||||
"Type": {
|
||||
"description": "success = 1, info = 2, warning = 3, error = 4",
|
||||
"type": "integer",
|
||||
"format": "uint8"
|
||||
},
|
||||
"UserId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"x-go-package": "jannex/admin-dashboard-backend/modules/structs"
|
||||
},
|
||||
"NotificationsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Notifications": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Notification"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-go-package": "jannex/admin-dashboard-backend/modules/structs"
|
||||
},
|
||||
"Role": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -1206,6 +1353,10 @@
|
|||
"type": "string"
|
||||
}
|
||||
},
|
||||
"TotalNotifications": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"UserId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package notification
|
||||
|
||||
import (
|
||||
"jannex/admin-dashboard-backend/modules/notification"
|
||||
"jannex/admin-dashboard-backend/modules/structs"
|
||||
"jannex/admin-dashboard-backend/modules/utils"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func AddNotification(c *fiber.Ctx) error {
|
||||
// swagger:operation POST /notifications notifications notificationsAddNotification
|
||||
// ---
|
||||
// summary: Add a new notification
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: X-Api-Key
|
||||
// in: header
|
||||
// description: You can create a new api key in your user profile
|
||||
// - name: body
|
||||
// in: body
|
||||
// schema:
|
||||
// "$ref": "#/definitions/AddNotificationRequest"
|
||||
// responses:
|
||||
// '200':
|
||||
// description: New notification added successfully
|
||||
// '400':
|
||||
// description: Invalid request body
|
||||
// '401':
|
||||
// description: No permissions
|
||||
// '422':
|
||||
// description: No users found
|
||||
// '500':
|
||||
// description: Failed to add notification
|
||||
|
||||
var body structs.AddNotificationRequest
|
||||
|
||||
if err := utils.BodyParserHelper(c, &body); err != nil {
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
return notification.AddNotification(c, body)
|
||||
}
|
||||
|
||||
func GetNotifications(c *fiber.Ctx) error {
|
||||
// swagger:operation GET /notifications notifications notificationsGetNotifications
|
||||
// ---
|
||||
// summary: Get notifications
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: X-Api-Key
|
||||
// in: header
|
||||
// description: You can create a new api key in your user profile
|
||||
// responses:
|
||||
// '200':
|
||||
// description: Notifications
|
||||
// schema:
|
||||
// "$ref": "#/definitions/NotificationsResponse"
|
||||
// '401':
|
||||
// description: No permissions
|
||||
// '500':
|
||||
// description: Failed to get notifications
|
||||
|
||||
return c.JSON(structs.NotificationsResponse{
|
||||
Notifications: notification.GetNotifications(c.Locals("userId").(string)),
|
||||
})
|
||||
}
|
|
@ -3,6 +3,7 @@ package user
|
|||
import (
|
||||
"jannex/admin-dashboard-backend/modules/cache"
|
||||
"jannex/admin-dashboard-backend/modules/database"
|
||||
"jannex/admin-dashboard-backend/modules/notification"
|
||||
"jannex/admin-dashboard-backend/modules/structs"
|
||||
"jannex/admin-dashboard-backend/modules/utils"
|
||||
"jannex/admin-dashboard-backend/socketclients"
|
||||
|
@ -55,5 +56,6 @@ func UserInfo(c *fiber.Ctx) error {
|
|||
Permissions: socketclients.GetPermissionsByRoleId(user.RoleId),
|
||||
AvailableCategoryGroups: categories,
|
||||
Users: socketclients.GetAllUsers(),
|
||||
TotalNotifications: notification.GetTotalNotifications(user.Id),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"jannex/admin-dashboard-backend/routers/router/api/v1/equipment"
|
||||
"jannex/admin-dashboard-backend/routers/router/api/v1/grouptasks"
|
||||
log "jannex/admin-dashboard-backend/routers/router/api/v1/logger"
|
||||
"jannex/admin-dashboard-backend/routers/router/api/v1/notification"
|
||||
"jannex/admin-dashboard-backend/routers/router/api/v1/user"
|
||||
"jannex/admin-dashboard-backend/routers/router/api/v1/users"
|
||||
"jannex/admin-dashboard-backend/socketclients"
|
||||
|
@ -56,6 +57,10 @@ func SetupRoutes(app *fiber.App) {
|
|||
a := v1.Group("/adminarea")
|
||||
a.Get("/roles", requestAccessValidation, adminarea.GetRoles)
|
||||
|
||||
ns := v1.Group("/notifications")
|
||||
ns.Get("/", requestAccessValidation, notification.GetNotifications)
|
||||
ns.Post("/", requestAccessValidation, notification.AddNotification)
|
||||
|
||||
app.Static("/", config.Cfg.FolderPaths.PublicStatic)
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ func BroadcastMessageToTopicExceptUserSessionId(topic string, ignoreUserSessionI
|
|||
}
|
||||
|
||||
func hasClientSubscribedToTopic(topic string, clientTopic string) bool {
|
||||
log.Info().Msgf("hasClientSubscribedToTopic %s %s", topic, clientTopic)
|
||||
return clientTopic == topic || strings.HasPrefix(clientTopic, topic)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"jannex/admin-dashboard-backend/modules/database"
|
||||
"jannex/admin-dashboard-backend/modules/grouptasks"
|
||||
"jannex/admin-dashboard-backend/modules/logger"
|
||||
"jannex/admin-dashboard-backend/modules/notification"
|
||||
"jannex/admin-dashboard-backend/modules/structs"
|
||||
"jannex/admin-dashboard-backend/modules/systempermissions"
|
||||
"jannex/admin-dashboard-backend/modules/utils"
|
||||
|
@ -356,6 +357,11 @@ func RunHub() {
|
|||
|
||||
cache.SubscribeSocketClientToTopic(data.Conn.Locals("sessionId").(string), receivedMessage.Body["topic"].(string))
|
||||
break
|
||||
case utils.ReceivedCmdDeleteAllNotifications:
|
||||
notification.DeleteAllNotifications(data.Conn.Locals("userId").(string))
|
||||
break
|
||||
case utils.ReceivedCmdDeleteOneNotification:
|
||||
notification.DeleteOneNotification(data.Conn.Locals("userId").(string), receivedMessage.Body["notificationId"].(string))
|
||||
default:
|
||||
log.Error().Msgf("Received unknown message: %v", receivedMessage)
|
||||
break
|
||||
|
|
Loading…
Reference in New Issue