api key usage
parent
0d545ebc86
commit
679f6a16a1
|
@ -895,3 +895,39 @@ func StartUnlockLockedGroupTaskStepsTicker() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func StartGroupTask(userId string, groupTask structs.GroupTasks) {
|
||||
groupTask.Id = uuid.New().String()
|
||||
groupTask.CreatorUserId = userId
|
||||
groupTask.CurrentTasksStep = 1
|
||||
groupTask.Status = utils.GroupTasksStatusRunning
|
||||
groupTask.StartedAt = time.Now()
|
||||
|
||||
database.DB.Create(&groupTask)
|
||||
|
||||
socketclients.BroadcastMessage(structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdNewGroupTaskStarted,
|
||||
Body: groupTask,
|
||||
})
|
||||
|
||||
go RunGroupTask(RunGroupTaskArgs{
|
||||
CreatorUserId: userId,
|
||||
StartType: RunGroupTaskStartTypeNormal,
|
||||
GroupTaskId: groupTask.Id,
|
||||
Category: groupTask.Category,
|
||||
GroupId: groupTask.GroupId,
|
||||
Step: 1,
|
||||
TaskStepId: "",
|
||||
GlobalInputs: groupTask.GlobalInputs,
|
||||
})
|
||||
|
||||
logger.AddGroupTasksLog(structs.LogMessage{
|
||||
Id: 0,
|
||||
Type: utils.LogTypeInfo,
|
||||
Messages: []structs.LogData{
|
||||
{Type: "userId", Value: userId},
|
||||
{Type: "groupTaskId", Value: groupTask.Id},
|
||||
{Type: "groupTaskName", Value: groupTask.GroupName},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package structs
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type ApiGroupTaskRequest struct {
|
||||
Category string
|
||||
GroupId string
|
||||
Description string
|
||||
GlobalInputs map[string]string
|
||||
GlobalInputs json.RawMessage
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ const (
|
|||
LenHeaderXAuthorization = 36
|
||||
lenHeaderXAuthorization = "36"
|
||||
LenUserId = 36
|
||||
LenHeaderXApiKey = 36
|
||||
|
||||
HeaderXAuthorization = "X-Authorization"
|
||||
HeaderXApiKey = "X-Api-Key"
|
||||
|
||||
MaxAvatarSize = 5 * 1024 * 1024 // 5 MB
|
||||
|
||||
|
@ -62,6 +64,8 @@ const (
|
|||
SentCmdAllUsersUserDeactivation = 28
|
||||
SentCmdGroupTasksCategoryGroupChanges = 29
|
||||
SentCmdNewUserApiKeyCreated = 30
|
||||
SentCmdDeletedUserApiKey = 31
|
||||
SentCmdNewApiKeyUsageCount = 32
|
||||
)
|
||||
|
||||
// commands received from web clients
|
||||
|
@ -105,6 +109,13 @@ var (
|
|||
"SessionId": "required,len=" + lenHeaderXAuthorization,
|
||||
"ScannerName": "required,min=" + minScannerName + ",max=" + maxScannerName,
|
||||
}
|
||||
|
||||
groupTaskRules = map[string]string{
|
||||
"Category": "required",
|
||||
"GroupId": "required",
|
||||
"Description": "required",
|
||||
"GlobalInputs": "required",
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -128,6 +139,8 @@ const (
|
|||
PermissionAdminAreaDeleteRole = _adminAreaRoles + "delete_role"
|
||||
PermissionAdminAreaMoveRoleUpDown = _adminAreaRoles + "move_role_up_down"
|
||||
PermissionAdminAreaLogs = _adminArea + "logs"
|
||||
|
||||
PermissionUserProfileApiKeys = "user_profile.api_keys"
|
||||
)
|
||||
|
||||
var SystemPermissions = []string{
|
||||
|
@ -143,6 +156,7 @@ var SystemPermissions = []string{
|
|||
PermissionAdminAreaDeleteRole,
|
||||
PermissionAdminAreaMoveRoleUpDown,
|
||||
PermissionAdminAreaLogs,
|
||||
PermissionUserProfileApiKeys,
|
||||
}
|
||||
|
||||
var DynamicGroupTasksPermissions = []string{
|
||||
|
|
|
@ -14,6 +14,10 @@ func GetXAuhorizationHeader(c *fiber.Ctx) string {
|
|||
return c.GetReqHeaders()[HeaderXAuthorization]
|
||||
}
|
||||
|
||||
func GetXApiKeyHeader(c *fiber.Ctx) string {
|
||||
return c.GetReqHeaders()[HeaderXApiKey]
|
||||
}
|
||||
|
||||
func MarshalJson(v any) string {
|
||||
json, err := json.Marshal(v)
|
||||
|
||||
|
|
|
@ -34,4 +34,7 @@ func ValidatorInit() {
|
|||
structs.UserLoginRequest{},
|
||||
structs.UserSignOutSessionRequest{},
|
||||
structs.ScannerRequest{})
|
||||
|
||||
Validate.RegisterStructValidationMapRules(groupTaskRules,
|
||||
structs.ApiGroupTaskRequest{})
|
||||
}
|
||||
|
|
|
@ -1,20 +1,120 @@
|
|||
package grouptask
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"janex/admin-dashboard-backend/modules/cache"
|
||||
"janex/admin-dashboard-backend/modules/grouptasks"
|
||||
"janex/admin-dashboard-backend/modules/structs"
|
||||
"janex/admin-dashboard-backend/modules/utils"
|
||||
"janex/admin-dashboard-backend/socketclients"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type b struct {
|
||||
}
|
||||
|
||||
func StartGroupTask(c *fiber.Ctx) error {
|
||||
var body b
|
||||
var body structs.ApiGroupTaskRequest
|
||||
|
||||
if err := c.BodyParser(&body); err != nil {
|
||||
log.Error().Msg("Failed to parse body, err: " + err.Error())
|
||||
return c.Status(fiber.StatusBadRequest).JSON(err)
|
||||
}
|
||||
|
||||
if errValidation := utils.ValidateStruct(body); errValidation != nil {
|
||||
log.Error().Msgf("Failed to validate body, err: %v", errValidation)
|
||||
return c.Status(fiber.StatusBadRequest).JSON(errValidation)
|
||||
}
|
||||
|
||||
userId := c.Locals("userId").(string)
|
||||
|
||||
if !socketclients.HasPermission(userId, utils.PermissionUserProfileApiKeys) || !socketclients.HasXYPermission(userId, utils.PermissionGroupTasksOverviewXYNewTask, body.Category) {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
categoryGroup := cache.GetCategoryGroupByCategory(body.Category)
|
||||
|
||||
if categoryGroup.Category == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSONP(fiber.Map{"err": "Category not found"})
|
||||
}
|
||||
|
||||
group := getGroupFromCategoryGroup(categoryGroup, body.GroupId)
|
||||
|
||||
if group.Category == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSONP(fiber.Map{"err": "GroupId not found"})
|
||||
}
|
||||
|
||||
var bodyGlobalInputs []map[string]string
|
||||
|
||||
err := json.Unmarshal(body.GlobalInputs, &bodyGlobalInputs)
|
||||
|
||||
if err != nil {
|
||||
log.Error().Msgf("Failed to unmarshal body global inputs: %v", err)
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(group.Tasks) == 0 || !globalInputsComplete(bodyGlobalInputs, group.GlobalInputs) {
|
||||
return c.SendStatus(fiber.StatusUnprocessableEntity)
|
||||
}
|
||||
|
||||
grouptasks.StartGroupTask(userId, structs.GroupTasks{
|
||||
Category: body.Category,
|
||||
GroupId: body.GroupId,
|
||||
GroupName: group.Name,
|
||||
Description: body.Description,
|
||||
NumberOfSteps: uint8(len(group.Tasks)),
|
||||
GlobalInputs: convertJsonGlobalInputToStruct(bodyGlobalInputs, group.GlobalInputs),
|
||||
})
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func getGroupFromCategoryGroup(categoryGroup structs.CategoryGroup, groupId string) structs.Group {
|
||||
for _, group := range categoryGroup.Groups {
|
||||
if group.Id == groupId {
|
||||
return group
|
||||
}
|
||||
}
|
||||
|
||||
return structs.Group{}
|
||||
}
|
||||
|
||||
func globalInputsComplete(bodyGlobalInputs []map[string]string, groupGlobalInputs []structs.GlobalInputs) bool {
|
||||
for _, gGlobalInput := range groupGlobalInputs {
|
||||
if !isInList(gGlobalInput.ParameterName, bodyGlobalInputs) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isInList(gParameterName string, bodyInputs []map[string]string) bool {
|
||||
for _, bInput := range bodyInputs {
|
||||
if bInput[gParameterName] != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type GlobalInputs struct {
|
||||
ParameterName string `json:"parameterName"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func convertJsonGlobalInputToStruct(bodyGlobalInputs []map[string]string, groupGlobalInputs []structs.GlobalInputs) string {
|
||||
var globalInputs []GlobalInputs
|
||||
|
||||
for _, gGlobalInput := range groupGlobalInputs {
|
||||
for _, bInput := range bodyGlobalInputs {
|
||||
if bInput[gGlobalInput.ParameterName] != "" {
|
||||
globalInputs = append(globalInputs, GlobalInputs{
|
||||
ParameterName: gGlobalInput.ParameterName,
|
||||
Value: bInput[gGlobalInput.ParameterName],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return utils.MarshalJson(globalInputs)
|
||||
}
|
||||
|
|
|
@ -3,14 +3,18 @@ package router
|
|||
import (
|
||||
"janex/admin-dashboard-backend/modules/config"
|
||||
"janex/admin-dashboard-backend/modules/database"
|
||||
"janex/admin-dashboard-backend/modules/logger"
|
||||
"janex/admin-dashboard-backend/modules/structs"
|
||||
"janex/admin-dashboard-backend/modules/utils"
|
||||
"janex/admin-dashboard-backend/routers/router/api/v1/grouptask"
|
||||
"janex/admin-dashboard-backend/routers/router/api/v1/jxscanner"
|
||||
log "janex/admin-dashboard-backend/routers/router/api/v1/logger"
|
||||
"janex/admin-dashboard-backend/routers/router/api/v1/user"
|
||||
"janex/admin-dashboard-backend/socketclients"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func SetupRoutes(app *fiber.App) {
|
||||
|
@ -31,11 +35,59 @@ func SetupRoutes(app *fiber.App) {
|
|||
l.Get("/", userSessionValidation, log.GetSystemLog)
|
||||
|
||||
g := v1.Group("/grouptasks")
|
||||
g.Post("/", grouptask.StartGroupTask)
|
||||
g.Post("/start", userApikeyTokenValidation, grouptask.StartGroupTask)
|
||||
|
||||
app.Static("/", config.Cfg.FolderPaths.PublicStatic)
|
||||
}
|
||||
|
||||
func userApikeyTokenValidation(c *fiber.Ctx) error {
|
||||
xApikey := utils.GetXApiKeyHeader(c)
|
||||
|
||||
if len(xApikey) != utils.LenHeaderXApiKey {
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
var apiKey structs.UserApiKey
|
||||
|
||||
database.DB.Select("id, user_id, token, usage_count").First(&apiKey, "token = ?", xApikey)
|
||||
|
||||
if apiKey.Token != xApikey {
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
lastUsed := time.Now()
|
||||
|
||||
database.DB.Model(&structs.UserApiKey{}).Where("id = ?", apiKey.Id).Updates(map[string]interface{}{
|
||||
"usage_count": gorm.Expr("usage_count + ?", 1),
|
||||
"last_used": lastUsed,
|
||||
})
|
||||
|
||||
c.Locals("userId", apiKey.UserId)
|
||||
|
||||
socketclients.SendMessageToUser(apiKey.UserId, "", structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdNewApiKeyUsageCount,
|
||||
Body: struct {
|
||||
Id string
|
||||
UsageCount uint
|
||||
LastUsed time.Time
|
||||
}{
|
||||
Id: apiKey.Id,
|
||||
UsageCount: (apiKey.UsageCount + 1),
|
||||
LastUsed: lastUsed,
|
||||
},
|
||||
})
|
||||
|
||||
logger.AddSystemLog(structs.LogMessage{
|
||||
Id: 25,
|
||||
Type: utils.LogTypeInfo,
|
||||
Messages: []structs.LogData{
|
||||
{Type: "userId", Value: apiKey.UserId},
|
||||
},
|
||||
})
|
||||
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func userSessionValidation(c *fiber.Ctx) error {
|
||||
xAuthorization := utils.GetXAuhorizationHeader(c)
|
||||
|
||||
|
@ -47,7 +99,7 @@ func userSessionValidation(c *fiber.Ctx) error {
|
|||
|
||||
database.DB.First(&userSession, "id = ?", xAuthorization)
|
||||
|
||||
if len(userSession.Id) != utils.LenHeaderXAuthorization {
|
||||
if userSession.Id != xAuthorization {
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
|
@ -67,7 +119,7 @@ func scannerSessionValidation(c *fiber.Ctx) error {
|
|||
|
||||
database.DB.First(&scanner, "session = ?", xAuthorization)
|
||||
|
||||
if len(scanner.Session) != utils.LenHeaderXAuthorization {
|
||||
if scanner.Session != xAuthorization {
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
|
|
|
@ -962,4 +962,29 @@ func CreateNewUserApiKey(userId string, apiName string) {
|
|||
Cmd: utils.SentCmdNewUserApiKeyCreated,
|
||||
Body: newApiKey,
|
||||
})
|
||||
|
||||
logger.AddSystemLog(structs.LogMessage{
|
||||
Id: 23,
|
||||
Type: utils.LogTypeInfo,
|
||||
Messages: []structs.LogData{
|
||||
{Type: "userId", Value: userId},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteUserApiKey(userId string, apiKey string) {
|
||||
database.DB.Where("id = ?", apiKey).Where("user_id = ?", userId).Delete(&structs.UserApiKey{})
|
||||
|
||||
SendMessageToUser(userId, "", structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdDeletedUserApiKey,
|
||||
Body: apiKey,
|
||||
})
|
||||
|
||||
logger.AddSystemLog(structs.LogMessage{
|
||||
Id: 24,
|
||||
Type: utils.LogTypeInfo,
|
||||
Messages: []structs.LogData{
|
||||
{Type: "userId", Value: userId},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -118,50 +118,63 @@ func RunHub() {
|
|||
|
||||
globalInputsJsonString := utils.MarshalJson(receivedMessage.Body["globalInputs"])
|
||||
|
||||
groupTaskId := uuid.New().String()
|
||||
grouptasks.StartGroupTask(data.Conn.Locals("userId").(string),
|
||||
structs.GroupTasks{
|
||||
Category: category,
|
||||
GroupId: groupId,
|
||||
GroupName: receivedMessage.Body["groupName"].(string),
|
||||
Description: receivedMessage.Body["description"].(string),
|
||||
NumberOfSteps: uint8(receivedMessage.Body["numberOfSteps"].(float64)),
|
||||
GlobalInputs: globalInputsJsonString,
|
||||
RememberId: receivedMessage.Body["rememberId"].(string),
|
||||
})
|
||||
|
||||
groupTasks := &structs.GroupTasks{
|
||||
Id: groupTaskId,
|
||||
CreatorUserId: data.Conn.Locals("userId").(string),
|
||||
Category: category,
|
||||
GroupId: groupId,
|
||||
GroupName: receivedMessage.Body["groupName"].(string),
|
||||
Description: receivedMessage.Body["description"].(string),
|
||||
CurrentTasksStep: 1,
|
||||
NumberOfSteps: uint8(receivedMessage.Body["numberOfSteps"].(float64)),
|
||||
Status: utils.GroupTasksStatusRunning,
|
||||
GlobalInputs: globalInputsJsonString,
|
||||
StartedAt: time.Now(),
|
||||
RememberId: receivedMessage.Body["rememberId"].(string),
|
||||
}
|
||||
//groupTaskId := uuid.New().String()
|
||||
|
||||
database.DB.Create(groupTasks)
|
||||
/*
|
||||
groupTasks := structs.GroupTasks{
|
||||
Id: groupTaskId,
|
||||
CreatorUserId: data.Conn.Locals("userId").(string),
|
||||
Category: category,
|
||||
GroupId: groupId,
|
||||
GroupName: receivedMessage.Body["groupName"].(string),
|
||||
Description: receivedMessage.Body["description"].(string),
|
||||
CurrentTasksStep: 1,
|
||||
NumberOfSteps: uint8(receivedMessage.Body["numberOfSteps"].(float64)),
|
||||
Status: utils.GroupTasksStatusRunning,
|
||||
GlobalInputs: globalInputsJsonString,
|
||||
StartedAt: time.Now(),
|
||||
RememberId: receivedMessage.Body["rememberId"].(string),
|
||||
}
|
||||
|
||||
socketclients.BroadcastMessage(structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdNewGroupTaskStarted,
|
||||
Body: groupTasks,
|
||||
})
|
||||
database.DB.Create(&groupTasks)
|
||||
|
||||
go grouptasks.RunGroupTask(grouptasks.RunGroupTaskArgs{
|
||||
CreatorUserId: data.Conn.Locals("userId").(string),
|
||||
StartType: grouptasks.RunGroupTaskStartTypeNormal,
|
||||
GroupTaskId: groupTaskId,
|
||||
Category: category,
|
||||
GroupId: groupId,
|
||||
Step: 1,
|
||||
TaskStepId: "",
|
||||
GlobalInputs: globalInputsJsonString,
|
||||
})
|
||||
socketclients.BroadcastMessage(structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdNewGroupTaskStarted,
|
||||
Body: groupTasks,
|
||||
})
|
||||
|
||||
go grouptasks.RunGroupTask(grouptasks.RunGroupTaskArgs{
|
||||
CreatorUserId: data.Conn.Locals("userId").(string),
|
||||
StartType: grouptasks.RunGroupTaskStartTypeNormal,
|
||||
GroupTaskId: groupTaskId,
|
||||
Category: category,
|
||||
GroupId: groupId,
|
||||
Step: 1,
|
||||
TaskStepId: "",
|
||||
GlobalInputs: globalInputsJsonString,
|
||||
})
|
||||
|
||||
logger.AddGroupTasksLog(structs.LogMessage{
|
||||
Id: 0,
|
||||
Type: utils.LogTypeInfo,
|
||||
Messages: []structs.LogData{
|
||||
{Type: "userId", Value: data.Conn.Locals("userId").(string)},
|
||||
{Type: "groupTaskId", Value: groupTaskId},
|
||||
{Type: "groupTaskName", Value: groupTasks.GroupName},
|
||||
},
|
||||
}) */
|
||||
|
||||
logger.AddGroupTasksLog(structs.LogMessage{
|
||||
Id: 0,
|
||||
Type: utils.LogTypeInfo,
|
||||
Messages: []structs.LogData{
|
||||
{Type: "userId", Value: data.Conn.Locals("userId").(string)},
|
||||
{Type: "groupTaskId", Value: groupTaskId},
|
||||
{Type: "groupTaskName", Value: groupTasks.GroupName},
|
||||
},
|
||||
})
|
||||
break
|
||||
case utils.ReceivedCmdTaskFailedTryAgainRunTaskStep:
|
||||
groupTaskArgs := grouptasks.RunGroupTaskArgs{
|
||||
|
@ -371,13 +384,18 @@ func RunHub() {
|
|||
grouptasks.LookingForCategoryGroupChanges(data.Conn.Locals("userId").(string))
|
||||
break
|
||||
case utils.ReceivedCmdHandleUserActionTaskStep:
|
||||
if !socketclients.HasXYPermission(data.Conn.Locals("userId").(string), utils.PermissionGroupTasksOverviewXYReloadGroupConfig, receivedMessage.Body["category"].(string)) {
|
||||
socketclients.SendErrorMessageNoPermissions(data.Conn.Locals("sessionId").(string))
|
||||
break
|
||||
}
|
||||
|
||||
grouptasks.HandleUserActionTaskStep(data.Conn.Locals("userId").(string), receivedMessage.Body)
|
||||
break
|
||||
case utils.ReceivedCmdCreateNewUserApiKey:
|
||||
socketclients.CreateNewUserApiKey(data.Conn.Locals("userId").(string), receivedMessage.Body["Name"].(string))
|
||||
break
|
||||
case utils.ReceivedCmdDeleteUserApiKey:
|
||||
|
||||
socketclients.DeleteUserApiKey(data.Conn.Locals("userId").(string), receivedMessage.Body["Id"].(string))
|
||||
break
|
||||
|
||||
default:
|
||||
|
|
|
@ -297,5 +297,44 @@
|
|||
"message": "%userId% hat eine seiner Sitzungen ausgeloggt"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
"message": "%userId% has created an API key"
|
||||
},
|
||||
{
|
||||
"lang": "de",
|
||||
"message": "%userId% hat einen API-Schlüssel erstellt"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
"message": "%userId% has deleted one of its api keys"
|
||||
},
|
||||
{
|
||||
"lang": "de",
|
||||
"message": "%userId% hat einen seiner Api-Schlüssel gelöscht"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
"message": "%userId% has used one of its api keys"
|
||||
},
|
||||
{
|
||||
"lang": "de",
|
||||
"message": "%userId% hat einen seiner Api-Schlüssel verwendet"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue