package grouptasks import ( "encoding/json" "jannex/admin-dashboard-backend/modules/cache" "jannex/admin-dashboard-backend/modules/database" "jannex/admin-dashboard-backend/modules/grouptasks" "jannex/admin-dashboard-backend/modules/structs" "jannex/admin-dashboard-backend/modules/utils" "jannex/admin-dashboard-backend/socketclients" "git.ex.umbach.dev/Alex/roese-utils/rspagination" "git.ex.umbach.dev/Alex/roese-utils/rsutils" "git.ex.umbach.dev/Alex/roese-utils/rsvalidator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog/log" ) func GetGroupTasks(c *fiber.Ctx) error { // swagger:operation GET /grouptasks/{category} grouptasks grouptaskGetGroupTasks // --- // summary: Get group tasks // produces: // - application/json // parameters: // - name: category // in: query // description: Category of the group tasks // required: true // - name: page // in: query // description: Page number // responses: // '200': // description: Group tasks // schema: // "$ref": "#/definitions/GroupTasksResponse" // '400': // description: Invalid request query // '401': // description: No permissions // '500': // description: Failed to get group tasks var params structs.GroupTasksRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !socketclients.HasXYPermission(c.Locals("userId").(string), utils.PermissionGroupTasksOverviewXYView, params.Category) { return c.SendStatus(fiber.StatusUnauthorized) } var query rspagination.PageQuery if err := c.QueryParser(&query); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var categoryGroup structs.CategoryGroup for _, cGroup := range cache.GetCategoryGroups() { if cGroup.Category == params.Category { categoryGroup = cGroup } } return c.JSON(structs.GroupTasksResponse{ CategoryGroup: categoryGroup, GroupTasks: grouptasks.GetAllGroupTasks(params.Category, query), TotalPages: rspagination.GetTotalPages(database.DB, utils.GroupTasksPaginationLimit, []structs.GroupTasks{}, "category = ?", params.Category), }) } func GetGroupTaskSteps(c *fiber.Ctx) error { // swagger:operation GET /grouptasks/{category}/steps/{groupTaskId} grouptasks grouptaskGetGroupTaskSteps // --- // summary: Get group task steps // produces: // - application/json // parameters: // - name: category // in: query // description: Category of the group tasks // required: true // - name: groupTaskId // in: query // description: Id of the group task // required: true // responses: // '200': // description: Group task steps // schema: // "$ref": "#/definitions/GroupTaskSteps" // '400': // description: Invalid request query // '401': // description: No permissions // '500': // description: Failed to get group task steps var params structs.GroupTaskStepsRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !socketclients.HasXYPermission(c.Locals("userId").(string), utils.PermissionGroupTasksOverviewXYView, params.Category) { return c.SendStatus(fiber.StatusUnauthorized) } return c.JSON(grouptasks.GetGroupTaskSteps(params.GroupTaskId)) } func StartGroupTask(c *fiber.Ctx) error { // swagger:operation POST /grouptasks/start grouptasks grouptaskStartGroupTask // --- // summary: Start a new group task // 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/ApiGroupTaskRequest" // responses: // '200': // description: New group task started successfully // '400': // description: Invalid request body // '401': // description: No permissions // '422': // description: Global inputs are not complete or no group tasks in this category // '500': // description: Failed to start group task 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 := rsvalidator.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 rsutils.MarshalJson(globalInputs) }