diff --git a/api/.env.example b/api/.env.example index b3b95cf6..be108ad9 100644 --- a/api/.env.example +++ b/api/.env.example @@ -72,3 +72,6 @@ SELF_SERVICE_FLOWS_REGISTRATION_AFTER_DEFAULT_BROWSER_RETURN_URL=http://127.0.0. # SELFSERVICE_ALLOWED_RETURN_URLS_0=http://127.0.0.1:3000 # SELFSERVICE_ALLOWED_RETURN_URLS_1=http://127.0.0.1:4433 LOG_LEVEL=trace + +MAX_QUIZ_FILE_SIZE=1048576 +BODY_LIMIT_MB=15 #MB \ No newline at end of file diff --git a/api/cli/api.go b/api/cli/api.go index 3d6e7259..00a38014 100644 --- a/api/cli/api.go +++ b/api/cli/api.go @@ -26,7 +26,9 @@ func GetAPICommandDef(cfg config.AppConfig, logger *zap.Logger) cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { // Create fiber app - app := fiber.New(fiber.Config{}) + app := fiber.New(fiber.Config{ + BodyLimit: cfg.BodyLimitMB * 1024 * 1024, + }) app.Use(cors.New(cors.Config{ AllowHeaders: "Origin,Content-Type,Accept,Content-Length,Accept-Language,Accept-Encoding,Connection,Access-Control-Allow-Origin,Authorization,Options", diff --git a/api/config/main.go b/api/config/main.go index 379d643e..845e7272 100644 --- a/api/config/main.go +++ b/api/config/main.go @@ -28,6 +28,7 @@ type AppConfig struct { Secret string `envconfig:"JWT_SECRET"` WebUrl string `envconfig:"WEB_URL"` JWTIssuer string `envconfig:"ISSUER"` + BodyLimitMB int `envconfig:"BODY_LIMIT_MB"` RedisClient RedisClientConfig DB DBConfig Kratos KratosConfig diff --git a/api/config/quiz.go b/api/config/quiz.go index edfb47be..dc7bf7a3 100644 --- a/api/config/quiz.go +++ b/api/config/quiz.go @@ -3,4 +3,5 @@ package config type QuizConfig struct { QuestionTimeLimit string `envconfig:"QUESTION_TIME_LIMIT"` ScoreboardMaxDuration string `envconfig:"SCOREBOARD_MAX_DURATION"` + FileSize int64 `envconfig:"QUIZ_FILE_SIZE" default:"1048576"` } diff --git a/api/constants/constant.go b/api/constants/constant.go index 24e9f893..9c19b145 100644 --- a/api/constants/constant.go +++ b/api/constants/constant.go @@ -107,7 +107,7 @@ const ( QuizTitle = "quiz_title" QuizTitleRequired = "quiz-title is required" ErrGettingAttachment = "error in getting file" - ErrFileSizeExceed = "file size exceeded" + ErrFileSizeExceed = "The file is too large to upload. Please select a smaller file." ErrFileIsNotInSupportedType = "file has no supported type" ErrProblemInUploadFile = "there was some error in file upload" ErrValidatingColumns = "file columns not in proper format" diff --git a/api/middlewares/csv_auth.go b/api/middlewares/csv_auth.go index 9786a435..74518a4f 100644 --- a/api/middlewares/csv_auth.go +++ b/api/middlewares/csv_auth.go @@ -21,9 +21,9 @@ func (m *Middleware) ValidateCsv(c *fiber.Ctx) error { return utils.JSONFail(c, http.StatusBadRequest, constants.ErrGettingAttachment) } - if file.Size > constants.FileSize { + if file.Size > m.Config.Quiz.FileSize { m.Logger.Error("error in getting csv file", zap.Error(err)) - return utils.JSONFail(c, http.StatusBadRequest, constants.ErrGettingAttachment) + return utils.JSONFail(c, http.StatusBadRequest, constants.ErrFileSizeExceed) } isMatched := false diff --git a/app/.env.example b/app/.env.example index f664c6e0..08c2d542 100644 --- a/app/.env.example +++ b/app/.env.example @@ -5,4 +5,5 @@ HOST=127.0.0.1 NUXT_PUBLIC_BASE_URL=http://127.0.0.1:5000 NUXT_PUBLIC_API_URL="http://127.0.0.1:3000/api/v1" NUXT_PUBLIC_API_SOCKET_URL="ws://127.0.0.1:3000/api/v1/socket" -NUXT_PUBLIC_KRATOS_URL="http://127.0.0.1:4433" \ No newline at end of file +NUXT_PUBLIC_KRATOS_URL="http://127.0.0.1:4433" +MAX_IMAGE_FILE_SIZE=1048576 #KB \ No newline at end of file diff --git a/app/nuxt.config.ts b/app/nuxt.config.ts index 3c3f22d0..7716b19f 100644 --- a/app/nuxt.config.ts +++ b/app/nuxt.config.ts @@ -7,6 +7,7 @@ export default defineNuxtConfig({ public: { baseUrl: process.env.NUXT_PUBLIC_BASE_URL || "http://127.0.0.1:3001", apiUrl: process.env.NUXT_PUBLIC_API_URL || "http://127.0.0.1:3000/api/v1", + maxImageFileSize: parseInt(process.env.MAX_IMAGE_FILE_SIZE || "1048576") , //1MB default apiSocketUrl: process.env.NUXT_PUBLIC_API_SOCKET_URL || "ws://127.0.0.1:3000/api/v1/socket", diff --git a/app/pages/admin/quiz/create-quiz.vue b/app/pages/admin/quiz/create-quiz.vue index 6b00cda9..4e8a0709 100644 --- a/app/pages/admin/quiz/create-quiz.vue +++ b/app/pages/admin/quiz/create-quiz.vue @@ -10,7 +10,8 @@ useSystemEnv(); // define props and emits let file = ref(0); let title = ref(""); -const url = useRuntimeConfig().public; +const publicRuntimeConfig = useRuntimeConfig().public; +const maxFileSize = publicRuntimeConfig.maxImageFileSize; let quizId = ref(); const requestPending = ref(false); const imageRequestPending = ref(false); @@ -27,7 +28,7 @@ const uploadQuizAndQuestions = async (e) => { formData.append(description.name, description.value); formData.append(attachment.name, attachment.files[0]); try { - await $fetch(encodeURI(`${url.apiUrl}/quizzes/${title.value}/upload`), { + await $fetch(encodeURI(`${publicRuntimeConfig.apiUrl}/quizzes/${title.value}/upload`), { method: "POST", headers: { Accept: "application/json", @@ -51,7 +52,7 @@ const uploadQuizAndQuestions = async (e) => { try { await $fetch( - encodeURI(`${url.apiUrl}/quizzes/${quizId.value}/questions?media=image`), + encodeURI(`${publicRuntimeConfig.apiUrl}/quizzes/${quizId.value}/questions?media=image`), { method: "GET", headers: { @@ -106,9 +107,9 @@ const imageFileUpload = async (e) => { return; } - // 2 MB max - if (file.size > 2000000) { - toast.error("Please upload an image less than 2 MB."); + // 1 MB max + if (file.size > maxFileSize) { + toast.error(`Please upload an image less than ${maxFileSize / 1024 / 1024} MB.`); return; } @@ -117,7 +118,7 @@ const imageFileUpload = async (e) => { imageRequestPending.value = true; try { - await $fetch(encodeURI(`${url.apiUrl}/images?quiz_id=${quizId.value}`), { + await $fetch(encodeURI(`${publicRuntimeConfig.apiUrl}/images?quiz_id=${quizId.value}`), { method: "POST", headers: { Accept: "application/json",