package check_ownership import ( "fmt" "gitea.pena/SQuiz/common/dal" "gitea.pena/SQuiz/common/middleware" "github.com/gofiber/fiber/v2" "regexp" "strconv" ) type Owner interface { Check(ctx *fiber.Ctx) (bool, error) } type OwnerShip struct { dal *dal.DAL } func NewOwnerShip(dal *dal.DAL) *OwnerShip { return &OwnerShip{ dal: dal, } } // имеем id квиза и id аккаунта проверяем что квиз принадлежит аккаунту func (o *OwnerShip) CheckQuiz(ctx *fiber.Ctx) (bool, error) { accountId, ok := middleware.GetAccountId(ctx) if !ok { return false, fiber.NewError(fiber.StatusUnauthorized, "account id is required") } quizIDStr := ctx.Params("quizID") var quizID uint64 var err error if quizIDStr != "" { quizID, err = strconv.ParseUint(quizIDStr, 10, 64) if err != nil { return false, fiber.NewError(fiber.StatusBadRequest, "invalid quiz ID") } } if quizIDStr == "" { var body struct { QuizID uint64 `json:"quiz_id"` } if err := ctx.BodyParser(&body); err != nil { return false, fiber.NewError(fiber.StatusBadRequest, "invalid request data") } quizID = body.QuizID } isOwner, err := o.dal.QuizRepo.CheckQuizOwner(ctx.Context(), accountId, quizID) if err != nil { return false, fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return isOwner, nil } // имеем id результата и id аккаунта проверяем с помощью CheckResultOwner func (o *OwnerShip) CheckResult(ctx *fiber.Ctx) (bool, error) { accountID, ok := middleware.GetAccountId(ctx) if !ok { return false, fiber.NewError(fiber.StatusUnauthorized, "account id is required") } // todo интересная штука заметил что параметры на этапе промежуточного по не существует, оч сильно усложняет надо будет обдумать resultID, err := strconv.ParseUint(ctx.Params("resultID"), 10, 64) if err != nil { return false, fiber.NewError(fiber.StatusBadRequest, "invalid result ID format") } isOwner, err := o.dal.ResultRepo.CheckResultOwner(ctx.Context(), resultID, accountID) if err != nil { return false, fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return isOwner, nil } // имеем id вопроса и id аккаунта проверяем что квиз этого вопроса относится к аккаунту func (o *OwnerShip) CheckQuestion(ctx *fiber.Ctx) (bool, error) { accountID, ok := middleware.GetAccountId(ctx) if !ok { return false, fiber.NewError(fiber.StatusUnauthorized, "account id is required") } var body struct { QuestionID uint64 `json:"id"` } if err := ctx.BodyParser(&body); err != nil { return false, fiber.NewError(fiber.StatusBadRequest, "invalid request data") } isOwner, err := o.dal.QuestionRepo.CheckQuestionOwner(ctx.Context(), accountID, body.QuestionID) if err != nil { return false, fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return isOwner, nil } // проверка для лид таргета надо проверить что в лид имеет отношение к аккаунту func (o *OwnerShip) CheckLeadTarget(ctx *fiber.Ctx) (bool, error) { return true, nil } func (o *OwnerShip) CheckStatistic(ctx *fiber.Ctx) (bool, error) { return true, nil } var pathCheckMap = map[*regexp.Regexp]func(*OwnerShip, *fiber.Ctx) (bool, error){ regexp.MustCompile(`^POST /question/create$`): (*OwnerShip).CheckQuiz, // quiz_id regexp.MustCompile(`^POST /question/getList$`): (*OwnerShip).CheckQuiz, // quiz_id regexp.MustCompile(`^PATCH /question/edit$`): (*OwnerShip).CheckQuestion, // id regexp.MustCompile(`^POST /question/copy$`): (*OwnerShip).CheckQuiz, // quiz_id regexp.MustCompile(`^POST /question/history$`): (*OwnerShip).CheckQuestion, // id regexp.MustCompile(`^DELETE /question/delete$`): (*OwnerShip).CheckQuestion, // id //regexp.MustCompile(`^GET /result/\d+$`): (*OwnerShip).CheckResult, // resultID в роуте (id ответа) // todo POST /results/getResults/16675 regexp.MustCompile(`^POST /results/getResults/\d+$`): (*OwnerShip).CheckQuiz, // quizID в роуте // todo POST /results/16675/export regexp.MustCompile(`^POST /results/\d+/export$`): (*OwnerShip).CheckQuiz, // quizID в роуте // todo все роутф статистики клиентские regexp.MustCompile(`^POST /statistic/\d+/devices$`): (*OwnerShip).CheckStatistic, regexp.MustCompile(`^POST /statistic/\d+/general$`): (*OwnerShip).CheckStatistic, regexp.MustCompile(`^POST /statistic/\d+/questions$`): (*OwnerShip).CheckStatistic, // пока не в приоритете todo regexp.MustCompile(`^DELETE /account/account/leadtarget/\d+$`): (*OwnerShip).CheckLeadTarget, regexp.MustCompile(`^PUT /account/account/leadtarget$`): (*OwnerShip).CheckLeadTarget, } // todo подключить проверить func OwnerShipMiddleware(o *OwnerShip) fiber.Handler { return func(c *fiber.Ctx) error { methodPath := fmt.Sprintf("%s %s", c.Method(), c.Path()) fmt.Println(methodPath) fmt.Println(c.Params("resultID")) for re, f := range pathCheckMap { if re.MatchString(methodPath) { ok, err := f(o, c) if err != nil { return err } if !ok { return fiber.NewError(fiber.StatusForbidden, "access denied") } break } } return c.Next() } }