core/internal/controllers/http_controllers/quiz/quiz.go

656 lines
19 KiB
Go
Raw Normal View History

2024-10-25 15:26:03 +00:00
package quiz
2024-02-19 17:48:04 +00:00
import (
2025-05-08 21:03:37 +00:00
"fmt"
2025-02-27 13:10:51 +00:00
"gitea.pena/PenaSide/common/log_mw"
2025-02-24 17:06:12 +00:00
"gitea.pena/SQuiz/common/dal"
2025-02-27 13:10:51 +00:00
"gitea.pena/SQuiz/common/middleware"
"gitea.pena/SQuiz/common/model"
"gitea.pena/SQuiz/common/repository/quiz"
2025-05-14 21:51:35 +00:00
"gitea.pena/SQuiz/core/internal/brokers"
2025-02-24 17:06:12 +00:00
"gitea.pena/SQuiz/core/internal/models"
2025-05-08 21:03:37 +00:00
"github.com/gofiber/fiber/v2"
2025-05-15 08:58:21 +00:00
"strconv"
2024-02-19 17:48:04 +00:00
"time"
"unicode/utf8"
)
2024-10-25 15:26:03 +00:00
type Deps struct {
2025-05-15 08:58:21 +00:00
DAL *dal.DAL
ProducerGigaChat *brokers.Producer
2024-10-25 15:26:03 +00:00
}
type Quiz struct {
2025-05-15 08:58:21 +00:00
dal *dal.DAL
producerGigaChat *brokers.Producer
2024-10-25 15:26:03 +00:00
}
func NewQuizController(deps Deps) *Quiz {
2025-05-15 08:58:21 +00:00
return &Quiz{
dal: deps.DAL,
producerGigaChat: deps.ProducerGigaChat,
}
2024-10-25 15:26:03 +00:00
}
2024-02-19 17:48:04 +00:00
type CreateQuizReq struct {
Fingerprinting bool `json:"fingerprinting"` // true if you need to store device id
Repeatable bool `json:"repeatable"` // make it true for allow more than one quiz checkouting
NotePrevented bool `json:"note_prevented"` // note answers even if the quiz was aborted
MailNotifications bool `json:"mail_notifications"` // set true if you want get an email with every quiz passing
UniqueAnswers bool `json:"unique_answers"` // set true if we you mention only last quiz passing
2024-04-20 09:45:24 +00:00
Name string `json:"name"` // max 700 chars
2024-02-19 17:48:04 +00:00
Description string `json:"description"`
Config string `json:"config"` // serialize json with config for page rules. fill it up only if implement one form scenario
Status string `json:"status"` // status of quiz as enum. see Status const. fill it up only if implement one form scenario
Limit uint64 `json:"limit"` // max count of quiz passing
DueTo uint64 `json:"due_to"` // time when quiz is end
QuestionCnt uint64 `json:"question_cnt"` // for creating at one request
TimeOfPassing uint64 `json:"time_of_passing"` // amount of seconds for give all appropriate answers for quiz
Pausable bool `json:"pausable"` // true allows to pause the quiz taking
Super bool `json:"super"` // set true if you want to create group
GroupId uint64 `json:"group_id"` // if you create quiz in group provide there the id of super quiz
}
// CreateQuiz handler for quiz creating request
2024-10-25 15:26:03 +00:00
func (r *Quiz) CreateQuiz(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req CreateQuizReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
hlogger := log_mw.ExtractLogger(ctx)
2024-06-02 09:36:22 +00:00
2024-02-19 17:48:04 +00:00
// check that we can store name
2024-04-20 09:45:24 +00:00
if utf8.RuneCountInString(req.Name) > 700 {
return ctx.Status(fiber.StatusUnprocessableEntity).SendString("name field should have less then 700 chars")
2024-02-19 17:48:04 +00:00
}
// status should be empty or equal one of status enum strings
// I mean not draft, template, stop, start statuses
if req.Status != "" &&
req.Status != model.StatusDraft &&
req.Status != model.StatusTemplate &&
2025-04-16 21:17:58 +00:00
req.Status != model.StatusAI &&
2024-02-19 17:48:04 +00:00
req.Status != model.StatusStop &&
req.Status != model.StatusStart {
return ctx.Status(fiber.StatusNotAcceptable).SendString("status on creating must be only draft,template,stop,start")
}
// DueTo should be bigger then now
if req.DueTo != 0 && req.DueTo <= uint64(time.Now().Unix()) {
return ctx.Status(fiber.StatusNotAcceptable).SendString("due to time must be lesser then now")
}
// you can pause quiz only if it has deadline for passing
if req.Pausable && req.TimeOfPassing == 0 {
return ctx.Status(fiber.StatusConflict).SendString("you can pause quiz only if it has deadline for passing")
}
record := model.Quiz{
AccountId: accountId,
Fingerprinting: req.Fingerprinting,
Repeatable: req.Repeatable,
NotePrevented: req.NotePrevented,
MailNotifications: req.MailNotifications,
UniqueAnswers: req.UniqueAnswers,
Name: req.Name,
Description: req.Description,
Config: req.Config,
Status: req.Status,
Limit: req.Limit,
DueTo: req.DueTo,
TimeOfPassing: req.TimeOfPassing,
Pausable: req.Pausable,
QuestionsCount: req.QuestionCnt,
ParentIds: []int32{},
Super: req.Super,
GroupId: req.GroupId,
}
2024-10-25 15:26:03 +00:00
quizID, err := r.dal.QuizRepo.CreateQuiz(ctx.Context(), &record)
2024-06-02 09:36:22 +00:00
if err != nil {
2024-02-19 17:48:04 +00:00
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
2024-06-02 09:36:22 +00:00
hlogger.Emit(models.InfoQuizCreated{
CtxUserID: accountId,
2025-05-08 21:03:37 +00:00
CtxIDInt: int64(quizID),
2024-06-02 09:36:22 +00:00
})
2024-02-19 17:48:04 +00:00
return ctx.Status(fiber.StatusCreated).JSON(record)
}
// GetQuizListReq request struct for paginated quiz table
type GetQuizListReq struct {
Limit uint64 `json:"limit"`
Page uint64 `json:"page"`
From int64 `json:"from"`
To int64 `json:"to"`
Search string `json:"search"`
Status string `json:"status"`
Deleted bool `json:"deleted"`
Archived bool `json:"archived"`
Super bool `json:"super"`
GroupId uint64 `json:"group_id"`
}
type GetQuizListResp struct {
Count uint64 `json:"count"`
Items []model.Quiz `json:"items"`
}
// GetQuizList handler for paginated list quiz
2024-10-25 15:26:03 +00:00
func (r *Quiz) GetQuizList(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req GetQuizListReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
if req.Status != "" &&
req.Status != model.StatusStop &&
req.Status != model.StatusStart &&
req.Status != model.StatusDraft &&
req.Status != model.StatusTemplate &&
2025-04-16 21:17:58 +00:00
req.Status != model.StatusAI &&
2024-02-19 17:48:04 +00:00
req.Status != model.StatusTimeout &&
req.Status != model.StatusOffLimit {
return ctx.Status(fiber.StatusNotAcceptable).SendString("inappropriate status, allowed only '', " +
"'stop','start','draft', 'template','timeout','offlimit'")
}
2024-10-25 15:26:03 +00:00
res, cnt, err := r.dal.QuizRepo.GetQuizList(ctx.Context(),
2024-02-19 17:48:04 +00:00
quiz.GetQuizListDeps{
Limit: req.Limit,
Offset: req.Limit * req.Page,
From: uint64(req.From),
To: uint64(req.To),
Group: req.GroupId,
Deleted: req.Deleted,
Archived: req.Archived,
Super: req.Super,
Search: req.Search,
Status: req.Status,
AccountId: accountId,
})
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.JSON(GetQuizListResp{
Items: res,
Count: cnt,
})
}
type UpdateQuizReq struct {
Id uint64 `json:"id"`
Fingerprinting bool `json:"fp"`
Repeatable bool `json:"rep"`
NotePrevented bool `json:"note_prevented"`
MailNotifications bool `json:"mailing"`
UniqueAnswers bool `json:"uniq"`
Name string `json:"name"`
Description string `json:"desc"`
Config string `json:"conf"`
Status string `json:"status"`
Limit uint64 `json:"limit"`
DueTo uint64 `json:"due_to"`
TimeOfPassing uint64 `json:"time_of_passing"`
Pausable bool `json:"pausable"`
QuestionCnt uint64 `json:"question_cnt"` // for creating at one request
Super bool `json:"super"`
GroupId uint64 `json:"group_id"`
}
2024-10-25 15:26:03 +00:00
type UpdateResp struct {
Updated uint64 `json:"updated"`
}
func (r *Quiz) UpdateQuiz(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req UpdateQuizReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
hlogger := log_mw.ExtractLogger(ctx)
2024-06-02 09:36:22 +00:00
2024-02-19 17:48:04 +00:00
if req.Id == 0 {
return ctx.Status(fiber.StatusFailedDependency).SendString("need id of question for update")
}
2024-04-20 09:45:24 +00:00
if utf8.RuneCountInString(req.Name) > 700 {
return ctx.Status(fiber.StatusUnprocessableEntity).SendString("name field should have less then 700 chars")
2024-02-19 17:48:04 +00:00
}
// status should be empty or equal one of status enum strings
// I mean not draft, template, stop, start statuses
if req.Status != "" &&
req.Status != model.StatusDraft &&
req.Status != model.StatusTemplate &&
2025-04-16 21:17:58 +00:00
req.Status != model.StatusAI &&
2024-02-19 17:48:04 +00:00
req.Status != model.StatusStop &&
req.Status != model.StatusStart {
return ctx.Status(fiber.StatusNotAcceptable).SendString("status on creating must be only draft,template,stop,start")
}
// DueTo should be bigger then now
if req.DueTo != 0 && req.DueTo <= uint64(time.Now().Unix()) {
return ctx.Status(fiber.StatusNotAcceptable).SendString("due to time must be lesser then now")
}
// you can pause quiz only if it has deadline for passing
if req.Pausable && req.TimeOfPassing == 0 {
return ctx.Status(fiber.StatusConflict).SendString("you can pause quiz only if it has deadline for passing")
}
2024-10-25 15:26:03 +00:00
quiz, err := r.dal.QuizRepo.MoveToHistoryQuiz(ctx.Context(), req.Id, accountId)
2024-02-19 17:48:04 +00:00
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
quiz.ParentIds = append(quiz.ParentIds, int32(quiz.Id))
quiz.Id = req.Id
quiz.Version += 1
if req.Fingerprinting != quiz.Fingerprinting {
quiz.Fingerprinting = req.Fingerprinting
}
if req.Repeatable != quiz.Repeatable {
quiz.Repeatable = req.Repeatable
}
if req.MailNotifications != quiz.MailNotifications {
quiz.MailNotifications = req.MailNotifications
}
if req.NotePrevented != quiz.NotePrevented {
quiz.NotePrevented = req.NotePrevented
}
if req.UniqueAnswers != quiz.UniqueAnswers {
quiz.UniqueAnswers = req.UniqueAnswers
}
if req.Pausable != quiz.Pausable {
quiz.Pausable = req.Pausable
}
if req.Name != "" && req.Name != quiz.Name {
quiz.Name = req.Name
}
if req.Description != "" && req.Description != quiz.Description {
quiz.Description = req.Description
}
if req.Status != "" && req.Status != quiz.Status {
quiz.Status = req.Status
}
if req.TimeOfPassing != quiz.TimeOfPassing {
quiz.TimeOfPassing = req.TimeOfPassing
}
if req.DueTo != quiz.DueTo {
quiz.DueTo = req.DueTo
}
if req.Limit != quiz.Limit {
quiz.Limit = req.Limit
}
if req.Config != "" && req.Config != quiz.Config {
quiz.Config = req.Config
}
if req.Super != quiz.Super {
quiz.Super = req.Super
}
if req.GroupId != quiz.GroupId {
quiz.GroupId = req.GroupId
}
quiz.QuestionsCount = req.QuestionCnt
quiz.ParentIds = append(quiz.ParentIds, int32(quiz.Id))
2024-10-25 15:26:03 +00:00
if err := r.dal.QuizRepo.UpdateQuiz(ctx.Context(), accountId, quiz); err != nil {
2024-02-19 17:48:04 +00:00
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
2024-06-02 09:36:22 +00:00
if req.Status == model.StatusStart {
hlogger.Emit(models.InfoQuizPublish{
CtxUserID: accountId,
2025-05-08 21:03:37 +00:00
CtxIDInt: int64(quiz.Id),
2024-06-02 09:36:22 +00:00
})
}
if req.Status == model.StatusStop {
hlogger.Emit(models.InfoQuizStop{
CtxUserID: accountId,
2025-05-08 21:03:37 +00:00
CtxIDInt: int64(quiz.Id),
2024-06-02 09:36:22 +00:00
})
}
2024-02-19 17:48:04 +00:00
return ctx.JSON(UpdateResp{
Updated: quiz.Id,
})
}
// CopyQuizReq request struct for copy quiz
type CopyQuizReq struct {
Id uint64 `json:"id"`
}
// CopyQuiz request handler for copy quiz
2024-10-25 15:26:03 +00:00
func (r *Quiz) CopyQuiz(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req CopyQuizReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
if req.Id == 0 {
return ctx.Status(fiber.StatusFailedDependency).SendString("no id provided")
}
2024-10-25 15:26:03 +00:00
quiz, err := r.dal.QuizRepo.CopyQuiz(ctx.Context(), accountId, req.Id)
2024-02-19 17:48:04 +00:00
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.JSON(UpdateResp{
Updated: quiz.Id,
})
}
// GetQuizHistoryReq struct of get history request
type GetQuizHistoryReq struct {
Id uint64 `json:"id"`
Limit uint64 `json:"l"`
Page uint64 `json:"p"`
}
// GetQuizHistory handler for history of quiz
2024-10-25 15:26:03 +00:00
func (r *Quiz) GetQuizHistory(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req GetQuizHistoryReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
if req.Id == 0 {
return ctx.Status(fiber.StatusFailedDependency).SendString("no id provided")
}
2024-10-25 15:26:03 +00:00
history, err := r.dal.QuizRepo.QuizHistory(ctx.Context(), quiz.QuizHistoryDeps{
2024-02-19 17:48:04 +00:00
Id: req.Id,
Limit: req.Limit,
Offset: req.Page * req.Limit,
AccountId: accountId,
})
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.Status(fiber.StatusCreated).JSON(history)
}
// DeactivateReq request structure for archiving and deleting
type DeactivateReq struct {
Id uint64 `json:"id"`
}
type DeactivateResp struct {
Deactivated uint64 `json:"deactivated"`
}
// DeleteQuiz handler for fake delete quiz
2024-10-25 15:26:03 +00:00
func (r *Quiz) DeleteQuiz(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req DeactivateReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
hlogger := log_mw.ExtractLogger(ctx)
2024-02-19 17:48:04 +00:00
if req.Id == 0 {
return ctx.Status(fiber.StatusFailedDependency).SendString("id for deleting is required")
}
2024-10-25 15:26:03 +00:00
deleted, err := r.dal.QuizRepo.DeleteQuiz(ctx.Context(), accountId, req.Id)
2024-02-19 17:48:04 +00:00
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
2024-06-02 09:36:22 +00:00
hlogger.Emit(models.InfoQuizDelete{
CtxUserID: accountId,
2025-05-08 21:03:37 +00:00
CtxIDInt: int64(req.Id),
2024-06-02 09:36:22 +00:00
})
2024-02-19 17:48:04 +00:00
return ctx.JSON(DeactivateResp{
Deactivated: deleted.Id,
})
}
// ArchiveQuiz handler for archiving quiz
2024-10-25 15:26:03 +00:00
func (r *Quiz) ArchiveQuiz(ctx *fiber.Ctx) error {
2024-02-19 17:48:04 +00:00
var req DeactivateReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
accountId, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
if req.Id == 0 {
return ctx.Status(fiber.StatusFailedDependency).SendString("id for archive quiz is required")
}
2024-10-25 15:26:03 +00:00
archived, err := r.dal.QuizRepo.DeleteQuiz(ctx.Context(), accountId, req.Id)
2024-02-19 17:48:04 +00:00
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.JSON(DeactivateResp{
Deactivated: archived.Id,
})
}
2024-03-19 17:29:34 +00:00
type QuizMoveReq struct {
Qid, AccountID string
}
2024-10-25 15:26:03 +00:00
func (r *Quiz) QuizMove(ctx *fiber.Ctx) error {
2024-03-19 17:29:34 +00:00
var req QuizMoveReq
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
if req.Qid == "" || req.AccountID == "" {
2024-05-13 11:15:06 +00:00
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request qid and accountID is required")
2024-03-19 17:29:34 +00:00
}
2024-10-25 15:26:03 +00:00
resp, err := r.dal.QuizRepo.QuizMove(ctx.Context(), req.Qid, req.AccountID)
2024-03-19 17:29:34 +00:00
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.Status(fiber.StatusOK).JSON(resp)
}
2024-03-22 12:42:52 +00:00
2024-10-25 15:26:03 +00:00
func (r *Quiz) TemplateCopy(ctx *fiber.Ctx) error {
2024-05-13 11:15:06 +00:00
accountID, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
hlogger := log_mw.ExtractLogger(ctx)
2024-05-13 11:15:06 +00:00
var req struct {
2024-05-13 11:17:45 +00:00
Qid string `json:"qid"`
2024-05-13 11:15:06 +00:00
}
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
if req.Qid == "" {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request qid is required")
}
2024-10-25 15:26:03 +00:00
qizID, err := r.dal.QuizRepo.TemplateCopy(ctx.Context(), accountID, req.Qid)
2024-05-13 11:15:06 +00:00
if err != nil {
2024-07-17 10:59:48 +00:00
fmt.Println("TEMPLERR", err)
2024-05-13 11:15:06 +00:00
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
2024-06-02 09:36:22 +00:00
hlogger.Emit(models.InfoQuizTemplateCopy{
CtxUserID: accountID,
2024-06-02 09:36:22 +00:00
// todo либо возвращать id копируемого квиза либо поле с qid
// для него потому что id получаем уже в запросе sql
//CtxID: req.Qid,
CtxQuizID: qizID,
2024-06-02 09:36:22 +00:00
})
2024-05-17 14:25:32 +00:00
return ctx.Status(fiber.StatusOK).JSON(fiber.Map{"id": qizID})
2024-05-13 11:15:06 +00:00
}
2025-05-08 21:03:37 +00:00
2025-05-14 21:51:35 +00:00
func (s *Quiz) CreateQuizAuditory(ctx *fiber.Ctx) error {
var req struct {
Sex bool `json:"sex"` // false - female, true - male
Age string `json:"age"`
}
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
}
quizIDStr := ctx.Params("quizID")
quizID, err := strconv.ParseInt(quizIDStr, 10, 64)
if err != nil {
return ctx.Status(fiber.StatusBadRequest).SendString("invalid quiz ID")
}
if quizID == 0 || req.Age == "" {
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request missing required fields")
}
result, err := s.dal.QuizRepo.CreateQuizAudience(ctx.Context(), quiz.DepsCreateQuizAudience{
QuizID: quizID,
Age: req.Age,
Sex: req.Sex,
})
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
err = s.producerGigaChat.ToGigaChatNotify(ctx.Context(), brokers.MessageGigaChat{
ID: result,
QuizID: quizID,
Age: req.Age,
Sex: req.Sex,
})
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.Status(fiber.StatusOK).JSON(fiber.Map{"ID": result})
2025-05-08 21:03:37 +00:00
}
2025-05-14 21:51:35 +00:00
func (s *Quiz) GetQuizAuditory(ctx *fiber.Ctx) error {
quizIDStr := ctx.Params("quizID")
quizID, err := strconv.ParseInt(quizIDStr, 10, 64)
2025-05-31 07:43:33 +00:00
if err != nil || quizID == 0 {
return ctx.Status(fiber.StatusBadRequest).SendString("invalid quiz ID")
}
2025-05-31 07:43:33 +00:00
accountID, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
2025-05-31 07:43:33 +00:00
isOwner, err := s.dal.QuizRepo.CheckQuizOwner(ctx.Context(), accountID, uint64(quizID))
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to check ownership: " + err.Error())
}
if !isOwner {
return ctx.Status(fiber.StatusForbidden).SendString("you are not the owner")
}
result, err := s.dal.QuizRepo.GetQuizAudience(ctx.Context(), quizID)
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.Status(fiber.StatusOK).JSON(result)
2025-05-08 21:03:37 +00:00
}
2025-05-14 21:51:35 +00:00
func (s *Quiz) DeleteQuizAuditory(ctx *fiber.Ctx) error {
quizIDStr := ctx.Params("quizID")
quizID, err := strconv.ParseInt(quizIDStr, 10, 64)
2025-05-31 07:43:33 +00:00
if err != nil || quizID == 0 {
return ctx.Status(fiber.StatusBadRequest).SendString("invalid quiz ID")
}
2025-05-31 07:43:33 +00:00
audienceIDStr := ctx.Params("audienceID")
audienceID, err := strconv.ParseInt(audienceIDStr, 10, 64)
if err != nil || audienceID == 0 {
return ctx.Status(fiber.StatusBadRequest).SendString("invalid audience ID")
}
accountID, ok := middleware.GetAccountId(ctx)
if !ok {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
isOwner, err := s.dal.QuizRepo.CheckIsOwnerAudience(ctx.Context(), quizID, audienceID, accountID)
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to check ownership: " + err.Error())
}
if !isOwner {
return ctx.Status(fiber.StatusForbidden).SendString("you are not the owner of this quiz audience")
}
2025-05-31 07:43:33 +00:00
err = s.dal.QuizRepo.DeleteQuizAudience(ctx.Context(), quizID, audienceID)
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
return ctx.SendStatus(fiber.StatusOK)
2025-05-08 21:03:37 +00:00
}