diff --git a/docs/docs.go b/docs/docs.go
index aad76131fffdf4511f3699ffc3dafc59aa1bc6a5..49b75f3556829fa1845dddc0737e82c9ab85bc01 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -451,37 +451,100 @@ const docTemplate = `{
                 }
             }
         },
-        "/reset/confirm": {
+        "/course": {
+            "get": {
+                "description": "Retrieve a list of all available courses.",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get all courses",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
             "put": {
-                "description": "Do confirmation to reset password",
+                "description": "Add a new course with the given details",
+                "consumes": [
+                    "application/json"
+                ],
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
-                    "reset"
+                    "course"
                 ],
-                "summary": "Confirm Reset Password",
+                "summary": "Add a new course",
                 "parameters": [
                     {
                         "type": "string",
-                        "description": "Email validation token",
+                        "description": "AddCourseToken",
                         "name": "Authorization",
                         "in": "header",
                         "required": true
                     },
                     {
-                        "description": "payload",
+                        "description": "Add Course payload",
                         "name": "data",
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/confirm.ConfirmRequestPayload"
+                            "$ref": "#/definitions/course.AddCourseRequestPayload"
                         }
                     }
                 ],
                 "responses": {
                     "200": {
-                        "description": "Login Success",
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
                         "schema": {
                             "$ref": "#/definitions/web.BaseResponse"
                         }
@@ -489,30 +552,100 @@ const docTemplate = `{
                 }
             }
         },
-        "/reset/request": {
-            "post": {
-                "description": "Send Reset password token to email",
+        "/course/faculty": {
+            "get": {
+                "description": "Retrieves a list of all faculties",
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
-                    "reset"
+                    "course"
                 ],
-                "summary": "Request Reset Password Token",
+                "summary": "Get all faculties",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "put": {
+                "description": "Adds a new faculty with the given details",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Add a new faculty",
                 "parameters": [
                     {
-                        "description": "payload",
+                        "type": "string",
+                        "description": "AddFacultyToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Faculty payload",
                         "name": "data",
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/request.RequestRequestPayload"
+                            "$ref": "#/definitions/faculty.AddFacultyRequestPayload"
                         }
                     }
                 ],
                 "responses": {
                     "200": {
-                        "description": "Login Success",
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
                         "schema": {
                             "$ref": "#/definitions/web.BaseResponse"
                         }
@@ -520,108 +653,1514 @@ const docTemplate = `{
                 }
             }
         },
-        "/reset/validate": {
+        "/course/faculty/courses/{id}": {
             "get": {
-                "description": "Send Reset password token to email",
+                "description": "Retrieve all courses that belong to the faculty with the given ID",
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
-                    "reset"
+                    "course"
                 ],
-                "summary": "Request Reset Password Token",
+                "summary": "Get all courses by faculty ID",
                 "parameters": [
                     {
                         "type": "string",
-                        "description": "Email validation token",
-                        "name": "Authorization",
-                        "in": "header",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
                         "required": true
                     }
                 ],
                 "responses": {
                     "200": {
-                        "description": "Login Success",
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
                         "schema": {
                             "$ref": "#/definitions/web.BaseResponse"
                         }
                     }
                 }
             }
-        }
-    },
-    "definitions": {
-        "admin.AdminAddUserPayload": {
-            "type": "object",
-            "required": [
-                "email",
-                "name",
-                "role"
-            ],
-            "properties": {
-                "email": {
-                    "description": "User Email",
-                    "type": "string",
-                    "example": "someone@example.com"
-                },
-                "name": {
-                    "description": "User name",
-                    "type": "string",
-                    "example": "someone"
-                },
-                "role": {
-                    "description": "User Role",
-                    "type": "string",
-                    "example": "admin"
-                }
-            }
         },
-        "admin.AdminUpdateUserPayload": {
-            "type": "object",
-            "required": [
-                "email",
-                "name",
-                "role"
-            ],
-            "properties": {
-                "email": {
-                    "description": "User Email",
-                    "type": "string",
-                    "example": "someone@example.com"
-                },
-                "name": {
-                    "description": "User name",
-                    "type": "string",
-                    "example": "someone"
-                },
-                "role": {
-                    "description": "User Role",
-                    "type": "string",
-                    "example": "admin"
+        "/course/faculty/majors/{id}": {
+            "get": {
+                "description": "Returns a list of majors associated with the given faculty ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get majors by faculty ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
                 }
             }
         },
-        "confirm.ConfirmRequestPayload": {
-            "description": "Information that should be available when you confirm a password reset",
-            "type": "object",
-            "required": [
-                "password",
-                "password_validation"
-            ],
-            "properties": {
+        "/course/faculty/{id}": {
+            "get": {
+                "description": "Retrieve faculty data by UUID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get faculty by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "patch": {
+                "description": "Update a faculty with the given ID",
+                "tags": [
+                    "course"
+                ],
+                "summary": "Update a faculty",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Faculty Payload",
+                        "name": "payload",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/faculty.UpdateFacultyRequestPayload"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateFacultyToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/major": {
+            "get": {
+                "description": "Get a list of all majors",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get all majors",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "put": {
+                "description": "Add a new major to a faculty",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Add Major",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "AddMajorToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Major payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/major.AddMajorRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/major/courses/{id}": {
+            "get": {
+                "description": "Retrieve all courses related to a major",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get courses by major",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Major ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/major/{id}": {
+            "get": {
+                "description": "Get a major by ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get a major by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Major ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "put": {
+                "description": "Update a major with the given ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Update a major",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Major ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateMajorToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Major payload",
+                        "name": "payload",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/major.UpdateMajorRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}": {
+            "get": {
+                "description": "Retrieve a course by ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get a course by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "ID of the course to retrieve",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete a course with the specified ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Delete course by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Course ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "DeleteCourseToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "patch": {
+                "description": "Update an existing course.",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Update Course",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "Course ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateCourseToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Course Payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/course.UpdateCourseRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}/material": {
+            "post": {
+                "description": "Add new material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Add Material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Material Request",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/material.CreateMaterialRequest"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "example": "IF3230",
+                        "description": "Course id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/material.CreateMaterialResponse"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}/materials": {
+            "get": {
+                "description": "Get materials",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Get materials",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "example": "IF3270",
+                        "description": "Course id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": "#/definitions/material.Material"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}/quiz": {
+            "get": {
+                "description": "Get all cours",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get Course quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Course id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": "#/definitions/quiz.Quiz"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/material/{id}": {
+            "get": {
+                "description": "Get material detail",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Get material detail",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "example": "IF3270",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/material.Material"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            },
+            "post": {
+                "description": "Add content of material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Add Content",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add content request",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/material.NewContentRequest"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/material.NewContentResponse"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Delete material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/material/{id}/content/{content-id}": {
+            "delete": {
+                "description": "Delete content of material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Delete Content",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Content id",
+                        "name": "content-id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/quiz/{id}": {
+            "get": {
+                "description": "Get Quiz Detail",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Get Quiz Detail",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/quiz.Quiz"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/quiz/{id}/solution": {
+            "get": {
+                "description": "Take a quiz",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Get Quiz Solution",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Authenticate User (any role)",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/quiz.QuizDetail"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/quiz/{id}/take": {
+            "post": {
+                "description": "Finish quiz session and get the score",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Finish Quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Authenticate User (any role)",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Quiz Finish payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/quiz.FinishQuizPayload"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/quiz.QuizDetail"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/reset/confirm": {
+            "put": {
+                "description": "Do confirmation to reset password",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "reset"
+                ],
+                "summary": "Confirm Reset Password",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Email validation token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/confirm.ConfirmRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Login Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/reset/request": {
+            "post": {
+                "description": "Send Reset password token to email",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "reset"
+                ],
+                "summary": "Request Reset Password Token",
+                "parameters": [
+                    {
+                        "description": "payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.RequestRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Login Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/reset/validate": {
+            "get": {
+                "description": "Send Reset password token to email",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "reset"
+                ],
+                "summary": "Request Reset Password Token",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Email validation token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Login Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "admin.AdminAddUserPayload": {
+            "type": "object",
+            "required": [
+                "email",
+                "name",
+                "role"
+            ],
+            "properties": {
+                "email": {
+                    "description": "User Email",
+                    "type": "string",
+                    "example": "someone@example.com"
+                },
+                "name": {
+                    "description": "User name",
+                    "type": "string",
+                    "example": "someone"
+                },
+                "role": {
+                    "description": "User Role",
+                    "type": "string",
+                    "example": "admin"
+                }
+            }
+        },
+        "admin.AdminUpdateUserPayload": {
+            "type": "object",
+            "required": [
+                "email",
+                "name",
+                "role"
+            ],
+            "properties": {
+                "email": {
+                    "description": "User Email",
+                    "type": "string",
+                    "example": "someone@example.com"
+                },
+                "name": {
+                    "description": "User name",
+                    "type": "string",
+                    "example": "someone"
+                },
+                "role": {
+                    "description": "User Role",
+                    "type": "string",
+                    "example": "admin"
+                }
+            }
+        },
+        "confirm.ConfirmRequestPayload": {
+            "description": "Information that should be available when you confirm a password reset",
+            "type": "object",
+            "required": [
+                "password",
+                "password_validation"
+            ],
+            "properties": {
                 "confirmToken": {
                     "description": "Web Token that was appended to the link",
                     "type": "string"
                 },
-                "password": {
-                    "description": "User Password",
-                    "type": "string",
-                    "example": "secret"
+                "password": {
+                    "description": "User Password",
+                    "type": "string",
+                    "example": "secret"
+                },
+                "password_validation": {
+                    "description": "User Password Validation, must be same as user",
+                    "type": "string",
+                    "example": "secret"
+                }
+            }
+        },
+        "course.AddCourseRequestPayload": {
+            "description": "Information that should be available when you add a course",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "email",
+                "id",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Course Name Abbreviation",
+                    "type": "string"
+                },
+                "addCourseToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Course Description (Can be left empty)",
+                    "type": "string"
+                },
+                "email": {
+                    "description": "Contributor Email",
+                    "type": "string",
+                    "example": "someone@example.com"
+                },
+                "id": {
+                    "description": "Course ID",
+                    "type": "string"
+                },
+                "majabbr": {
+                    "description": "Course Major Abbreviation",
+                    "type": "string"
                 },
-                "password_validation": {
-                    "description": "User Password Validation, must be same as user",
+                "major_id": {
+                    "description": "Major Id, will be set by the server",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Course Name",
+                    "type": "string"
+                }
+            }
+        },
+        "course.UpdateCourseRequestPayload": {
+            "description": "Information that should be available when you add a course",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "email",
+                "lecturer",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Course Name Abbreviation",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Course Description (Can be left empty)",
+                    "type": "string"
+                },
+                "email": {
+                    "description": "Contributor Email",
                     "type": "string",
-                    "example": "secret"
+                    "example": "someone@example.com"
+                },
+                "id": {
+                    "description": "Course ID, Provided by query",
+                    "type": "string"
+                },
+                "lecturer": {
+                    "description": "Course Lecturer",
+                    "type": "string"
+                },
+                "majabbr": {
+                    "description": "Course Major Abbreviation",
+                    "type": "string"
+                },
+                "major_id": {
+                    "description": "Major Id, will be set by the server",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Course Name",
+                    "type": "string"
+                },
+                "updateCourseToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
+        "faculty.AddFacultyRequestPayload": {
+            "description": "Information that should be available when you add a faculty",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Faculty Name Abbreviation",
+                    "type": "string"
+                },
+                "faculty_token": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Faculty Name",
+                    "type": "string"
+                }
+            }
+        },
+        "faculty.UpdateFacultyRequestPayload": {
+            "description": "Information that should be available when you update a faculty",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Faculty Name Abbreviation",
+                    "type": "string"
+                },
+                "id": {
+                    "description": "Faculty ID, Provided by Query",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Faculty Name",
+                    "type": "string"
+                },
+                "updateFacultyToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
                 }
             }
         },
@@ -659,6 +2198,295 @@ const docTemplate = `{
                 }
             }
         },
+        "major.AddMajorRequestPayload": {
+            "description": "Information that should be available when you add a major",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Major Name Abbreviation",
+                    "type": "string"
+                },
+                "facabbr": {
+                    "description": "Major Faculty Abbreviation",
+                    "type": "string"
+                },
+                "faculty_id": {
+                    "description": "Faculty Id, will be set by the server",
+                    "type": "string"
+                },
+                "major_token": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Major Name",
+                    "type": "string"
+                }
+            }
+        },
+        "major.UpdateMajorRequestPayload": {
+            "description": "Information that should be available when you update a major",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Major Name Abbreviation",
+                    "type": "string"
+                },
+                "facabbr": {
+                    "description": "Major Faculty Abbreviation",
+                    "type": "string"
+                },
+                "faculty_id": {
+                    "description": "Faculty Id, will be set by the server",
+                    "type": "string"
+                },
+                "id": {
+                    "description": "Major ID, provided by query",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Major Name",
+                    "type": "string"
+                },
+                "updateMajorToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
+        "material.Content": {
+            "type": "object",
+            "properties": {
+                "id": {
+                    "type": "string"
+                },
+                "link": {
+                    "type": "string"
+                },
+                "material_id": {
+                    "type": "string"
+                },
+                "type": {
+                    "$ref": "#/definitions/material.MaterialType"
+                }
+            }
+        },
+        "material.CreateMaterialRequest": {
+            "type": "object",
+            "required": [
+                "name"
+            ],
+            "properties": {
+                "name": {
+                    "type": "string"
+                }
+            }
+        },
+        "material.CreateMaterialResponse": {
+            "type": "object",
+            "properties": {
+                "material_id": {
+                    "type": "string"
+                }
+            }
+        },
+        "material.Material": {
+            "type": "object",
+            "properties": {
+                "contents": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/material.Content"
+                    }
+                },
+                "course_id": {
+                    "type": "string"
+                },
+                "creator_email": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "week": {
+                    "type": "integer"
+                }
+            }
+        },
+        "material.MaterialType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-varnames": [
+                "Handout",
+                "Video",
+                "External"
+            ]
+        },
+        "material.NewContentRequest": {
+            "type": "object",
+            "required": [
+                "type"
+            ],
+            "properties": {
+                "link": {
+                    "type": "string"
+                },
+                "type": {
+                    "$ref": "#/definitions/material.MaterialType"
+                }
+            }
+        },
+        "material.NewContentResponse": {
+            "type": "object",
+            "properties": {
+                "upload_link": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.AnswerOption": {
+            "type": "object",
+            "properties": {
+                "answer": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "is_solution": {
+                    "type": "boolean"
+                },
+                "media_id": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                }
+            }
+        },
+        "quiz.FinishQuizPayload": {
+            "type": "object",
+            "properties": {
+                "data": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.Response"
+                    }
+                }
+            }
+        },
+        "quiz.Quiz": {
+            "type": "object",
+            "properties": {
+                "course_id": {
+                    "type": "string"
+                },
+                "creator_email": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "nama": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.QuizDetail": {
+            "type": "object",
+            "properties": {
+                "course_id": {
+                    "type": "string"
+                },
+                "description": {
+                    "type": "string"
+                },
+                "help": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "media": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.QuizMedia"
+                    }
+                },
+                "name": {
+                    "type": "string"
+                },
+                "problems": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.QuizProblem"
+                    }
+                }
+            }
+        },
+        "quiz.QuizMedia": {
+            "type": "object",
+            "properties": {
+                "id": {
+                    "type": "string"
+                },
+                "type": {
+                    "type": "string"
+                },
+                "url": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.QuizProblem": {
+            "type": "object",
+            "properties": {
+                "answers": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.AnswerOption"
+                    }
+                },
+                "id": {
+                    "type": "string"
+                },
+                "media_id": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                },
+                "question": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.Response": {
+            "type": "object",
+            "properties": {
+                "answer_id": {
+                    "type": "string"
+                },
+                "problem_id": {
+                    "type": "string"
+                }
+            }
+        },
         "refresh.RefreshResponsePayload": {
             "description": "Refresh endpoint response when process success",
             "type": "object",
diff --git a/docs/swagger.json b/docs/swagger.json
index 5e40a0e52c5c837cf1a9c167f1e4ab064fce87f3..883d3d799d994fab91eb3dbf9e1aee4d8483c36f 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -443,37 +443,100 @@
                 }
             }
         },
-        "/reset/confirm": {
+        "/course": {
+            "get": {
+                "description": "Retrieve a list of all available courses.",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get all courses",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
             "put": {
-                "description": "Do confirmation to reset password",
+                "description": "Add a new course with the given details",
+                "consumes": [
+                    "application/json"
+                ],
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
-                    "reset"
+                    "course"
                 ],
-                "summary": "Confirm Reset Password",
+                "summary": "Add a new course",
                 "parameters": [
                     {
                         "type": "string",
-                        "description": "Email validation token",
+                        "description": "AddCourseToken",
                         "name": "Authorization",
                         "in": "header",
                         "required": true
                     },
                     {
-                        "description": "payload",
+                        "description": "Add Course payload",
                         "name": "data",
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/confirm.ConfirmRequestPayload"
+                            "$ref": "#/definitions/course.AddCourseRequestPayload"
                         }
                     }
                 ],
                 "responses": {
                     "200": {
-                        "description": "Login Success",
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
                         "schema": {
                             "$ref": "#/definitions/web.BaseResponse"
                         }
@@ -481,30 +544,100 @@
                 }
             }
         },
-        "/reset/request": {
-            "post": {
-                "description": "Send Reset password token to email",
+        "/course/faculty": {
+            "get": {
+                "description": "Retrieves a list of all faculties",
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
-                    "reset"
+                    "course"
                 ],
-                "summary": "Request Reset Password Token",
+                "summary": "Get all faculties",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "put": {
+                "description": "Adds a new faculty with the given details",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Add a new faculty",
                 "parameters": [
                     {
-                        "description": "payload",
+                        "type": "string",
+                        "description": "AddFacultyToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Faculty payload",
                         "name": "data",
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/request.RequestRequestPayload"
+                            "$ref": "#/definitions/faculty.AddFacultyRequestPayload"
                         }
                     }
                 ],
                 "responses": {
                     "200": {
-                        "description": "Login Success",
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
                         "schema": {
                             "$ref": "#/definitions/web.BaseResponse"
                         }
@@ -512,108 +645,1514 @@
                 }
             }
         },
-        "/reset/validate": {
+        "/course/faculty/courses/{id}": {
             "get": {
-                "description": "Send Reset password token to email",
+                "description": "Retrieve all courses that belong to the faculty with the given ID",
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
-                    "reset"
+                    "course"
                 ],
-                "summary": "Request Reset Password Token",
+                "summary": "Get all courses by faculty ID",
                 "parameters": [
                     {
                         "type": "string",
-                        "description": "Email validation token",
-                        "name": "Authorization",
-                        "in": "header",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
                         "required": true
                     }
                 ],
                 "responses": {
                     "200": {
-                        "description": "Login Success",
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
                         "schema": {
                             "$ref": "#/definitions/web.BaseResponse"
                         }
                     }
                 }
             }
-        }
-    },
-    "definitions": {
-        "admin.AdminAddUserPayload": {
-            "type": "object",
-            "required": [
-                "email",
-                "name",
-                "role"
-            ],
-            "properties": {
-                "email": {
-                    "description": "User Email",
-                    "type": "string",
-                    "example": "someone@example.com"
-                },
-                "name": {
-                    "description": "User name",
-                    "type": "string",
-                    "example": "someone"
-                },
-                "role": {
-                    "description": "User Role",
-                    "type": "string",
-                    "example": "admin"
-                }
-            }
         },
-        "admin.AdminUpdateUserPayload": {
-            "type": "object",
-            "required": [
-                "email",
-                "name",
-                "role"
-            ],
-            "properties": {
-                "email": {
-                    "description": "User Email",
-                    "type": "string",
-                    "example": "someone@example.com"
-                },
-                "name": {
-                    "description": "User name",
-                    "type": "string",
-                    "example": "someone"
-                },
-                "role": {
-                    "description": "User Role",
-                    "type": "string",
-                    "example": "admin"
+        "/course/faculty/majors/{id}": {
+            "get": {
+                "description": "Returns a list of majors associated with the given faculty ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get majors by faculty ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
                 }
             }
         },
-        "confirm.ConfirmRequestPayload": {
-            "description": "Information that should be available when you confirm a password reset",
-            "type": "object",
-            "required": [
-                "password",
-                "password_validation"
-            ],
-            "properties": {
+        "/course/faculty/{id}": {
+            "get": {
+                "description": "Retrieve faculty data by UUID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get faculty by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "patch": {
+                "description": "Update a faculty with the given ID",
+                "tags": [
+                    "course"
+                ],
+                "summary": "Update a faculty",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Faculty ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Faculty Payload",
+                        "name": "payload",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/faculty.UpdateFacultyRequestPayload"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateFacultyToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/major": {
+            "get": {
+                "description": "Get a list of all majors",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get all majors",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "put": {
+                "description": "Add a new major to a faculty",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Add Major",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "AddMajorToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Major payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/major.AddMajorRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/major/courses/{id}": {
+            "get": {
+                "description": "Retrieve all courses related to a major",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get courses by major",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Major ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/major/{id}": {
+            "get": {
+                "description": "Get a major by ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get a major by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Major ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "put": {
+                "description": "Update a major with the given ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Update a major",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Major ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateMajorToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Major payload",
+                        "name": "payload",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/major.UpdateMajorRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}": {
+            "get": {
+                "description": "Retrieve a course by ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get a course by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "ID of the course to retrieve",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete a course with the specified ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Delete course by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Course ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "DeleteCourseToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "patch": {
+                "description": "Update an existing course.",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Update Course",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "Course ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateCourseToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Course Payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/course.UpdateCourseRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}/material": {
+            "post": {
+                "description": "Add new material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Add Material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Material Request",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/material.CreateMaterialRequest"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "example": "IF3230",
+                        "description": "Course id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/material.CreateMaterialResponse"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}/materials": {
+            "get": {
+                "description": "Get materials",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Get materials",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "example": "IF3270",
+                        "description": "Course id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": "#/definitions/material.Material"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/course/{id}/quiz": {
+            "get": {
+                "description": "Get all cours",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "course"
+                ],
+                "summary": "Get Course quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Course id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": "#/definitions/quiz.Quiz"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/material/{id}": {
+            "get": {
+                "description": "Get material detail",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Get material detail",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "example": "IF3270",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/material.Material"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            },
+            "post": {
+                "description": "Add content of material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Add Content",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add content request",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/material.NewContentRequest"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/material.NewContentResponse"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Delete material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/material/{id}/content/{content-id}": {
+            "delete": {
+                "description": "Delete content of material",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "content"
+                ],
+                "summary": "Delete Content",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Access token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Material id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Content id",
+                        "name": "content-id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/quiz/{id}": {
+            "get": {
+                "description": "Get Quiz Detail",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Get Quiz Detail",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/quiz.Quiz"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/quiz/{id}/solution": {
+            "get": {
+                "description": "Take a quiz",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Get Quiz Solution",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Authenticate User (any role)",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/quiz.QuizDetail"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/quiz/{id}/take": {
+            "post": {
+                "description": "Finish quiz session and get the score",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Finish Quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Authenticate User (any role)",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Quiz Finish payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/quiz.FinishQuizPayload"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/web.BaseResponse"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/quiz.QuizDetail"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/reset/confirm": {
+            "put": {
+                "description": "Do confirmation to reset password",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "reset"
+                ],
+                "summary": "Confirm Reset Password",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Email validation token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/confirm.ConfirmRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Login Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/reset/request": {
+            "post": {
+                "description": "Send Reset password token to email",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "reset"
+                ],
+                "summary": "Request Reset Password Token",
+                "parameters": [
+                    {
+                        "description": "payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.RequestRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Login Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/reset/validate": {
+            "get": {
+                "description": "Send Reset password token to email",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "reset"
+                ],
+                "summary": "Request Reset Password Token",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Email validation token",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Login Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "admin.AdminAddUserPayload": {
+            "type": "object",
+            "required": [
+                "email",
+                "name",
+                "role"
+            ],
+            "properties": {
+                "email": {
+                    "description": "User Email",
+                    "type": "string",
+                    "example": "someone@example.com"
+                },
+                "name": {
+                    "description": "User name",
+                    "type": "string",
+                    "example": "someone"
+                },
+                "role": {
+                    "description": "User Role",
+                    "type": "string",
+                    "example": "admin"
+                }
+            }
+        },
+        "admin.AdminUpdateUserPayload": {
+            "type": "object",
+            "required": [
+                "email",
+                "name",
+                "role"
+            ],
+            "properties": {
+                "email": {
+                    "description": "User Email",
+                    "type": "string",
+                    "example": "someone@example.com"
+                },
+                "name": {
+                    "description": "User name",
+                    "type": "string",
+                    "example": "someone"
+                },
+                "role": {
+                    "description": "User Role",
+                    "type": "string",
+                    "example": "admin"
+                }
+            }
+        },
+        "confirm.ConfirmRequestPayload": {
+            "description": "Information that should be available when you confirm a password reset",
+            "type": "object",
+            "required": [
+                "password",
+                "password_validation"
+            ],
+            "properties": {
                 "confirmToken": {
                     "description": "Web Token that was appended to the link",
                     "type": "string"
                 },
-                "password": {
-                    "description": "User Password",
-                    "type": "string",
-                    "example": "secret"
+                "password": {
+                    "description": "User Password",
+                    "type": "string",
+                    "example": "secret"
+                },
+                "password_validation": {
+                    "description": "User Password Validation, must be same as user",
+                    "type": "string",
+                    "example": "secret"
+                }
+            }
+        },
+        "course.AddCourseRequestPayload": {
+            "description": "Information that should be available when you add a course",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "email",
+                "id",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Course Name Abbreviation",
+                    "type": "string"
+                },
+                "addCourseToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Course Description (Can be left empty)",
+                    "type": "string"
+                },
+                "email": {
+                    "description": "Contributor Email",
+                    "type": "string",
+                    "example": "someone@example.com"
+                },
+                "id": {
+                    "description": "Course ID",
+                    "type": "string"
+                },
+                "majabbr": {
+                    "description": "Course Major Abbreviation",
+                    "type": "string"
                 },
-                "password_validation": {
-                    "description": "User Password Validation, must be same as user",
+                "major_id": {
+                    "description": "Major Id, will be set by the server",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Course Name",
+                    "type": "string"
+                }
+            }
+        },
+        "course.UpdateCourseRequestPayload": {
+            "description": "Information that should be available when you add a course",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "email",
+                "lecturer",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Course Name Abbreviation",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Course Description (Can be left empty)",
+                    "type": "string"
+                },
+                "email": {
+                    "description": "Contributor Email",
                     "type": "string",
-                    "example": "secret"
+                    "example": "someone@example.com"
+                },
+                "id": {
+                    "description": "Course ID, Provided by query",
+                    "type": "string"
+                },
+                "lecturer": {
+                    "description": "Course Lecturer",
+                    "type": "string"
+                },
+                "majabbr": {
+                    "description": "Course Major Abbreviation",
+                    "type": "string"
+                },
+                "major_id": {
+                    "description": "Major Id, will be set by the server",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Course Name",
+                    "type": "string"
+                },
+                "updateCourseToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
+        "faculty.AddFacultyRequestPayload": {
+            "description": "Information that should be available when you add a faculty",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Faculty Name Abbreviation",
+                    "type": "string"
+                },
+                "faculty_token": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Faculty Name",
+                    "type": "string"
+                }
+            }
+        },
+        "faculty.UpdateFacultyRequestPayload": {
+            "description": "Information that should be available when you update a faculty",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Faculty Name Abbreviation",
+                    "type": "string"
+                },
+                "id": {
+                    "description": "Faculty ID, Provided by Query",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Faculty Name",
+                    "type": "string"
+                },
+                "updateFacultyToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
                 }
             }
         },
@@ -651,6 +2190,295 @@
                 }
             }
         },
+        "major.AddMajorRequestPayload": {
+            "description": "Information that should be available when you add a major",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Major Name Abbreviation",
+                    "type": "string"
+                },
+                "facabbr": {
+                    "description": "Major Faculty Abbreviation",
+                    "type": "string"
+                },
+                "faculty_id": {
+                    "description": "Faculty Id, will be set by the server",
+                    "type": "string"
+                },
+                "major_token": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Major Name",
+                    "type": "string"
+                }
+            }
+        },
+        "major.UpdateMajorRequestPayload": {
+            "description": "Information that should be available when you update a major",
+            "type": "object",
+            "required": [
+                "abbreviation",
+                "name"
+            ],
+            "properties": {
+                "abbreviation": {
+                    "description": "Major Name Abbreviation",
+                    "type": "string"
+                },
+                "facabbr": {
+                    "description": "Major Faculty Abbreviation",
+                    "type": "string"
+                },
+                "faculty_id": {
+                    "description": "Faculty Id, will be set by the server",
+                    "type": "string"
+                },
+                "id": {
+                    "description": "Major ID, provided by query",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Major Name",
+                    "type": "string"
+                },
+                "updateMajorToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
+        "material.Content": {
+            "type": "object",
+            "properties": {
+                "id": {
+                    "type": "string"
+                },
+                "link": {
+                    "type": "string"
+                },
+                "material_id": {
+                    "type": "string"
+                },
+                "type": {
+                    "$ref": "#/definitions/material.MaterialType"
+                }
+            }
+        },
+        "material.CreateMaterialRequest": {
+            "type": "object",
+            "required": [
+                "name"
+            ],
+            "properties": {
+                "name": {
+                    "type": "string"
+                }
+            }
+        },
+        "material.CreateMaterialResponse": {
+            "type": "object",
+            "properties": {
+                "material_id": {
+                    "type": "string"
+                }
+            }
+        },
+        "material.Material": {
+            "type": "object",
+            "properties": {
+                "contents": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/material.Content"
+                    }
+                },
+                "course_id": {
+                    "type": "string"
+                },
+                "creator_email": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "week": {
+                    "type": "integer"
+                }
+            }
+        },
+        "material.MaterialType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-varnames": [
+                "Handout",
+                "Video",
+                "External"
+            ]
+        },
+        "material.NewContentRequest": {
+            "type": "object",
+            "required": [
+                "type"
+            ],
+            "properties": {
+                "link": {
+                    "type": "string"
+                },
+                "type": {
+                    "$ref": "#/definitions/material.MaterialType"
+                }
+            }
+        },
+        "material.NewContentResponse": {
+            "type": "object",
+            "properties": {
+                "upload_link": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.AnswerOption": {
+            "type": "object",
+            "properties": {
+                "answer": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "is_solution": {
+                    "type": "boolean"
+                },
+                "media_id": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                }
+            }
+        },
+        "quiz.FinishQuizPayload": {
+            "type": "object",
+            "properties": {
+                "data": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.Response"
+                    }
+                }
+            }
+        },
+        "quiz.Quiz": {
+            "type": "object",
+            "properties": {
+                "course_id": {
+                    "type": "string"
+                },
+                "creator_email": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "nama": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.QuizDetail": {
+            "type": "object",
+            "properties": {
+                "course_id": {
+                    "type": "string"
+                },
+                "description": {
+                    "type": "string"
+                },
+                "help": {
+                    "type": "string"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "media": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.QuizMedia"
+                    }
+                },
+                "name": {
+                    "type": "string"
+                },
+                "problems": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.QuizProblem"
+                    }
+                }
+            }
+        },
+        "quiz.QuizMedia": {
+            "type": "object",
+            "properties": {
+                "id": {
+                    "type": "string"
+                },
+                "type": {
+                    "type": "string"
+                },
+                "url": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.QuizProblem": {
+            "type": "object",
+            "properties": {
+                "answers": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/quiz.AnswerOption"
+                    }
+                },
+                "id": {
+                    "type": "string"
+                },
+                "media_id": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                },
+                "question": {
+                    "type": "string"
+                }
+            }
+        },
+        "quiz.Response": {
+            "type": "object",
+            "properties": {
+                "answer_id": {
+                    "type": "string"
+                },
+                "problem_id": {
+                    "type": "string"
+                }
+            }
+        },
         "refresh.RefreshResponsePayload": {
             "description": "Refresh endpoint response when process success",
             "type": "object",
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index d2280c2b16106e29102e0ed33e5e14d8ac794bc6..58ea9348fb473426c5890cff161bd98360f62bf0 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -56,6 +56,112 @@ definitions:
     - password
     - password_validation
     type: object
+  course.AddCourseRequestPayload:
+    description: Information that should be available when you add a course
+    properties:
+      abbreviation:
+        description: Course Name Abbreviation
+        type: string
+      addCourseToken:
+        description: Web Token that was appended to the link
+        type: string
+      description:
+        description: Course Description (Can be left empty)
+        type: string
+      email:
+        description: Contributor Email
+        example: someone@example.com
+        type: string
+      id:
+        description: Course ID
+        type: string
+      majabbr:
+        description: Course Major Abbreviation
+        type: string
+      major_id:
+        description: Major Id, will be set by the server
+        type: string
+      name:
+        description: Course Name
+        type: string
+    required:
+    - abbreviation
+    - email
+    - id
+    - name
+    type: object
+  course.UpdateCourseRequestPayload:
+    description: Information that should be available when you add a course
+    properties:
+      abbreviation:
+        description: Course Name Abbreviation
+        type: string
+      description:
+        description: Course Description (Can be left empty)
+        type: string
+      email:
+        description: Contributor Email
+        example: someone@example.com
+        type: string
+      id:
+        description: Course ID, Provided by query
+        type: string
+      lecturer:
+        description: Course Lecturer
+        type: string
+      majabbr:
+        description: Course Major Abbreviation
+        type: string
+      major_id:
+        description: Major Id, will be set by the server
+        type: string
+      name:
+        description: Course Name
+        type: string
+      updateCourseToken:
+        description: Web Token that was appended to the link
+        type: string
+    required:
+    - abbreviation
+    - email
+    - lecturer
+    - name
+    type: object
+  faculty.AddFacultyRequestPayload:
+    description: Information that should be available when you add a faculty
+    properties:
+      abbreviation:
+        description: Faculty Name Abbreviation
+        type: string
+      faculty_token:
+        description: Web Token that was appended to the link
+        type: string
+      name:
+        description: Faculty Name
+        type: string
+    required:
+    - abbreviation
+    - name
+    type: object
+  faculty.UpdateFacultyRequestPayload:
+    description: Information that should be available when you update a faculty
+    properties:
+      abbreviation:
+        description: Faculty Name Abbreviation
+        type: string
+      id:
+        description: Faculty ID, Provided by Query
+        type: string
+      name:
+        description: Faculty Name
+        type: string
+      updateFacultyToken:
+        description: Web Token that was appended to the link
+        type: string
+    required:
+    - abbreviation
+    - name
+    type: object
   login.LoginRequestPayload:
     description: Information that should be available when do a login process
     properties:
@@ -81,6 +187,200 @@ definitions:
         description: Token that used to generate new access token
         type: string
     type: object
+  major.AddMajorRequestPayload:
+    description: Information that should be available when you add a major
+    properties:
+      abbreviation:
+        description: Major Name Abbreviation
+        type: string
+      facabbr:
+        description: Major Faculty Abbreviation
+        type: string
+      faculty_id:
+        description: Faculty Id, will be set by the server
+        type: string
+      major_token:
+        description: Web Token that was appended to the link
+        type: string
+      name:
+        description: Major Name
+        type: string
+    required:
+    - abbreviation
+    - name
+    type: object
+  major.UpdateMajorRequestPayload:
+    description: Information that should be available when you update a major
+    properties:
+      abbreviation:
+        description: Major Name Abbreviation
+        type: string
+      facabbr:
+        description: Major Faculty Abbreviation
+        type: string
+      faculty_id:
+        description: Faculty Id, will be set by the server
+        type: string
+      id:
+        description: Major ID, provided by query
+        type: string
+      name:
+        description: Major Name
+        type: string
+      updateMajorToken:
+        description: Web Token that was appended to the link
+        type: string
+    required:
+    - abbreviation
+    - name
+    type: object
+  material.Content:
+    properties:
+      id:
+        type: string
+      link:
+        type: string
+      material_id:
+        type: string
+      type:
+        $ref: '#/definitions/material.MaterialType'
+    type: object
+  material.CreateMaterialRequest:
+    properties:
+      name:
+        type: string
+    required:
+    - name
+    type: object
+  material.CreateMaterialResponse:
+    properties:
+      material_id:
+        type: string
+    type: object
+  material.Material:
+    properties:
+      contents:
+        items:
+          $ref: '#/definitions/material.Content'
+        type: array
+      course_id:
+        type: string
+      creator_email:
+        type: string
+      id:
+        type: string
+      name:
+        type: string
+      week:
+        type: integer
+    type: object
+  material.MaterialType:
+    enum:
+    - 1
+    - 2
+    - 3
+    type: integer
+    x-enum-varnames:
+    - Handout
+    - Video
+    - External
+  material.NewContentRequest:
+    properties:
+      link:
+        type: string
+      type:
+        $ref: '#/definitions/material.MaterialType'
+    required:
+    - type
+    type: object
+  material.NewContentResponse:
+    properties:
+      upload_link:
+        type: string
+    type: object
+  quiz.AnswerOption:
+    properties:
+      answer:
+        type: string
+      id:
+        type: string
+      is_solution:
+        type: boolean
+      media_id:
+        items:
+          type: string
+        type: array
+    type: object
+  quiz.FinishQuizPayload:
+    properties:
+      data:
+        items:
+          $ref: '#/definitions/quiz.Response'
+        type: array
+    type: object
+  quiz.Quiz:
+    properties:
+      course_id:
+        type: string
+      creator_email:
+        type: string
+      id:
+        type: string
+      nama:
+        type: string
+    type: object
+  quiz.QuizDetail:
+    properties:
+      course_id:
+        type: string
+      description:
+        type: string
+      help:
+        type: string
+      id:
+        type: string
+      media:
+        items:
+          $ref: '#/definitions/quiz.QuizMedia'
+        type: array
+      name:
+        type: string
+      problems:
+        items:
+          $ref: '#/definitions/quiz.QuizProblem'
+        type: array
+    type: object
+  quiz.QuizMedia:
+    properties:
+      id:
+        type: string
+      type:
+        type: string
+      url:
+        type: string
+    type: object
+  quiz.QuizProblem:
+    properties:
+      answers:
+        items:
+          $ref: '#/definitions/quiz.AnswerOption'
+        type: array
+      id:
+        type: string
+      media_id:
+        items:
+          type: string
+        type: array
+      question:
+        type: string
+    type: object
+  quiz.Response:
+    properties:
+      answer_id:
+        type: string
+      problem_id:
+        type: string
+    type: object
   refresh.RefreshResponsePayload:
     description: Refresh endpoint response when process success
     properties:
@@ -435,6 +735,916 @@ paths:
       summary: Send Email Verification
       tags:
       - auth
+  /course:
+    get:
+      description: Retrieve a list of all available courses.
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get all courses
+      tags:
+      - course
+    put:
+      consumes:
+      - application/json
+      description: Add a new course with the given details
+      parameters:
+      - description: AddCourseToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Add Course payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/course.AddCourseRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add a new course
+      tags:
+      - course
+  /course/{id}:
+    delete:
+      consumes:
+      - application/json
+      description: Delete a course with the specified ID
+      parameters:
+      - description: Course ID
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: DeleteCourseToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Delete course by ID
+      tags:
+      - course
+    get:
+      description: Retrieve a course by ID
+      parameters:
+      - description: ID of the course to retrieve
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get a course by ID
+      tags:
+      - course
+    patch:
+      consumes:
+      - application/json
+      description: Update an existing course.
+      parameters:
+      - description: Course ID
+        in: path
+        name: id
+        required: true
+        type: integer
+      - description: UpdateCourseToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Update Course Payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/course.UpdateCourseRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Update Course
+      tags:
+      - course
+  /course/{id}/material:
+    post:
+      consumes:
+      - application/json
+      description: Add new material
+      parameters:
+      - description: Access token
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Material Request
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/material.CreateMaterialRequest'
+      - description: Course id
+        example: IF3230
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  $ref: '#/definitions/material.CreateMaterialResponse'
+              type: object
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add Material
+      tags:
+      - content
+  /course/{id}/materials:
+    get:
+      consumes:
+      - application/json
+      description: Get materials
+      parameters:
+      - description: Course id
+        example: IF3270
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  items:
+                    $ref: '#/definitions/material.Material'
+                  type: array
+              type: object
+      summary: Get materials
+      tags:
+      - content
+  /course/{id}/quiz:
+    get:
+      consumes:
+      - application/json
+      description: Get all cours
+      parameters:
+      - description: Course id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  items:
+                    $ref: '#/definitions/quiz.Quiz'
+                  type: array
+              type: object
+      summary: Get Course quiz
+      tags:
+      - course
+  /course/faculty:
+    get:
+      description: Retrieves a list of all faculties
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get all faculties
+      tags:
+      - course
+    put:
+      consumes:
+      - application/json
+      description: Adds a new faculty with the given details
+      parameters:
+      - description: AddFacultyToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Add Faculty payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/faculty.AddFacultyRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add a new faculty
+      tags:
+      - course
+  /course/faculty/{id}:
+    get:
+      description: Retrieve faculty data by UUID
+      parameters:
+      - description: Faculty ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get faculty by ID
+      tags:
+      - course
+    patch:
+      description: Update a faculty with the given ID
+      parameters:
+      - description: Faculty ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: Update Faculty Payload
+        in: body
+        name: payload
+        required: true
+        schema:
+          $ref: '#/definitions/faculty.UpdateFacultyRequestPayload'
+      - description: UpdateFacultyToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Update a faculty
+      tags:
+      - course
+  /course/faculty/courses/{id}:
+    get:
+      description: Retrieve all courses that belong to the faculty with the given
+        ID
+      parameters:
+      - description: Faculty ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get all courses by faculty ID
+      tags:
+      - course
+  /course/faculty/majors/{id}:
+    get:
+      description: Returns a list of majors associated with the given faculty ID
+      parameters:
+      - description: Faculty ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get majors by faculty ID
+      tags:
+      - course
+  /course/major:
+    get:
+      description: Get a list of all majors
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get all majors
+      tags:
+      - course
+    put:
+      consumes:
+      - application/json
+      description: Add a new major to a faculty
+      parameters:
+      - description: AddMajorToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Add Major payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/major.AddMajorRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add Major
+      tags:
+      - course
+  /course/major/{id}:
+    get:
+      description: Get a major by ID
+      parameters:
+      - description: Major ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get a major by ID
+      tags:
+      - course
+    put:
+      consumes:
+      - application/json
+      description: Update a major with the given ID
+      parameters:
+      - description: Major ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: UpdateMajorToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Update Major payload
+        in: body
+        name: payload
+        required: true
+        schema:
+          $ref: '#/definitions/major.UpdateMajorRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Update a major
+      tags:
+      - course
+  /course/major/courses/{id}:
+    get:
+      description: Retrieve all courses related to a major
+      parameters:
+      - description: Major ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get courses by major
+      tags:
+      - course
+  /material/{id}:
+    delete:
+      consumes:
+      - application/json
+      description: Delete material
+      parameters:
+      - description: Access token
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Material id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Delete material
+      tags:
+      - content
+    get:
+      consumes:
+      - application/json
+      description: Get material detail
+      parameters:
+      - description: Material id
+        example: IF3270
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  $ref: '#/definitions/material.Material'
+              type: object
+      summary: Get material detail
+      tags:
+      - content
+    post:
+      consumes:
+      - application/json
+      description: Add content of material
+      parameters:
+      - description: Access token
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Add content request
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/material.NewContentRequest'
+      - description: Material id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  $ref: '#/definitions/material.NewContentResponse'
+              type: object
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add Content
+      tags:
+      - content
+  /material/{id}/content/{content-id}:
+    delete:
+      consumes:
+      - application/json
+      description: Delete content of material
+      parameters:
+      - description: Access token
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Material id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: Content id
+        format: uuid
+        in: path
+        name: content-id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Delete Content
+      tags:
+      - content
+  /quiz/{id}:
+    get:
+      consumes:
+      - application/json
+      description: Get Quiz Detail
+      parameters:
+      - description: Quiz id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  $ref: '#/definitions/quiz.Quiz'
+              type: object
+      summary: Get Quiz Detail
+      tags:
+      - quiz
+  /quiz/{id}/solution:
+    get:
+      consumes:
+      - application/json
+      description: Take a quiz
+      parameters:
+      - description: Authenticate User (any role)
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Quiz id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  $ref: '#/definitions/quiz.QuizDetail'
+              type: object
+      summary: Get Quiz Solution
+      tags:
+      - quiz
+  /quiz/{id}/take:
+    post:
+      consumes:
+      - application/json
+      description: Finish quiz session and get the score
+      parameters:
+      - description: Authenticate User (any role)
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Quiz Finish payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/quiz.FinishQuizPayload'
+      - description: Quiz id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/web.BaseResponse'
+            - properties:
+                data:
+                  $ref: '#/definitions/quiz.QuizDetail'
+              type: object
+      summary: Finish Quiz
+      tags:
+      - quiz
   /reset/confirm:
     put:
       description: Do confirmation to reset password
diff --git a/handler/admin/addUser.go b/handler/admin/addUser.go
index 02c631be6d59ed66f628b57dfa4ace8191b05249..71adae1097c94697a7666f4798f3ea65abfb43fb 100644
--- a/handler/admin/addUser.go
+++ b/handler/admin/addUser.go
@@ -7,14 +7,14 @@ import (
 
 // Index godoc
 //
-//	@Tags					admin
-//	@Summary			Add User
+//	@Tags			admin
+//	@Summary		Add User
 //	@Description	Add a user to database
-//	@Produce			json
-//	@Accept				json
-//	@Param				data body req.AdminAddUserPayload true "Admin Add User Payload"
-//	@Success			200	{object}	web.BaseResponse
-//	@Router				/admin/user [post]
+//	@Produce		json
+//	@Accept			json
+//	@Param			data	body		req.AdminAddUserPayload	true	"Admin Add User Payload"
+//	@Success		200		{object}	web.BaseResponse
+//	@Router			/admin/user [post]
 func (route AdminHandlerImpl) AddUser(w http.ResponseWriter, r *http.Request){
 	payload := req.AdminAddUserPayload{}
 
diff --git a/handler/admin/deleteUser.go b/handler/admin/deleteUser.go
index 9979a47a2279814f9de6c9302c3a555531a659aa..c9757d2d663584b0e675a1a27f3c4bc89a445a3f 100644
--- a/handler/admin/deleteUser.go
+++ b/handler/admin/deleteUser.go
@@ -7,13 +7,13 @@ import (
 
 // Index godoc
 //
-//	@Tags					admin
-//	@Summary			Delete User By Id
+//	@Tags			admin
+//	@Summary		Delete User By Id
 //	@Description	Delete a user from database
-//	@Produce			json
-//	@Accept				json
-//	@Success			200	{object}	web.BaseResponse
-//	@Router				/admin/user/{email} [delete]
+//	@Produce		json
+//	@Accept			json
+//	@Success		200	{object}	web.BaseResponse
+//	@Router			/admin/user/{email} [delete]
 func (route AdminHandlerImpl) DeleteUser(w http.ResponseWriter, r *http.Request){
 	email := path.Base(r.URL.Path)
 
diff --git a/handler/admin/getAllUser.go b/handler/admin/getAllUser.go
index 32771d8d99fcf9d82f53279bd70706a35d30f1b7..31732077a1ef80d9745efb59dc2891a95e0c0366 100644
--- a/handler/admin/getAllUser.go
+++ b/handler/admin/getAllUser.go
@@ -6,12 +6,12 @@ import (
 
 // Index godoc
 //
-//	@Tags					admin
-//	@Summary			Get All User
+//	@Tags			admin
+//	@Summary		Get All User
 //	@Description	Get all users from database
-//	@Produce			json
-//	@Success			200	{object}	web.BaseResponse
-//	@Router				/admin/user [get]
+//	@Produce		json
+//	@Success		200	{object}	web.BaseResponse
+//	@Router			/admin/user [get]
 func (route AdminHandlerImpl) GetAllUser(w http.ResponseWriter, r *http.Request){
 	// get all user from service
 	users, err := route.AdminService.GetAllUser()
diff --git a/handler/admin/getUserByEmail.go b/handler/admin/getUserByEmail.go
index fd21301db325bf6d59eb8df4404f352ba4fd2b29..7326be4653cd8fc165d60e49b24c152e14e4ea97 100644
--- a/handler/admin/getUserByEmail.go
+++ b/handler/admin/getUserByEmail.go
@@ -7,12 +7,12 @@ import (
 
 // Index godoc
 //
-//	@Tags					admin
-//	@Summary			Get User By Email
+//	@Tags			admin
+//	@Summary		Get User By Email
 //	@Description	Get a user from database
-//	@Produce			json
-//	@Success			200	{object}	web.BaseResponse
-//	@Router				/admin/user/{email} [get]
+//	@Produce		json
+//	@Success		200	{object}	web.BaseResponse
+//	@Router			/admin/user/{email} [get]
 func (route AdminHandlerImpl) GetUserByEmail(w http.ResponseWriter, r *http.Request) {
 	// email := r.URL.Query().Get("email")
 	email := path.Base(r.URL.Path)
diff --git a/handler/admin/updateUser.go b/handler/admin/updateUser.go
index 877d5c84a3785626e9736ecf1d433d37fdf1df40..a2f91cbd93fb181c23983e9aae3b1ef9d89293e1 100644
--- a/handler/admin/updateUser.go
+++ b/handler/admin/updateUser.go
@@ -8,14 +8,14 @@ import (
 
 // Index godoc
 //
-//	@Tags					admin
-//	@Summary			Update User By Id
+//	@Tags			admin
+//	@Summary		Update User By Id
 //	@Description	Update a user from database
-//	@Produce			json
-//	@Accept				json
-//	@Param				data body req.AdminUpdateUserPayload true "Admin Update User Payload"
-//	@Success			200	{object}	web.BaseResponse
-//	@Router				/admin/user/{email} [patch]
+//	@Produce		json
+//	@Accept			json
+//	@Param			data	body		req.AdminUpdateUserPayload	true	"Admin Update User Payload"
+//	@Success		200		{object}	web.BaseResponse
+//	@Router			/admin/user/{email} [patch]
 func (route AdminHandlerImpl) UpdateUser(w http.ResponseWriter, r *http.Request){
 	email := path.Base(r.URL.Path)
 	// TODO: how to change email
diff --git a/handler/auth/login.go b/handler/auth/login.go
index 3ab6f0759cde01fa545c1299fb1d2f9b056afafa..309db782e4547e931c301bf4a4dd5a452aeb37a6 100644
--- a/handler/auth/login.go
+++ b/handler/auth/login.go
@@ -11,19 +11,19 @@ import (
 
 // Index godoc
 //
-//		@Tags					auth
-//		@Summary			Login
-//		@Description	Login and generate new pair of token
-//		@Produce			json
-//		@Accept				json
-//		@Param				data body login.LoginRequestPayload true "Login payload"
-//		@Success			200	{object}	web.BaseResponse{data=login.LoginResponsePayload} "Login Success"
-//	  @Failure			400 {object}  web.BaseResponse{data=[]string} "Bad Input"
-//	  @Failure			403 {object}  web.BaseResponse "Login Credential Error"
-//	  @Failure			415 {object}  web.BaseResponse "Not a json request"
-//	  @Failure			422 {object}  web.BaseResponse "Invalid JSON input"
-//	  @Failure			500 {object}  web.BaseResponse "Unknown Internal Error"
-//		@Router				/auth/login [post]
+//	@Tags			auth
+//	@Summary		Login
+//	@Description	Login and generate new pair of token
+//	@Produce		json
+//	@Accept			json
+//	@Param			data	body		login.LoginRequestPayload							true	"Login payload"
+//	@Success		200		{object}	web.BaseResponse{data=login.LoginResponsePayload}	"Login Success"
+//	@Failure		400		{object}	web.BaseResponse{data=[]string}						"Bad Input"
+//	@Failure		403		{object}	web.BaseResponse									"Login Credential Error"
+//	@Failure		415		{object}	web.BaseResponse									"Not a json request"
+//	@Failure		422		{object}	web.BaseResponse									"Invalid JSON input"
+//	@Failure		500		{object}	web.BaseResponse									"Unknown Internal Error"
+//	@Router			/auth/login [post]
 func (a AuthHandlerImpl) Login(w http.ResponseWriter, r *http.Request) {
 	payload := login.LoginRequestPayload{}
 	validate := validator.New()
diff --git a/handler/auth/refresh.go b/handler/auth/refresh.go
index 20eaed5d8803d078beed923cf0855b9bc394f438..78a8a9b03f7386b7830f20fc30725e50e39b67d7 100644
--- a/handler/auth/refresh.go
+++ b/handler/auth/refresh.go
@@ -11,17 +11,17 @@ import (
 
 // Index godoc
 //
-//		@Tags					auth
-//		@Summary			Refresh Token
-//		@Description	Generate new access token
-//		@Produce			json
-//		@Accept				json
-//		@Param				Authorization header string true "Refresh token"
-//		@Success			200	{object}	web.BaseResponse{data=refresh.RefreshResponsePayload}
-//	  @Failure			400 {object}  web.BaseResponse
-//	  @Failure			401 {object}  web.BaseResponse
-//	  @Failure			500 {object}  web.BaseResponse
-//		@Router				/auth/refresh [post]
+//	@Tags			auth
+//	@Summary		Refresh Token
+//	@Description	Generate new access token
+//	@Produce		json
+//	@Accept			json
+//	@Param			Authorization	header		string	true	"Refresh token"
+//	@Success		200				{object}	web.BaseResponse{data=refresh.RefreshResponsePayload}
+//	@Failure		400				{object}	web.BaseResponse
+//	@Failure		401				{object}	web.BaseResponse
+//	@Failure		500				{object}	web.BaseResponse
+//	@Router			/auth/refresh [post]
 func (a AuthHandlerImpl) Refresh(w http.ResponseWriter, r *http.Request) {
 	payload := refresh.RefreshRequestPayload{}
 
diff --git a/handler/auth/register.go b/handler/auth/register.go
index 8a24f5da071967f00ddcea7e973bd6a46230fa1b..37a50b67dc97cdb86f925e54ff07439629a35571 100644
--- a/handler/auth/register.go
+++ b/handler/auth/register.go
@@ -12,16 +12,16 @@ import (
 
 // Index godoc
 //
-//		@Tags					auth
-//		@Summary			Register New Account
-//		@Description	Generate New Account as Member
-//		@Produce			json
-//		@Accept				json
-//		@Param				data body register.RegisterRequestPayload true "Register Payload"
-//		@Success			200	{object}	web.BaseResponse
-//	  @Failure			400 {object}  web.BaseResponse
-//	  @Failure			500 {object}  web.BaseResponse
-//		@Router				/auth/register [post]
+//	@Tags			auth
+//	@Summary		Register New Account
+//	@Description	Generate New Account as Member
+//	@Produce		json
+//	@Accept			json
+//	@Param			data	body		register.RegisterRequestPayload	true	"Register Payload"
+//	@Success		200		{object}	web.BaseResponse
+//	@Failure		400		{object}	web.BaseResponse
+//	@Failure		500		{object}	web.BaseResponse
+//	@Router			/auth/register [post]
 func (a AuthHandlerImpl) Register(w http.ResponseWriter, r *http.Request) {
 	payload := register.RegisterRequestPayload{}
 	validate := validator.New()
diff --git a/handler/auth/send_verify.go b/handler/auth/send_verify.go
index b2b4a2e70eaca89ac5de5f26a76fb4210d894416..b2b41d0473dcdd91c72840c20e903ac635fce7b3 100644
--- a/handler/auth/send_verify.go
+++ b/handler/auth/send_verify.go
@@ -11,16 +11,16 @@ import (
 
 // Index godoc
 //
-//		@Tags					auth
-//		@Summary			Send Email Verification
-//		@Description	Send Email Verification to user
-//		@Produce			json
-//		@Accept				json
-//		@Param				data body verification.VerificationSendRequestPayload true "Register Payload"
-//		@Success			200	{object}	web.BaseResponse
-//	  @Failure			400 {object}  web.BaseResponse
-//	  @Failure			500 {object}  web.BaseResponse
-//		@Router				/auth/verify/resend  [post]
+//	@Tags			auth
+//	@Summary		Send Email Verification
+//	@Description	Send Email Verification to user
+//	@Produce		json
+//	@Accept			json
+//	@Param			data	body		verification.VerificationSendRequestPayload	true	"Register Payload"
+//	@Success		200		{object}	web.BaseResponse
+//	@Failure		400		{object}	web.BaseResponse
+//	@Failure		500		{object}	web.BaseResponse
+//	@Router			/auth/verify/resend  [post]
 func (a AuthHandlerImpl) SendEmailVerify(w http.ResponseWriter, r *http.Request) {
 	payload := verification.VerificationSendRequestPayload{}
 	validate := validator.New()
diff --git a/handler/auth/verify.go b/handler/auth/verify.go
index a118518f67d6d8e4dff329541d93d406f545cbca..1e264a7cb810bad925d579dc67df080987961244 100644
--- a/handler/auth/verify.go
+++ b/handler/auth/verify.go
@@ -11,16 +11,16 @@ import (
 
 // Index godoc
 //
-//		@Tags					auth
-//		@Summary			Do Email Verification
-//		@Description	Do Email Verification to user
-//		@Produce			json
-//		@Accept				json
-//		@Param				data body verification.VerificationRequestPayload true "Register Payload"
-//		@Success			200	{object}	web.BaseResponse
-//	  @Failure			400 {object}  web.BaseResponse
-//	  @Failure			500 {object}  web.BaseResponse
-//		@Router				/auth/verify  [post]
+//	@Tags			auth
+//	@Summary		Do Email Verification
+//	@Description	Do Email Verification to user
+//	@Produce		json
+//	@Accept			json
+//	@Param			data	body		verification.VerificationRequestPayload	true	"Register Payload"
+//	@Success		200		{object}	web.BaseResponse
+//	@Failure		400		{object}	web.BaseResponse
+//	@Failure		500		{object}	web.BaseResponse
+//	@Router			/auth/verify  [post]
 func (a AuthHandlerImpl) EmailVerify(w http.ResponseWriter, r *http.Request) {
 	payload := verification.VerificationRequestPayload{}
 	validate := validator.New()
diff --git a/handler/common/home.go b/handler/common/home.go
index 7266a95ec32bcbccd657df123bb8fad5e0ef689a..272eda7d2f19bce70362e0de12c23c749323b23f 100644
--- a/handler/common/home.go
+++ b/handler/common/home.go
@@ -6,12 +6,12 @@ import (
 
 // Index godoc
 //
-//	@Tags					common
-//	@Summary			Index page
+//	@Tags			common
+//	@Summary		Index page
 //	@Description	Give server index page response
-//	@Produce			json
-//	@Success			200	{object}	web.BaseResponse
-//	@Router				/ [get]
+//	@Produce		json
+//	@Success		200	{object}	web.BaseResponse
+//	@Router			/ [get]
 func (route CommonHandlerImpl) Home(w http.ResponseWriter, r *http.Request) {
 	payload := route.WrapperUtil.SuccessResponseWrap(route.CommonService.Home())
 	route.HttpUtil.WriteSuccessJson(w, payload)
diff --git a/handler/course/addCourse.go b/handler/course/addCourse.go
index c07f9ce00468bf9589df78b295922432342e307e..4db1e673301c5b16d6de69ee20de09df593af416 100644
--- a/handler/course/addCourse.go
+++ b/handler/course/addCourse.go
@@ -7,12 +7,27 @@ import (
 
 	"github.com/go-playground/validator/v10"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/add"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Add a new course
+//	@Description	Add a new course with the given details
+//	@Tags			course
+//	@Accept			json
+//	@Produce		json
+//	@Param			Authorization	header		string							true	"AddCourseToken"
+//	@Param			data			body		course.AddCourseRequestPayload	true	"Add Course payload"
+//	@Success		200				{object}	web.BaseResponse				"Success"
+//	@Failure		400				{object}	web.BaseResponse				"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse				"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse				"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse				"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse				"Internal Server Error"
+//	@Router			/course [put]
 func (c CourseHandlerImpl) AddCourse(w http.ResponseWriter, r *http.Request) {
-	payload := add.AddCourseRequestPayload{}
-	validate := validator.New()
+	payload := course.AddCourseRequestPayload{}
 
 	// Validate payload
 	if r.Header.Get("Content-Type") != "application/json" {
@@ -27,6 +42,7 @@ func (c CourseHandlerImpl) AddCourse(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	validate := validator.New()
 	if err := validate.Struct(payload); err != nil {
 		if _, ok := err.(*validator.InvalidValidationError); ok {
 			payload := c.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
@@ -83,4 +99,4 @@ func (c CourseHandlerImpl) AddCourse(w http.ResponseWriter, r *http.Request) {
 
 	responsePayload := c.WrapperUtil.SuccessResponseWrap(nil)
 	c.HttpUtil.WriteSuccessJson(w, responsePayload)
-}
\ No newline at end of file
+}
diff --git a/handler/course/addFaculty.go b/handler/course/addFaculty.go
index a0430da8c4541a971771b86ef0d8cd3a1a002927..02269011fae0b1eb68de8ed75d52037dc02704df 100644
--- a/handler/course/addFaculty.go
+++ b/handler/course/addFaculty.go
@@ -7,11 +7,27 @@ import (
 
 	"github.com/go-playground/validator/v10"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty/add"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty"
 )
 
+// Index godoc
+//
+//	@Summary		Add a new faculty
+//	@Description	Adds a new faculty with the given details
+//	@Tags			course
+//	@Accept			json
+//	@Produce		json
+//	@Param			Authorization	header		string								true	"AddFacultyToken"
+//	@Param			data			body		faculty.AddFacultyRequestPayload	true	"Add Faculty payload"
+//	@Success		200				{object}	web.BaseResponse					"Success"
+//	@Failure		400				{object}	web.BaseResponse					"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse					"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse					"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse					"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse					"Internal Server Error"
+//	@Router			/course/faculty [put]
 func (c CourseHandlerImpl) AddFaculty(w http.ResponseWriter, r *http.Request) {
-	payload := add.AddFacultyRequestPayload{}
+	payload := faculty.AddFacultyRequestPayload{}
 	validate := validator.New()
 
 	// Validate payload
diff --git a/handler/course/addMajor.go b/handler/course/addMajor.go
index 3f3c3ab0faaf177ab6fc12a1da902dac2b8d7ad8..e73fb420cc51a7b8efe71b666a741e909b14cc8b 100644
--- a/handler/course/addMajor.go
+++ b/handler/course/addMajor.go
@@ -7,11 +7,27 @@ import (
 
 	"github.com/go-playground/validator/v10"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major/add"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major"
 )
 
+// Index godoc
+//
+//	@Summary		Add Major
+//	@Description	Add a new major to a faculty
+//	@Tags			course
+//	@Accept			json
+//	@Produce		json
+//	@Param			Authorization	header		string							true	"AddMajorToken"
+//	@Param			data			body		major.AddMajorRequestPayload	true	"Add Major payload"
+//	@Success		200				{object}	web.BaseResponse				"Success"
+//	@Failure		400				{object}	web.BaseResponse				"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse				"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse				"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse				"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse				"Internal Server Error"
+//	@Router			/course/major [put]
 func (c CourseHandlerImpl) AddMajor(w http.ResponseWriter, r *http.Request) {
-	payload := add.AddMajorRequestPayload{}
+	payload := major.AddMajorRequestPayload{}
 	validate := validator.New()
 
 	// Validate payload
diff --git a/handler/course/deleteCourse.go b/handler/course/deleteCourse.go
index a06a7a3e41c72742cb6bda478ecb34def0791056..c97221b8a230396c95353715e99f76b37e500592 100644
--- a/handler/course/deleteCourse.go
+++ b/handler/course/deleteCourse.go
@@ -3,14 +3,32 @@ package course
 import (
 	"fmt"
 	"net/http"
+	"path"
 	"strings"
 
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/delete"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Delete course by ID
+//	@Description	Delete a course with the specified ID
+//	@Tags			course
+//	@Accept			json
+//	@Produce		json
+//	@Param			id				path		string				true	"Course ID"
+//	@Param			Authorization	header		string				true	"DeleteCourseToken"
+//	@Success		200				{object}	web.BaseResponse	"Success"
+//	@Failure		400				{object}	web.BaseResponse	"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse	"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse	"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/{id} [delete]
 func (c CourseHandlerImpl) DeleteCourse(w http.ResponseWriter, r *http.Request) {
-	payload := delete.DeleteByStringRequestPayload{}
+	payload := course.DeleteByStringRequestPayload{}
+	payload.ID = path.Base(r.URL.Path)
 	validateTokenHeader := r.Header.Get("Authorization")
 
 	if validateTokenHeader == "" {
diff --git a/handler/course/getCourse.go b/handler/course/getCourse.go
index 290087fda55ac0219d3ad037f5c3a38415453056..7f20ae8af1d132fd515b2a6507ba54a8948cbc04 100644
--- a/handler/course/getCourse.go
+++ b/handler/course/getCourse.go
@@ -6,11 +6,22 @@ import (
 	"path"
 
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Get a course by ID
+//	@Description	Retrieve a course by ID
+//	@Tags			course
+//	@Produce		json
+//	@Param			id	path		string				true	"ID of the course to retrieve"
+//	@Success		200	{object}	web.BaseResponse	"OK"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/{id} [get]
 func (c CourseHandlerImpl) GetCourse(w http.ResponseWriter, r *http.Request) {
-	payload := get.GetByStringRequestPayload{}
+	payload := course.GetByStringRequestPayload{}
 	payload.ID = path.Base(r.URL.Path)
 	
 	packet, err := c.CourseService.GetCourse(payload)
diff --git a/handler/course/getCourses.go b/handler/course/getCourses.go
index 9280e47c7d96abd7f12d5188cc1c11c6ce927bab..e22ed91542d2442ffae6b580aba3505bec8b857a 100644
--- a/handler/course/getCourses.go
+++ b/handler/course/getCourses.go
@@ -7,6 +7,16 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 )
 
+// Index godoc
+//
+//	@Summary		Get all courses
+//	@Description	Retrieve a list of all available courses.
+//	@Tags			course
+//	@Produce		json
+//	@Success		200	{object}	web.BaseResponse	"OK"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course [get]
 func (c CourseHandlerImpl) GetCourses(w http.ResponseWriter, r *http.Request) {
 	packet, err := c.CourseService.GetAllCourse()
 
diff --git a/handler/course/getCoursesByFaculty.go b/handler/course/getCoursesByFaculty.go
index a59f6a82342b6f3989c4f7b95585c4e59f1b7ff1..c708d4ecaf0984319d1d7a945b15622ceeefa2ea 100644
--- a/handler/course/getCoursesByFaculty.go
+++ b/handler/course/getCoursesByFaculty.go
@@ -7,11 +7,23 @@ import (
 
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+// 
+//	@Summary		Get all courses by faculty ID
+//	@Description	Retrieve all courses that belong to the faculty with the given ID
+//	@Tags			course
+//	@Produce		json
+//	@Param			id	path		string				true	"Faculty ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/faculty/courses/{id} [get]
 func (c CourseHandlerImpl) GetCoursesByFaculty(w http.ResponseWriter, r *http.Request) {
-	payload := get.GetByUUIDRequestPayload{}
+	payload := course.GetByUUIDRequestPayload{}
 	id, err := uuid.Parse(path.Base(r.URL.Path))
 	
 	if err != nil {
diff --git a/handler/course/getCoursesByMajor.go b/handler/course/getCoursesByMajor.go
index 3f8413871825b2bcc11ad1579f3c82d56b294f58..5bfeadbbd47bd56fdab00cf9ef1b3ce4ad168601 100644
--- a/handler/course/getCoursesByMajor.go
+++ b/handler/course/getCoursesByMajor.go
@@ -7,11 +7,23 @@ import (
 
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Get courses by major
+//	@Description	Retrieve all courses related to a major
+//	@Tags			course
+//	@Produce		json
+//	@Param			id	path		string				true	"Major ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/major/courses/{id} [get]
 func (c CourseHandlerImpl) GetCoursesByMajor(w http.ResponseWriter, r *http.Request) {
-	payload := get.GetByUUIDRequestPayload{}
+	payload := course.GetByUUIDRequestPayload{}
 	id, err := uuid.Parse(path.Base(r.URL.Path))
 	
 	if err != nil {
diff --git a/handler/course/getFaculties.go b/handler/course/getFaculties.go
index 65473e5b47aa33f10c47f696dd4dd974896773d2..d51c8090ad70355bd0c3c9b0903c57c8bb10dde7 100644
--- a/handler/course/getFaculties.go
+++ b/handler/course/getFaculties.go
@@ -6,7 +6,16 @@ import (
 
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 )
-
+// Index godoc
+//
+//	@Summary		Get all faculties
+//	@Description	Retrieves a list of all faculties
+//	@Tags			course
+//	@Produce		json
+//	@Success		200	{object}	web.BaseResponse	"OK"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/faculty [get]
 func (c CourseHandlerImpl) GetFaculties(w http.ResponseWriter, r *http.Request) {
 	packet, err := c.CourseService.GetAllFaculty()
 
diff --git a/handler/course/getFaculty.go b/handler/course/getFaculty.go
index e50d77b17d5ec0482e1b96ee3a9901dc7b58b43b..494d3c0aeeb91699c6c62c92fc12d3f3a807b1a5 100644
--- a/handler/course/getFaculty.go
+++ b/handler/course/getFaculty.go
@@ -7,11 +7,23 @@ import (
 
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Get faculty by ID
+//	@Description	Retrieve faculty data by UUID
+//	@Tags			course
+//	@Produce		json
+//	@Param			id	path		string				true	"Faculty ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/faculty/{id} [get]
 func (c CourseHandlerImpl) GetFaculty(w http.ResponseWriter, r *http.Request) {
-	payload := get.GetByUUIDRequestPayload{}
+	payload := course.GetByUUIDRequestPayload{}
 	id, err := uuid.Parse(path.Base(r.URL.Path))
 	
 	if err != nil {
diff --git a/handler/course/getMajor.go b/handler/course/getMajor.go
index 8413ce7f474dc9a6e4259ea3a65fed1ee770cd02..fe3a4952790af76aee0ccf74423146390963dddb 100644
--- a/handler/course/getMajor.go
+++ b/handler/course/getMajor.go
@@ -7,11 +7,23 @@ import (
 
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Get a major by ID
+//	@Description	Get a major by ID
+//	@Tags			course
+//	@Produce		json
+//	@Param			id	path		string				true	"Major ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/major/{id} [get]
 func (c CourseHandlerImpl) GetMajor(w http.ResponseWriter, r *http.Request) {
-	payload := get.GetByUUIDRequestPayload{}
+	payload := course.GetByUUIDRequestPayload{}
 	id, err := uuid.Parse(path.Base(r.URL.Path))
 	
 	if err != nil {
diff --git a/handler/course/getMajors.go b/handler/course/getMajors.go
index 05466ce40e6e430b284a0e98f905fd0c14fe3869..cdb9d01fc3abd37c2faab0f53e02c69cc00adc5b 100644
--- a/handler/course/getMajors.go
+++ b/handler/course/getMajors.go
@@ -7,6 +7,16 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 )
 
+// Index godoc
+//
+//	@Summary		Get all majors
+//	@Description	Get a list of all majors
+//	@Tags			course
+//	@Produce		json
+//	@Success		200	{object}	web.BaseResponse	"OK"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/major [get]
 func (c CourseHandlerImpl) GetMajors(w http.ResponseWriter, r *http.Request) {
 	packet, err := c.CourseService.GetAllMajor()
 
diff --git a/handler/course/getMajorsByFaculty.go b/handler/course/getMajorsByFaculty.go
index abdedb8b72337808f4f092806784ddcf3bdefd5b..9eafc3d088a810f5879c27b2b20d7e21da995d3e 100644
--- a/handler/course/getMajorsByFaculty.go
+++ b/handler/course/getMajorsByFaculty.go
@@ -7,11 +7,22 @@ import (
 
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
-
+// Index godoc
+//
+//	@Summary		Get majors by faculty ID
+//	@Description	Returns a list of majors associated with the given faculty ID
+//	@Tags			course
+//	@Produce		json
+//	@Param			id	path		string				true	"Faculty ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/course/faculty/majors/{id} [get]
 func (c CourseHandlerImpl) GetMajorsByFaculty(w http.ResponseWriter, r *http.Request) {
-	payload := get.GetByUUIDRequestPayload{}
+	payload := course.GetByUUIDRequestPayload{}
 	id, err := uuid.Parse(path.Base(r.URL.Path))
 	
 	if err != nil {
diff --git a/handler/course/updateCourse.go b/handler/course/updateCourse.go
index 92dfef946154ecfd72775d44be63a3bb31bdb505..4e2ded686a6281dd2e6baebd5b8868fdcf92c150 100644
--- a/handler/course/updateCourse.go
+++ b/handler/course/updateCourse.go
@@ -5,13 +5,31 @@ import (
 	"net/http"
 	"strings"
 
+	"github.com/go-chi/chi/v5"
 	"github.com/go-playground/validator/v10"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/update"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
+// Index godoc
+//
+//	@Summary		Update Course
+//	@Description	Update an existing course.
+//	@Tags			course
+//	@Accept			json
+//	@Produce		json
+//	@Param			id				path		int									true	"Course ID"
+//	@Param			Authorization	header		string								true	"UpdateCourseToken"
+//	@Param			data			body		course.UpdateCourseRequestPayload	true	"Update Course Payload"
+//	@Success		200				{object}	web.BaseResponse					"Success"
+//	@Failure		400				{object}	web.BaseResponse					"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse					"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse					"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse					"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse					"Internal Server Error"
+//	@Router			/course/{id} [patch]
 func (c CourseHandlerImpl) UpdateCourse(w http.ResponseWriter, r *http.Request) {
-	payload := update.UpdateCourseRequestPayload{}
+	payload := course.UpdateCourseRequestPayload{}
 	validate := validator.New()
 
 	// Validate payload
@@ -64,6 +82,7 @@ func (c CourseHandlerImpl) UpdateCourse(w http.ResponseWriter, r *http.Request)
 	}
 
 	payload.UpdateCourseToken = token[1]
+	payload.ID = chi.URLParam(r, "id")
 	err := c.CourseService.UpdateCourse(payload)
 
 	if err != nil {
@@ -83,4 +102,4 @@ func (c CourseHandlerImpl) UpdateCourse(w http.ResponseWriter, r *http.Request)
 
 	responsePayload := c.WrapperUtil.SuccessResponseWrap(nil)
 	c.HttpUtil.WriteSuccessJson(w, responsePayload)
-}
\ No newline at end of file
+}
diff --git a/handler/course/updateFaculty.go b/handler/course/updateFaculty.go
index e79c7e51b717479b76ed11e0ff17a80a0f0d52ec..c27eca05f9aff3ab7f3d50984e0760a69e67d3b8 100644
--- a/handler/course/updateFaculty.go
+++ b/handler/course/updateFaculty.go
@@ -5,13 +5,30 @@ import (
 	"net/http"
 	"strings"
 
+	"github.com/go-chi/chi/v5"
 	"github.com/go-playground/validator/v10"
+	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty/update"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty"
 )
 
+// Index godoc
+//
+//	@Summary		Update a faculty 
+//	@Description	Update a faculty with the given ID
+//	@Tags			course
+//	@Param			id				path		string								true	"Faculty ID (UUID)"
+//	@Param			payload			body		faculty.UpdateFacultyRequestPayload	true	"Update Faculty Payload"
+//	@Param			Authorization	header		string								true	"UpdateFacultyToken"
+//	@Success		200				{object}	web.BaseResponse					"Success"
+//	@Failure		400				{object}	web.BaseResponse					"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse					"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse					"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse					"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse					"Internal Server Error"
+//	@Router			/course/faculty/{id} [patch]
 func (c CourseHandlerImpl) UpdateFaculty(w http.ResponseWriter, r *http.Request) {
-	payload := update.UpdateFacultyRequestPayload{}
+	payload := faculty.UpdateFacultyRequestPayload{}
 	validate := validator.New()
 
 	// Validate payload
@@ -63,8 +80,17 @@ func (c CourseHandlerImpl) UpdateFaculty(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := c.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		c.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
 	payload.UpdateFacultyToken = token[1]
-	err := c.CourseService.UpdateFaculty(payload)
+	payload.ID = id
+	err = c.CourseService.UpdateFaculty(payload)
 
 	if err != nil {
 		if errData, ok := err.(web.ResponseError); ok {
@@ -83,4 +109,4 @@ func (c CourseHandlerImpl) UpdateFaculty(w http.ResponseWriter, r *http.Request)
 
 	responsePayload := c.WrapperUtil.SuccessResponseWrap(nil)
 	c.HttpUtil.WriteSuccessJson(w, responsePayload)
-}
\ No newline at end of file
+}
diff --git a/handler/course/updateMajor.go b/handler/course/updateMajor.go
index b302b6e638f80206d3756f2af292b86373f2658a..ec802574680fb8f046bae1b7bb2e11031a41f282 100644
--- a/handler/course/updateMajor.go
+++ b/handler/course/updateMajor.go
@@ -5,13 +5,29 @@ import (
 	"net/http"
 	"strings"
 
+	"github.com/go-chi/chi/v5"
 	"github.com/go-playground/validator/v10"
+	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major/update"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major"
 )
-
+//	@Summary		Update a major
+//	@Description	Update a major with the given ID
+//	@Tags			course
+//	@Accept			json
+//	@Produce		json
+//	@Param			id				path		string								true	"Major ID (UUID)"
+//	@Param			Authorization	header		string								true	"UpdateMajorToken"
+//	@Param			payload			body		major.UpdateMajorRequestPayload	true	"Update Major payload"
+//	@Success		200				{object}	web.BaseResponse					"Success"
+//	@Failure		400				{object}	web.BaseResponse					"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse					"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse					"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse					"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse					"Internal Server Error"
+//	@Router			/course/major/{id} [put]
 func (c CourseHandlerImpl) UpdateMajor(w http.ResponseWriter, r *http.Request) {
-	payload := update.UpdateMajorRequestPayload{}
+	payload := major.UpdateMajorRequestPayload{}
 	validate := validator.New()
 
 	// Validate payload
@@ -63,8 +79,17 @@ func (c CourseHandlerImpl) UpdateMajor(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := c.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		c.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
 	payload.UpdateMajorToken = token[1]
-	err := c.CourseService.UpdateMajor(payload)
+	payload.ID = id
+	err = c.CourseService.UpdateMajor(payload)
 
 	if err != nil {
 		if errData, ok := err.(web.ResponseError); ok {
@@ -83,4 +108,4 @@ func (c CourseHandlerImpl) UpdateMajor(w http.ResponseWriter, r *http.Request) {
 
 	responsePayload := c.WrapperUtil.SuccessResponseWrap(nil)
 	c.HttpUtil.WriteSuccessJson(w, responsePayload)
-}
\ No newline at end of file
+}
diff --git a/handler/di.go b/handler/di.go
index 0f3eae80a5bd38faa6a1e07e63e13a9c6c41e11e..399ef81ecbb23c9d70b0431c6129610c92d5dadc 100644
--- a/handler/di.go
+++ b/handler/di.go
@@ -6,6 +6,8 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/handler/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/common"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/course"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/material"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/reset"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/swagger"
 )
@@ -18,11 +20,11 @@ var HandlerSet = wire.NewSet(
 	// Swagger
 	wire.Struct(new(swagger.SwaggerHandlerImpl), "*"),
 	wire.Bind(new(swagger.SwaggerHandler), new(*swagger.SwaggerHandlerImpl)),
-	
+
 	// Admin
 	wire.Struct(new(admin.AdminHandlerImpl), "*"),
 	wire.Bind(new(admin.AdminHandler), new(*admin.AdminHandlerImpl)),
-	
+
 	// Auth
 	wire.Struct(new(auth.AuthHandlerImpl), "*"),
 	wire.Bind(new(auth.AuthHandler), new(*auth.AuthHandlerImpl)),
@@ -34,4 +36,12 @@ var HandlerSet = wire.NewSet(
 	// Course
 	wire.Struct(new(course.CourseHandlerImpl), "*"),
 	wire.Bind(new(course.CourseHandler), new(*course.CourseHandlerImpl)),
+
+	// Material
+	wire.Struct(new(material.MaterialHandlerImpl), "*"),
+	wire.Bind(new(material.MaterialHandler), new(*material.MaterialHandlerImpl)),
+
+	// Quiz
+	wire.Struct(new(quiz.QuizHandlerImpl), "*"),
+	wire.Bind(new(quiz.QuizHandler), new(*quiz.QuizHandlerImpl)),
 )
diff --git a/handler/material/add_content.go b/handler/material/add_content.go
new file mode 100644
index 0000000000000000000000000000000000000000..1f5511f2e9ddc83640d3429d67128fdbc6a23ff1
--- /dev/null
+++ b/handler/material/add_content.go
@@ -0,0 +1,113 @@
+package material
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/go-playground/validator/v10"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	materialDomain "gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	authToken "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/material"
+)
+
+// Index godoc
+//
+//	@Tags			content
+//	@Summary		Add Content
+//	@Description	Add content of material
+//	@Produce		json
+//	@Accept			json
+//	@Param			Authorization	header		string						true	"Access token"
+//	@Param			data			body		material.NewContentRequest	true	"Add content request"
+//	@Param			id				path		string						true	"Material id"	Format(uuid)
+//	@Success		200				{object}	web.BaseResponse{data=material.NewContentResponse}
+//	@Success		400				{object}	web.BaseResponse
+//	@Success		401				{object}	web.BaseResponse
+//	@Router			/material/{id} [post]
+func (m MaterialHandlerImpl) AddContent(w http.ResponseWriter, r *http.Request) {
+	payload := material.NewContentRequest{}
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	materialId := chi.URLParam(r, "material-id")
+	if materialId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+	}
+
+	materialIdUUID, err := uuid.Parse(materialId)
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is invalid", err)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+	}
+
+	payload.MaterialId = materialIdUUID
+
+	if !ok {
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	validate := validator.New()
+
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := m.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := m.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		m.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := m.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if payload.Type != materialDomain.Handout && payload.Link == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("link is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	uploadLink, err := m.MaterialContentService.AddContent(payload.MaterialId, user.Email, materialDomain.Content{
+		Type: payload.Type,
+		Link: payload.Link,
+	})
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			if respErr.Code != "NOT_OWNER" {
+				m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			} else {
+				m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+			}
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(material.NewContentResponse{
+		UploadLink: uploadLink,
+	})
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/material/create_material.go b/handler/material/create_material.go
new file mode 100644
index 0000000000000000000000000000000000000000..55565566908a318265a647ba142e3047d875a003
--- /dev/null
+++ b/handler/material/create_material.go
@@ -0,0 +1,108 @@
+package material
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/go-playground/validator/v10"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	authToken "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/material"
+)
+
+// Index godoc
+//
+//	@Tags			content
+//	@Summary		Add Material
+//	@Description	Add new material
+//	@Produce		json
+//	@Accept			json
+//	@Param			Authorization	header		string							true	"Access token"
+//	@Param			data			body		material.CreateMaterialRequest	true	"Material Request"
+//	@Param			id				path		string							true	"Course id"	example(IF3230)
+//	@Success		200				{object}	web.BaseResponse{data=material.CreateMaterialResponse}
+//	@Success		400				{object}	web.BaseResponse
+//	@Success		401				{object}	web.BaseResponse
+//	@Router			/course/{id}/material [post]
+func (m MaterialHandlerImpl) CreateMaterial(w http.ResponseWriter, r *http.Request) {
+	payload := material.CreateMaterialRequest{}
+	courseId := chi.URLParam(r, "id")
+
+	// START OF VALIDATE
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := m.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := m.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		m.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	validate := validator.New()
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := m.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+	// END OF VALIDATE
+
+	if courseId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("course id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if isExist, _ := m.CourseRepository.IsCourseExist(courseId); !isExist {
+		payload := m.WrapperUtil.ErrorResponseWrap("course id not found", nil)
+		m.HttpUtil.WriteJson(w, http.StatusNotFound, payload)
+		return
+	}
+
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	if !ok {
+		m.Logger.Error("Context is not found")
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	id, err := m.MaterialService.Create(
+		courseId,
+		user.Email,
+		payload.Name,
+	)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			if respErr.Code != "NOT_OWNER" {
+				m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			} else {
+				m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+			}
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(material.CreateMaterialResponse{
+		MaterialId: id,
+	})
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/material/delete_content.go b/handler/material/delete_content.go
new file mode 100644
index 0000000000000000000000000000000000000000..f67bcc3aec47601aeaec8dbfacfc4e3c79285095
--- /dev/null
+++ b/handler/material/delete_content.go
@@ -0,0 +1,89 @@
+package material
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	authToken "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+)
+
+// Index godoc
+//
+//	@Tags			content
+//	@Summary		Delete Content
+//	@Description	Delete content of material
+//	@Produce		json
+//	@Accept			json
+//	@Param			Authorization	header		string	true	"Access token"
+//	@Param			id				path		string	true	"Material id"	Format(uuid)
+//	@Param			content-id		path		string	true	"Content id"	Format(uuid)
+//	@Success		200				{object}	web.BaseResponse
+//	@Router			/material/{id}/content/{content-id} [delete]
+func (m MaterialHandlerImpl) DeleteContent(w http.ResponseWriter, r *http.Request) {
+	materialIdUnparsed := chi.URLParam(r, "material-id")
+
+	if materialIdUnparsed == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	materialId, err := uuid.Parse(materialIdUnparsed)
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is invalid", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	contentIdUnparsed := chi.URLParam(r, "content-id")
+
+	if contentIdUnparsed == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("content id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	contentId, err := uuid.Parse(contentIdUnparsed)
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is invalid", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	if !ok {
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	err = m.MaterialContentService.DeleteContent(
+		materialId,
+		user.Email,
+		contentId,
+	)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			if respErr.Code != "NOT_OWNER" {
+				m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			} else {
+				m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+			}
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(nil)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/material/delete_material.go b/handler/material/delete_material.go
new file mode 100644
index 0000000000000000000000000000000000000000..1bd275c35e0d690045f67f9b61b5f4f5cc705e92
--- /dev/null
+++ b/handler/material/delete_material.go
@@ -0,0 +1,73 @@
+package material
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	authToken "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+)
+
+// Index godoc
+//
+//	@Tags			content
+//	@Summary		Delete material
+//	@Description	Delete material
+//	@Produce		json
+//	@Accept			json
+//	@Param			Authorization	header		string	true	"Access token"
+//	@Param			id				path		string	true	"Material id"	Format(uuid)
+//	@Success		200				{object}	web.BaseResponse
+//	@Router			/material/{id} [delete]
+func (m MaterialHandlerImpl) DeleteMaterial(w http.ResponseWriter, r *http.Request) {
+	materialIdUnparsed := chi.URLParam(r, "material-id")
+
+	if materialIdUnparsed == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	materialId, err := uuid.Parse(materialIdUnparsed)
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is invalid", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	if !ok {
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	err = m.MaterialService.Delete(
+		materialId,
+		user.Email,
+	)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			if respErr.Code != "NOT_OWNER" {
+				m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			} else {
+				m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+			}
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(nil)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+
+}
diff --git a/handler/material/detail_material.go b/handler/material/detail_material.go
new file mode 100644
index 0000000000000000000000000000000000000000..87c428d09d68ddea8b6741dac355083f0082125b
--- /dev/null
+++ b/handler/material/detail_material.go
@@ -0,0 +1,57 @@
+package material
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+)
+
+// Index godoc
+//
+//	@Tags			content
+//	@Summary		Get material detail
+//	@Description	Get material detail
+//	@Produce		json
+//	@Accept			json
+//	@Param			id	path		string	true	"Material id"	example(IF3270)
+//	@Success		200	{object}	web.BaseResponse{data=material.Material}
+//	@Router			/material/{id} [get]
+func (m MaterialHandlerImpl) DetailMaterial(w http.ResponseWriter, r *http.Request) {
+	idString := chi.URLParam(r, "material-id")
+
+	if idString == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("material id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	id, err := uuid.Parse(idString)
+
+	if err != nil {
+		// invalid uuid
+		payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	res, err := m.MaterialService.GetById(id)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(res)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+
+}
diff --git a/handler/material/get_material.go b/handler/material/get_material.go
new file mode 100644
index 0000000000000000000000000000000000000000..0ce5b5ab59c0aff2c604bb3965093ff3e9d242aa
--- /dev/null
+++ b/handler/material/get_material.go
@@ -0,0 +1,46 @@
+package material
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+)
+
+// Index godoc
+//
+//	@Tags			content
+//	@Summary		Get materials
+//	@Description	Get materials
+//	@Produce		json
+//	@Accept			json
+//	@Param			id	path		string	true	"Course id"	example(IF3270)
+//	@Success		200	{object}	web.BaseResponse{data=[]material.Material}
+//	@Router			/course/{id}/materials [get]
+func (m MaterialHandlerImpl) GetMaterial(w http.ResponseWriter, r *http.Request) {
+	courseId := chi.URLParam(r, "id")
+
+	if courseId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("course id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	result, err := m.MaterialService.Get(courseId)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(result)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/material/impl.go b/handler/material/impl.go
new file mode 100644
index 0000000000000000000000000000000000000000..f8aab59ca45cb8ce12796599e6b197e1a0d8c418
--- /dev/null
+++ b/handler/material/impl.go
@@ -0,0 +1,18 @@
+package material
+
+import (
+	"gitlab.informatika.org/ocw/ocw-backend/repository/course"
+	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/service/material"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/httputil"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/wrapper"
+)
+
+type MaterialHandlerImpl struct {
+	material.MaterialService
+	material.MaterialContentService
+	httputil.HttpUtil
+	logger.Logger
+	wrapper.WrapperUtil
+	course.CourseRepository
+}
diff --git a/handler/material/types.go b/handler/material/types.go
new file mode 100644
index 0000000000000000000000000000000000000000..8d968e0f8332c295dcc480310efa3461457d8654
--- /dev/null
+++ b/handler/material/types.go
@@ -0,0 +1,13 @@
+package material
+
+import "net/http"
+
+type MaterialHandler interface {
+	AddContent(w http.ResponseWriter, r *http.Request)
+	DeleteContent(w http.ResponseWriter, r *http.Request)
+
+	CreateMaterial(w http.ResponseWriter, r *http.Request)
+	DetailMaterial(w http.ResponseWriter, r *http.Request)
+	DeleteMaterial(w http.ResponseWriter, r *http.Request)
+	GetMaterial(w http.ResponseWriter, r *http.Request)
+}
diff --git a/handler/quiz/get.go b/handler/quiz/get.go
new file mode 100644
index 0000000000000000000000000000000000000000..799ca822a991240a0c6febccb29640720f1b5e67
--- /dev/null
+++ b/handler/quiz/get.go
@@ -0,0 +1,57 @@
+package quiz
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+)
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			Get Quiz Detail
+//	@Description	Get Quiz Detail
+//	@Produce			json
+//	@Accept				json
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse{data=quiz.Quiz}
+//	@Router				/quiz/{id} [get]
+func (m QuizHandlerImpl) GetQuizDetail(w http.ResponseWriter, r *http.Request) {
+	quizId := chi.URLParam(r, "id")
+
+	if quizId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	id, err := uuid.Parse(quizId)
+
+	if err != nil {
+		// invalid uuid
+		payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	result, err := m.QuizService.GetQuizDetail(id)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(result)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+
+}
diff --git a/handler/quiz/impl.go b/handler/quiz/impl.go
new file mode 100644
index 0000000000000000000000000000000000000000..f95f7e5f0ca56fe2c605c5c3692eb5c4dab1008a
--- /dev/null
+++ b/handler/quiz/impl.go
@@ -0,0 +1,15 @@
+package quiz
+
+import (
+	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/service/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/httputil"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/wrapper"
+)
+
+type QuizHandlerImpl struct {
+	quiz.QuizService
+	wrapper.WrapperUtil
+	httputil.HttpUtil
+	logger.Logger
+}
diff --git a/handler/quiz/list.go b/handler/quiz/list.go
new file mode 100644
index 0000000000000000000000000000000000000000..544894fcc9985ee8ebea4f75fd3032da1ff0fd2d
--- /dev/null
+++ b/handler/quiz/list.go
@@ -0,0 +1,50 @@
+package quiz
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+)
+
+// Index godoc
+//
+//	@Tags					course
+//	@Summary			Get Course quiz
+//	@Description	Get all cours
+//	@Produce			json
+//	@Accept				json
+//	@Param				id path string true "Course id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse{data=[]quiz.Quiz}
+//	@Router				/course/{id}/quiz [get]
+func (m QuizHandlerImpl) GetAllQuizes(w http.ResponseWriter, r *http.Request) {
+	courseId := chi.URLParam(r, "id")
+
+	if courseId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("course id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	result, err := m.QuizService.ListAllQuiz(courseId)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			if respErr.Code != "NOT_OWNER" {
+				m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			} else {
+				m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+			}
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(result)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/quiz/take.go b/handler/quiz/take.go
new file mode 100644
index 0000000000000000000000000000000000000000..530f4f77823001b1a5027b76d610b8c9ccafcaad
--- /dev/null
+++ b/handler/quiz/take.go
@@ -0,0 +1,219 @@
+package quiz
+
+import (
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/go-playground/validator/v10"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	authToken "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/quiz"
+)
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			Take Quiz
+//	@Description	Take a quiz
+//	@Produce			json
+//	@Accept				json
+//	@Param				Authorization	header		string							true "Authenticate User (any role)"
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse{data=quiz.QuizDetail}
+//	@Router				/quiz/{id}/take [post]
+func (m QuizHandlerImpl) TakeQuiz(w http.ResponseWriter, r *http.Request) {
+	rawQuizId := chi.URLParam(r, "id")
+
+	if rawQuizId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	quizId, err := uuid.Parse(rawQuizId)
+
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is not valid", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	if !ok {
+		m.Logger.Error("Context is not found")
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	detail, err := m.DoTakeQuiz(r.Context(), quizId, user.Email)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(detail)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			Get Quiz Solution
+//	@Description	Take a quiz
+//	@Produce			json
+//	@Accept				json
+//	@Param				Authorization	header		string							true "Authenticate User (any role)"
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse{data=quiz.QuizDetail}
+//	@Router				/quiz/{id}/solution [get]
+func (m QuizHandlerImpl) GetQuizSolution(w http.ResponseWriter, r *http.Request) {
+	rawQuizId := chi.URLParam(r, "id")
+
+	if rawQuizId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	quizId, err := uuid.Parse(rawQuizId)
+
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is not valid", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	if !ok {
+		m.Logger.Error("Context is not found")
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	detail, err := m.GetSolutionQuiz(r.Context(), quizId, user.Email)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			if respErr.Code == "ERR_NOT_ALLOWED" {
+				payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+				m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+			} else {
+				payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+				m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			}
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(detail)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			Finish Quiz
+//	@Description	Finish quiz session and get the score
+//	@Produce			json
+//	@Accept				json
+//	@Param				Authorization	header		string										true "Authenticate User (any role)"
+//	@Param			  data	body		quiz.FinishQuizPayload							true	"Quiz Finish payload"
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse{data=quiz.QuizDetail}
+//	@Router				/quiz/{id}/take [post]
+func (m QuizHandlerImpl) FinishQuiz(w http.ResponseWriter, r *http.Request) {
+	payload := quiz.FinishQuizPayload{}
+
+	/* Get user */
+	user, ok := r.Context().Value(guard.UserContext).(authToken.UserClaim)
+
+	if !ok {
+		m.Logger.Error("Context is not found")
+		payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+	/* Get user */
+
+	/* Validate input */
+	validate := validator.New()
+
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := m.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := m.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		m.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := m.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+	/* End of validate */
+
+	/* Get quiz id */
+	rawQuizId := chi.URLParam(r, "id")
+
+	if rawQuizId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	quizId, err := uuid.Parse(rawQuizId)
+
+	if err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is not valid", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+	/* end of get quiz id */
+
+	res, err := m.DoFinishQuiz(r.Context(), quizId, user.Email, payload.Data)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(res)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/quiz/type.go b/handler/quiz/type.go
new file mode 100644
index 0000000000000000000000000000000000000000..8c3bf6f5567cf7f04be9e42b67558279a0f6159d
--- /dev/null
+++ b/handler/quiz/type.go
@@ -0,0 +1,12 @@
+package quiz
+
+import "net/http"
+
+type QuizHandler interface {
+	GetAllQuizes(w http.ResponseWriter, r *http.Request)
+	GetQuizDetail(w http.ResponseWriter, r *http.Request)
+
+	TakeQuiz(w http.ResponseWriter, r *http.Request)
+	GetQuizSolution(w http.ResponseWriter, r *http.Request)
+	FinishQuiz(w http.ResponseWriter, r *http.Request)
+}
diff --git a/handler/reset/confirm.go b/handler/reset/confirm.go
index da9420190d78f8c5938860b8bfca3e9375c90c16..24e5b0934e4e5eb06a639bd63bca7b1946b162c4 100644
--- a/handler/reset/confirm.go
+++ b/handler/reset/confirm.go
@@ -12,14 +12,14 @@ import (
 
 // Index godoc
 //
-//	@Tags					reset
-//	@Summary			Confirm Reset Password
+//	@Tags			reset
+//	@Summary		Confirm Reset Password
 //	@Description	Do confirmation to reset password
-//	@Produce			json
-//	@Param			  Authorization header string true "Email validation token"
-//	@Param				data body confirm.ConfirmRequestPayload true "payload"
-//	@Success			200	{object}	web.BaseResponse "Login Success"
-//	@Router				/reset/confirm [put]
+//	@Produce		json
+//	@Param			Authorization	header		string							true	"Email validation token"
+//	@Param			data			body		confirm.ConfirmRequestPayload	true	"payload"
+//	@Success		200				{object}	web.BaseResponse				"Login Success"
+//	@Router			/reset/confirm [put]
 func (rs ResetHandlerImpl) Confirm(w http.ResponseWriter, r *http.Request) {
 	payload := confirm.ConfirmRequestPayload{}
 	validate := validator.New()
diff --git a/handler/reset/request.go b/handler/reset/request.go
index e118a0261b97d7bd0dbec2cde86644293d786313..ecdea1bf67e9eb60eb729760ca15ea4538e130e0 100644
--- a/handler/reset/request.go
+++ b/handler/reset/request.go
@@ -12,13 +12,13 @@ import (
 
 // Index godoc
 //
-//	@Tags					reset
-//	@Summary			Request Reset Password Token
+//	@Tags			reset
+//	@Summary		Request Reset Password Token
 //	@Description	Send Reset password token to email
-//	@Produce			json
-//	@Param				data body request.RequestRequestPayload true "payload"
-//	@Success			200	{object}	web.BaseResponse "Login Success"
-//	@Router				/reset/request [post]
+//	@Produce		json
+//	@Param			data	body		request.RequestRequestPayload	true	"payload"
+//	@Success		200		{object}	web.BaseResponse				"Login Success"
+//	@Router			/reset/request [post]
 func (rs ResetHandlerImpl) Request(w http.ResponseWriter, r *http.Request) {
 	payload := request.RequestRequestPayload{}
 	validate := validator.New()
diff --git a/handler/reset/validate.go b/handler/reset/validate.go
index 1bfa4dec36c2c1f3f2d2ff94110c80070906c3db..84be1fb797e3217866538dce680306f72bbf8dbb 100644
--- a/handler/reset/validate.go
+++ b/handler/reset/validate.go
@@ -11,13 +11,13 @@ import (
 
 // Index godoc
 //
-//	@Tags					reset
-//	@Summary			Request Reset Password Token
+//	@Tags			reset
+//	@Summary		Request Reset Password Token
 //	@Description	Send Reset password token to email
-//	@Produce			json
-//	@Param			  Authorization header string true "Email validation token"
-//	@Success			200	{object}	web.BaseResponse "Login Success"
-//	@Router				/reset/validate [get]
+//	@Produce		json
+//	@Param			Authorization	header		string				true	"Email validation token"
+//	@Success		200				{object}	web.BaseResponse	"Login Success"
+//	@Router			/reset/validate [get]
 func (rs ResetHandlerImpl) Validate(w http.ResponseWriter, r *http.Request) {
 	payload := validate.ValidateRequestPayload{}
 	validateTokenHeader := r.Header.Get("Authorization")
diff --git a/main.go b/main.go
index 3510a8d8544bff0deb21be27d74fdfeabec819cd..bfd1104b3b07646a97ee856600db25c929e34255 100644
--- a/main.go
+++ b/main.go
@@ -1,8 +1,8 @@
 package main
 
-// @title				Open Courseware Application
-// @version			1.0.1
-// @description	This is Open Couseware backend
+//	@title			Open Courseware Application
+//	@version		1.0.1
+//	@description	This is Open Couseware backend
 func main() {
 	server, err := CreateServer()
 
diff --git a/middleware/guard/builder.go b/middleware/guard/builder.go
index 75850ebf45a8ef08662c76311156cd2a067a4ff3..c0f06a9e6c2324734c1db6f64e5b5eb8e34f46d8 100644
--- a/middleware/guard/builder.go
+++ b/middleware/guard/builder.go
@@ -10,7 +10,9 @@ import (
 )
 
 type GuardBuilder struct {
-	GuardMiddleware
+	token.TokenUtil
+	logger.Logger
+	wrapper.WrapperUtil
 }
 
 func NewBuilder(
@@ -19,25 +21,19 @@ func NewBuilder(
 	wrapper wrapper.WrapperUtil,
 ) *GuardBuilder {
 	return &GuardBuilder{
-		GuardMiddleware{
-			Token:       token,
-			Role:        []user.UserRole{},
-			Logger:      logger,
-			WrapperUtil: wrapper,
-		},
+		token,
+		logger,
+		wrapper,
 	}
 }
 
-func (g *GuardBuilder) AddRole(role ...user.UserRole) *GuardBuilder {
-	g.GuardMiddleware.Role = role
-	return g
-}
-
-func (g *GuardBuilder) Build() func(http.Handler) http.Handler {
-	return g.GuardMiddleware.Handle
-}
+func (g *GuardBuilder) Build(role ...user.UserRole) func(http.Handler) http.Handler {
+	handler := &GuardMiddleware{
+		Token:       g.TokenUtil,
+		Role:        role,
+		Logger:      g.Logger,
+		WrapperUtil: g.WrapperUtil,
+	}
 
-func (g *GuardBuilder) BuildSimple(role user.UserRole) func(http.Handler) http.Handler {
-	g.AddRole(role)
-	return g.Build()
+	return handler.Handle
 }
diff --git a/middleware/guard/guard.go b/middleware/guard/guard.go
index 3b71984a870188559f7345793d786ccfce0f1e6d..487b5cf8e050ef23a52ae79f4afdbab5ca050871 100644
--- a/middleware/guard/guard.go
+++ b/middleware/guard/guard.go
@@ -83,7 +83,7 @@ func (g GuardMiddleware) Handle(next http.Handler) http.Handler {
 				return
 			}
 
-			ctx := context.WithValue(r.Context(), UserContext, claim)
+			ctx := context.WithValue(r.Context(), UserContext, *claim)
 			next.ServeHTTP(w, r.WithContext(ctx))
 			return
 		}
diff --git a/model/domain/course/course.go b/model/domain/course/course.go
index 3d11918d8bea39471ab99306e5dfda5f5d9de3a1..17d592f2301d2bd0097a7fb465e5b8474b46cc09 100644
--- a/model/domain/course/course.go
+++ b/model/domain/course/course.go
@@ -4,28 +4,28 @@ import "github.com/google/uuid"
 
 // TODO: Abbreviations should be unique constrainted as identifiers
 type Faculty struct {
-	ID           uuid.UUID `gorm:"primaryKey"`
-	Name         string
-	Abbreviation string
+	ID           uuid.UUID `json:"id" gorm:"primaryKey"`
+	Name         string    `json:"name"`
+	Abbreviation string    `json:"abbreviation"`
 }
 
 type Major struct {
-	ID           uuid.UUID `gorm:"primaryKey;type:uuid"`
-	Name         string
-	Fac_id       uuid.UUID `gorm:"type:uuid"`
-	Faculty      Faculty   `gorm:"foreignKey:Fac_id"`
-	Abbreviation string
+	ID           uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
+	Name         string    `json:"name"`
+	Fac_id       uuid.UUID `json:"fac_id" gorm:"type:uuid"`
+	Faculty      *Faculty  `json:"faculty" gorm:"foreignKey:Fac_id"`
+	Abbreviation string    `json:"abbreviation"`
 }
 
 type Course struct {
-	ID           string `gorm:"primaryKey"`
-	Name         string
-	Major_id     uuid.UUID `gorm:"type:uuid"`
-	Major        Major     `gorm:"foreignKey:Major_id"`
-	Description  string
-	Email        string
-	Abbreviation string
-	Lecturer     string
+	ID           string    `json:"id" gorm:"primaryKey"`
+	Name         string    `json:"name"`
+	Major_id     uuid.UUID `json:"major_id" gorm:"type:uuid"`
+	Major        *Major    `json:"major" gorm:"foreignKey:Major_id"`
+	Description  string    `json:"description"`
+	Email        string    `json:"email"`
+	Abbreviation string    `json:"abbreviation"`
+	Lecturer     string    `json:"lecturer"`
 }
 
 func (Faculty) TableName() string {
diff --git a/model/domain/material/content.go b/model/domain/material/content.go
index 0e181045ba1141a363e07b196bf985c9fc0f4adf..c68f1587cd6dd653f04433cca81a1946d1ad0277 100644
--- a/model/domain/material/content.go
+++ b/model/domain/material/content.go
@@ -3,10 +3,10 @@ package material
 import "github.com/google/uuid"
 
 type Content struct {
-	Id         uuid.UUID `gorm:"primaryKey"`
-	Type       MaterialType
-	Link       string
-	MaterialId uuid.UUID
+	Id         uuid.UUID    `gorm:"primaryKey" json:"id"`
+	Type       MaterialType `json:"type"`
+	Link       string       `json:"link"`
+	MaterialID uuid.UUID    `json:"material_id"`
 }
 
 func (Content) TableName() string {
diff --git a/model/domain/material/material.go b/model/domain/material/material.go
index 55d6bfbf7d002af41a7edc6bdb50beed800650a0..fa4d788dc7dad157bdc6e9c310c824722dad0bc4 100644
--- a/model/domain/material/material.go
+++ b/model/domain/material/material.go
@@ -2,17 +2,15 @@ package material
 
 import (
 	"github.com/google/uuid"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 )
 
 type Material struct {
-	Id           uuid.UUID `gorm:"primaryKey"`
-	CourseId     string
-	CreatorEmail string
-	Creator      user.User     `gorm:"foreignKey:CreatorEmail;references:Email"`
-	Course       course.Course `gorm:"foreignKey:CourseId;references:Id"`
-	Contents     []Content     `gorm:"foreignKey:MaterialId;references:Id"`
+	ID           uuid.UUID `json:"id" gorm:"primaryKey"`
+	CourseId     string    `json:"course_id"`
+	CreatorEmail string    `json:"creator_email"`
+	Name         string    `json:"name"`
+	Week         int       `json:"week"`
+	Contents     []Content `json:"contents"`
 }
 
 func (Material) TableName() string {
diff --git a/model/domain/material/material_type.go b/model/domain/material/material_type.go
index 10e8abdc730e658f28f99da007bb755fc6896795..b8c7aec0193c2c71384f36b5ce2731d24be5f850 100644
--- a/model/domain/material/material_type.go
+++ b/model/domain/material/material_type.go
@@ -10,8 +10,8 @@ import (
 type MaterialType int
 
 const (
-	Video MaterialType = iota
-	Handout
+	Handout MaterialType = iota + 1
+	Video
 	External
 )
 
diff --git a/model/domain/quiz/options.go b/model/domain/quiz/options.go
deleted file mode 100644
index de062c3cc531f34b4572016248e2085a2d1f1d99..0000000000000000000000000000000000000000
--- a/model/domain/quiz/options.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package quiz
-
-import "github.com/google/uuid"
-
-type AnswerOption struct {
-	Id            uuid.UUID `gorm:"primaryKey"`
-	QuizProblemId uuid.UUID `gorm:"primaryKey"`
-	Statement     string
-	IsAnswer      bool
-}
-
-func (AnswerOption) TableName() string {
-	return "quiz_choice_answer"
-}
diff --git a/model/domain/quiz/problem.go b/model/domain/quiz/problem.go
new file mode 100644
index 0000000000000000000000000000000000000000..7794b7f4355177f0ce5a948d11c6ff3f62aa89de
--- /dev/null
+++ b/model/domain/quiz/problem.go
@@ -0,0 +1,38 @@
+package quiz
+
+import "github.com/google/uuid"
+
+type QuizMedia struct {
+	Id   uuid.UUID `json:"id"`
+	Url  string    `json:"url"`
+	Type string    `json:"type"`
+}
+
+type AnswerOption struct {
+	Id         uuid.UUID   `json:"id"`
+	MediaId    []uuid.UUID `json:"media_id"`
+	Answer     string      `json:"answer"`
+	IsSolution *bool       `json:"is_solution"`
+}
+
+type QuizProblem struct {
+	Id       uuid.UUID      `json:"id"`
+	MediaId  []uuid.UUID    `json:"media_id"`
+	Question string         `json:"question"`
+	Answer   []AnswerOption `json:"answers"`
+}
+
+type QuizDetail struct {
+	Id          uuid.UUID     `json:"id"`
+	Name        string        `json:"name"`
+	CourseId    string        `json:"course_id"`
+	Description string        `json:"description"`
+	Help        string        `json:"help"`
+	Media       []QuizMedia   `json:"media"`
+	Problems    []QuizProblem `json:"problems"`
+}
+
+type Response struct {
+	ProblemId uuid.UUID `json:"problem_id"`
+	AnswerId  uuid.UUID `json:"answer_id"`
+}
diff --git a/model/domain/quiz/problem_type.go b/model/domain/quiz/problem_type.go
deleted file mode 100644
index c03621526c635dc524f1caee1518665931b80d10..0000000000000000000000000000000000000000
--- a/model/domain/quiz/problem_type.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package quiz
-
-import (
-	"database/sql/driver"
-	"encoding/json"
-	"errors"
-	"fmt"
-)
-
-type ProblemType int
-
-const (
-	Choice ProblemType = iota
-)
-
-var roleMapping = map[ProblemType]string{
-	Choice: "choice",
-}
-
-func (ur *ProblemType) Scan(value interface{}) error {
-	val := value.(string)
-
-	for key, label := range roleMapping {
-		if label == val {
-			*ur = key
-			return nil
-		}
-	}
-
-	return fmt.Errorf("invalid user role")
-}
-
-func (u ProblemType) Value() (driver.Value, error) {
-	value, ok := roleMapping[u]
-
-	if !ok {
-		return nil, fmt.Errorf("invalid user role")
-	}
-
-	return value, nil
-}
-
-func (u *ProblemType) UnmarshalJSON(b []byte) error {
-	var s string
-	if err := json.Unmarshal(b, &s); err != nil {
-		return err
-	}
-
-	for key, label := range roleMapping {
-		if label == s {
-			*u = key
-			return nil
-		}
-	}
-
-	return fmt.Errorf("unkown role, given %s", s)
-}
-
-func (u ProblemType) MarshalJSON() ([]byte, error) {
-	s, ok := roleMapping[u]
-
-	if !ok {
-		return nil, errors.New("unkown user role")
-	}
-
-	return json.Marshal(s)
-}
diff --git a/model/domain/quiz/quiz.go b/model/domain/quiz/quiz.go
index 6caade417ae857ec2a78fdf8c13b5ef007a8529a..896536cc66c3ffbca9840836c446019b139e8074 100644
--- a/model/domain/quiz/quiz.go
+++ b/model/domain/quiz/quiz.go
@@ -2,18 +2,14 @@ package quiz
 
 import (
 	"github.com/google/uuid"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 )
 
 type Quiz struct {
-	Id           uuid.UUID `gorm:"primaryKey"`
-	Name         string
-	CourseId     string
-	CreatorEmail string
-	Creator      user.User     `gorm:"foreignKey:CreatorEmail;references:Email"`
-	Course       course.Course `gorm:"foreignKey:CourseId;references:Id"`
-	Problems     []QuizProblem `gorm:"foreignKey:QuizId;references:Id"`
+	Id           uuid.UUID `gorm:"primaryKey" json:"id"`
+	Name         string    `json:"nama"`
+	CourseId     string    `json:"course_id"`
+	CreatorEmail string    `json:"creator_email"`
+	QuizPath     string    `json:"-"`
 }
 
 func (Quiz) TableName() string {
diff --git a/model/domain/quiz/quiz_problem.go b/model/domain/quiz/quiz_problem.go
deleted file mode 100644
index 3ce4195465d2fd477567f18858296d949c60020c..0000000000000000000000000000000000000000
--- a/model/domain/quiz/quiz_problem.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package quiz
-
-import "github.com/google/uuid"
-
-type QuizProblem struct {
-	Id        uuid.UUID `gorm:"primaryKey"`
-	Statement string
-	Type      ProblemType
-	QuizId    uuid.UUID
-	Options   []AnswerOption `gorm:"foreignKey:QuizProblemId;references:Id"`
-}
-
-func (QuizProblem) TableName() string {
-	return "quiz_problem"
-}
diff --git a/model/domain/quiz/take.go b/model/domain/quiz/take.go
index c66263f60f1e4009019e5dcd428e7c905784f243..399989d2db63432372643f615caecafee0cbc896 100644
--- a/model/domain/quiz/take.go
+++ b/model/domain/quiz/take.go
@@ -1,22 +1,18 @@
 package quiz
 
 import (
-	"os/user"
 	"time"
 
 	"github.com/google/uuid"
 )
 
 type QuizTake struct {
-	Id            uuid.UUID `gorm:"primaryKey"`
-	QuizId        uuid.UUID
-	Email         string
-	StartTime     time.Time
-	IsFinished    bool
-	Score         int
-	Quiz          `gorm:"foreignKey:QuizId;references:Id"`
-	user.User     `gorm:"foreignKey:Email;references:Email"`
-	ChoiceAnswers []TakeChoiceAnswer `gorm:"foreignKey:QuizTakeId;references:Id"`
+	Id         uuid.UUID `gorm:"primaryKey" json:"id"`
+	QuizId     uuid.UUID `json:"quiz_id"`
+	Email      string    `json:"email"`
+	StartTime  time.Time `json:"start"`
+	IsFinished bool      `json:"finished"`
+	Score      int       `json:"score"`
 }
 
 func (QuizTake) TableName() string {
diff --git a/model/domain/quiz/take_choice_answer.go b/model/domain/quiz/take_choice_answer.go
deleted file mode 100644
index 25e76746d8951251d3dbdee694986205ce364d53..0000000000000000000000000000000000000000
--- a/model/domain/quiz/take_choice_answer.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package quiz
-
-import "github.com/google/uuid"
-
-type TakeChoiceAnswer struct {
-	QuizTakeId    uuid.UUID `gorm:"primaryKey"`
-	AnswerChoice  uuid.UUID
-	QuizProblemId uuid.UUID `gorm:"primaryKey"`
-	AnswerOption  `gorm:"foreignKey:AnswerChoice,QuizProblemId;references:Id,QuizProblemId"`
-}
-
-func (TakeChoiceAnswer) TableName() string {
-	return "quiz_take_choice_answer"
-}
diff --git a/model/domain/user/user.go b/model/domain/user/user.go
index f2fbb565f6dd4aa94cbf7f15b260980ead0351f9..ad56084aa4fddda0f60e71d8de8819589e467bf1 100644
--- a/model/domain/user/user.go
+++ b/model/domain/user/user.go
@@ -3,13 +3,13 @@ package user
 import "time"
 
 type User struct {
-	Email       string `gorm:"primaryKey"`
-	Password    string
-	Name        string
-	Role        UserRole `gorm:"type:user_role"`
-	IsActivated bool
-	CreatedAt   time.Time
-	UpdatedAt   time.Time
+	Email       string    `gorm:"primaryKey" json:"email"`
+	Password    string    `json:"-"`
+	Name        string    `json:"name"`
+	Role        UserRole  `gorm:"type:user_role" json:"role"`
+	IsActivated bool      `json:"activated"`
+	CreatedAt   time.Time `json:"created_at"`
+	UpdatedAt   time.Time `json:"updated_at"`
 }
 
 func (User) TableName() string {
diff --git a/model/web/admin/addUser/request.go b/model/web/admin/addUser/request.go
index c08f743abc16843b3c0ca60c3725ac24d348db05..d1166ee9bdbcf0b870f7452c317c1fa295592c36 100644
--- a/model/web/admin/addUser/request.go
+++ b/model/web/admin/addUser/request.go
@@ -1,7 +1,7 @@
 package admin
 
 // AdminAddUserPayload Request Payload
-// @Description Information that should be available when admin add user
+//	@Description	Information that should be available when admin add user
 
 // TODO: find a way to make default password for new user
 
diff --git a/model/web/admin/updateUser/request.go b/model/web/admin/updateUser/request.go
index 437d35fa7e7f5f415fea0ab49ec84f09c246ff7e..de60152fab122e1d48b48a172096c5d7a0db334c 100644
--- a/model/web/admin/updateUser/request.go
+++ b/model/web/admin/updateUser/request.go
@@ -1,7 +1,7 @@
 package admin
 
 // AdminUpdateUserPayload Request Payload
-// @Description Information that should be available when admin update user
+//	@Description	Information that should be available when admin update user
 
 type AdminUpdateUserPayload struct {
 	// User name
diff --git a/model/web/auth/login/request.go b/model/web/auth/login/request.go
index 716c505d9eb29cfcaf8a55c7561d4885fb1f2e7c..a5b9fa5000728b8884fdcc9c6118c7876739f480 100644
--- a/model/web/auth/login/request.go
+++ b/model/web/auth/login/request.go
@@ -1,7 +1,7 @@
 package login
 
 // Login Request Payload
-// @Description Information that should be available when do a login process
+//	@Description	Information that should be available when do a login process
 type LoginRequestPayload struct {
 	// User Email
 	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
diff --git a/model/web/auth/login/response.go b/model/web/auth/login/response.go
index 8cb68ca68d2c5491b090dba2f96240d9d6f143af..c961e2e24673721959fc1999c8210ad10d45399b 100644
--- a/model/web/auth/login/response.go
+++ b/model/web/auth/login/response.go
@@ -1,7 +1,7 @@
 package login
 
 // Login Response Payload
-// @Description Login response when process success
+//	@Description	Login response when process success
 type LoginResponsePayload struct {
 	// Token that used to generate new access token
 	RefreshToken string `json:"refresh_token"`
diff --git a/model/web/auth/refresh/response.go b/model/web/auth/refresh/response.go
index f349ba6e3e2d9b70ad0fd08680d046e1a6ad9ba8..80e35164afd41fd54b1d02902a72ed1872e57232 100644
--- a/model/web/auth/refresh/response.go
+++ b/model/web/auth/refresh/response.go
@@ -1,7 +1,7 @@
 package refresh
 
 // Refresh Response Payload
-// @Description Refresh endpoint response when process success
+//	@Description	Refresh endpoint response when process success
 type RefreshResponsePayload struct {
 	// Token that used to access the resources
 	AccessToken string `json:"access_token"`
diff --git a/model/web/auth/register/request.go b/model/web/auth/register/request.go
index 48d58105956364d445c27ea82129f2d0c27581eb..7a8a7d1394b5c151c4926fdc6e3795d9e1464fd5 100644
--- a/model/web/auth/register/request.go
+++ b/model/web/auth/register/request.go
@@ -1,7 +1,7 @@
 package register
 
 // Register Request Payload
-// @Description Information that should be available when do a registration process
+//	@Description	Information that should be available when do a registration process
 type RegisterRequestPayload struct {
 	// User Email
 	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
diff --git a/model/web/auth/token/token.go b/model/web/auth/token/token.go
index 497287e4d77c377c904e1161d0797f04ba022e04..fc57bf693dfd7092d889462a751f6979df6a09e0 100644
--- a/model/web/auth/token/token.go
+++ b/model/web/auth/token/token.go
@@ -7,8 +7,9 @@ import (
 
 type UserClaim struct {
 	jwt.RegisteredClaims
-	Name  string        `json:"name"`
-	Email string        `json:"email"`
-	Role  user.UserRole `json:"role"`
-	Type  TokenType     `json:"type"`
+	Name       string        `json:"name"`
+	Email      string        `json:"email"`
+	Role       user.UserRole `json:"role"`
+	Type       TokenType     `json:"type"`
+	IsVerified bool          `json:"is_verified"`
 }
diff --git a/model/web/auth/verification/request.go b/model/web/auth/verification/request.go
index dfddab4ba7adb0585a2147daa85ecfbfce77b25e..cd408e92fdd61b01d43fd857cfecbeefd314a006 100644
--- a/model/web/auth/verification/request.go
+++ b/model/web/auth/verification/request.go
@@ -1,7 +1,7 @@
 package verification
 
 // Email Verification Request Payload
-// @Description Information that should be passed when request verify
+//	@Description	Information that should be passed when request verify
 type VerificationSendRequestPayload struct {
 	// User Email
 	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
diff --git a/model/web/course/add/request.go b/model/web/course/add/request.go
deleted file mode 100644
index 0b86f3ab6618ef4ec1f7f299b0fd45c81bfb61dc..0000000000000000000000000000000000000000
--- a/model/web/course/add/request.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package add
-
-import "github.com/google/uuid"
-
-// AddCourse Request Payload
-// @Description Information that should be available when you add a course
-type AddCourseRequestPayload struct {
-	// Web Token that was appended to the link
-	AddCourseToken string
-
-	// Course ID
-	ID string `json:"id" validate:"required"`
-
-	// Course Name
-	Name string `json:"name" validate:"required"`
-
-	// Course Major Abbreviation
-	MajAbbr string `json:"majabbr" validate:"required_without=MajorID"`
-
-	// Major Id, will be set by the server
-	MajorID uuid.UUID `json:"major_id"`
-
-	// Course Description (Can be left empty)
-	Description string `json:"description"`
-
-	// Contributor Email
-	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
-
-	// Course Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
-}
diff --git a/model/web/course/delete/request.go b/model/web/course/delete/request.go
deleted file mode 100644
index fdfcdbc2809b1e2ad428cae959569dc84703b6d3..0000000000000000000000000000000000000000
--- a/model/web/course/delete/request.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package delete
-
-// DeleteCourse Request Payload
-// @Description Information that should be available when you delete using course id (string)
-type DeleteByStringRequestPayload struct {
-	// Web Token that was appended to the link
-	DeleteCourseToken string
-
-	// Course ID, provided by query
-	ID string
-}
diff --git a/model/web/course/faculty/add/request.go b/model/web/course/faculty/add/request.go
deleted file mode 100644
index fb7c2da86ab96c2c326748d03704ef7c62e07d39..0000000000000000000000000000000000000000
--- a/model/web/course/faculty/add/request.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package add
-
-// AddFaculty Request Payload
-// @Description Information that should be available when you add a faculty
-type AddFacultyRequestPayload struct {
-	// Web Token that was appended to the link
-	AddFacultyToken string
-
-	// Faculty Name
-	Name string `json:"name" validate:"required"`
-
-	// Faculty Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
-}
diff --git a/model/web/course/faculty/request.go b/model/web/course/faculty/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..1c08bddf6fc2410cc7bdec8542c9edc17f5a95e9
--- /dev/null
+++ b/model/web/course/faculty/request.go
@@ -0,0 +1,32 @@
+package faculty
+
+import "github.com/google/uuid"
+
+// AddFaculty Request Payload
+//	@Description	Information that should be available when you add a faculty
+type AddFacultyRequestPayload struct {
+	// Web Token that was appended to the link
+	AddFacultyToken string `json:"faculty_token"`
+
+	// Faculty Name
+	Name string `json:"name" validate:"required"`
+
+	// Faculty Name Abbreviation
+	Abbreviation string `json:"abbreviation" validate:"required"`
+}
+
+// UpdateFaculty Request Payload
+//	@Description	Information that should be available when you update a faculty
+type UpdateFacultyRequestPayload struct {
+	// Web Token that was appended to the link
+	UpdateFacultyToken string
+
+	// Faculty ID, Provided by Query
+	ID uuid.UUID
+
+	// Faculty Name
+	Name string `json:"name" validate:"required"`
+
+	// Faculty Name Abbreviation
+	Abbreviation string `json:"abbreviation" validate:"required"`
+}
\ No newline at end of file
diff --git a/model/web/course/faculty/update/request.go b/model/web/course/faculty/update/request.go
deleted file mode 100644
index 38f04860abe184ab7e61182c538c8a4b39003885..0000000000000000000000000000000000000000
--- a/model/web/course/faculty/update/request.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package update
-
-import "github.com/google/uuid"
-
-// UpdateFaculty Request Payload
-// @Description Information that should be available when you update a faculty
-type UpdateFacultyRequestPayload struct {
-	// Web Token that was appended to the link
-	UpdateFacultyToken string
-
-	// Faculty ID, Provided by Query
-	ID uuid.UUID
-
-	// Faculty Name
-	Name string `json:"name" validate:"required"`
-
-	// Faculty Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
-}
diff --git a/model/web/course/get/request.go b/model/web/course/get/request.go
deleted file mode 100644
index 7f1853ea4ad2051e145d01cb86b45f68c7804f44..0000000000000000000000000000000000000000
--- a/model/web/course/get/request.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package get
-
-import "github.com/google/uuid"
-
-// GetCourse Request Payload
-// @Description Information that should be available when you get using course id (string)
-type GetByStringRequestPayload struct {
-	// Course ID, provided by query
-	ID string
-}
-
-// GetCourse Request Payload
-// @Description Information that should be available when you get using major/faculty id (string)
-type GetByUUIDRequestPayload struct {
-	// Major/Faculty ID, provided by query
-	ID uuid.UUID
-}
\ No newline at end of file
diff --git a/model/web/course/major/add/request.go b/model/web/course/major/add/request.go
deleted file mode 100644
index fbc207644da74f83915b6ac16456d03b9a8efd1d..0000000000000000000000000000000000000000
--- a/model/web/course/major/add/request.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package add
-
-import "github.com/google/uuid"
-
-// AddMajor Request Payload
-// @Description Information that should be available when you add a major
-type AddMajorRequestPayload struct {
-	// Web Token that was appended to the link
-	AddMajorToken string
-
-	// Major Name
-	Name string `json:"name" validate:"required"`
-
-	// Major Faculty Abbreviation
-	FacAbbr string `json:"facabbr" validate:"required_without=FacultyID"`
-
-	// Faculty Id, will be set by the server
-	FacultyID uuid.UUID `json:"faculty_id"`
-
-	// Major Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
-}
diff --git a/model/web/course/major/request.go b/model/web/course/major/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..53bc733584b8c437905b7bf7ef9d3a636866262b
--- /dev/null
+++ b/model/web/course/major/request.go
@@ -0,0 +1,45 @@
+package major
+
+import "github.com/google/uuid"
+
+// AddMajor Request Payload
+//	@Description	Information that should be available when you add a major
+type AddMajorRequestPayload struct {
+	// Web Token that was appended to the link
+	AddMajorToken string `json:"major_token"`
+
+	// Major Name
+	Name string `json:"name" validate:"required"`
+
+	// Major Faculty Abbreviation
+	FacAbbr string `json:"facabbr" validate:"required_without=FacultyID"`
+
+	// Faculty Id, will be set by the server
+	FacultyID uuid.UUID `json:"faculty_id"`
+
+	// Major Name Abbreviation
+	Abbreviation string `json:"abbreviation" validate:"required"`
+}
+
+
+// UpdateMajor Request Payload
+//	@Description	Information that should be available when you update a major
+type UpdateMajorRequestPayload struct {
+	// Web Token that was appended to the link
+	UpdateMajorToken string
+
+	// Major ID, provided by query
+	ID uuid.UUID
+
+	// Major Name
+	Name string `json:"name" validate:"required"`
+
+	// Major Faculty Abbreviation
+	FacAbbr string `json:"facabbr" validate:"required_without=FacultyID"`
+
+	// Faculty Id, will be set by the server
+	FacultyID uuid.UUID `json:"faculty_id"`
+
+	// Major Name Abbreviation
+	Abbreviation string `json:"abbreviation" validate:"required"`
+}
diff --git a/model/web/course/major/update/request.go b/model/web/course/major/update/request.go
deleted file mode 100644
index b024427a8fdc6ed1d3851d10be75bec67a40aa71..0000000000000000000000000000000000000000
--- a/model/web/course/major/update/request.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package update
-
-import "github.com/google/uuid"
-
-// UpdateMajor Request Payload
-// @Description Information that should be available when you update a major
-type UpdateMajorRequestPayload struct {
-	// Web Token that was appended to the link
-	UpdateMajorToken string
-
-	// Major ID, provided by query
-	ID uuid.UUID
-
-	// Major Name
-	Name string `json:"name" validate:"required"`
-
-	// Major Faculty Abbreviation
-	FacAbbr string `json:"facabbr" validate:"required_without=FacultyID"`
-
-	// Faculty Id, will be set by the server
-	FacultyID uuid.UUID `json:"faculty_id"`
-
-	// Major Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
-}
diff --git a/model/web/course/request.go b/model/web/course/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..0fad2befd53b36b1722fa4d295123606277841e3
--- /dev/null
+++ b/model/web/course/request.go
@@ -0,0 +1,89 @@
+package course
+
+import "github.com/google/uuid"
+
+// AddCourse Request Payload
+//	@Description	Information that should be available when you add a course
+type AddCourseRequestPayload struct {
+	// Web Token that was appended to the link
+	AddCourseToken string
+
+	// Course ID
+	ID string `json:"id" validate:"required"`
+
+	// Course Name
+	Name string `json:"name" validate:"required"`
+
+	// Course Major Abbreviation
+	MajAbbr string `json:"majabbr" validate:"required_without=MajorID"`
+
+	// Major Id, will be set by the server
+	MajorID uuid.UUID `json:"major_id"`
+
+	// Course Description (Can be left empty)
+	Description string `json:"description"`
+
+	// Contributor Email
+	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
+
+	// Course Name Abbreviation
+	Abbreviation string `json:"abbreviation" validate:"required"`
+}
+
+// DeleteCourse Request Payload
+//	@Description	Information that should be available when you delete using course id (string)
+type DeleteByStringRequestPayload struct {
+	// Web Token that was appended to the link
+	DeleteCourseToken string
+
+	// Course ID, provided by query
+	ID string
+}
+
+
+// GetID Request Payload
+//	@Description	Information that should be available when you get using course id (string)
+type GetByStringRequestPayload struct {
+	// Course ID, provided by query
+	ID string
+}
+
+// GetUUID Request Payload
+//	@Description	Information that should be available when you get using major/faculty id (string)
+type GetByUUIDRequestPayload struct {
+	// Major/Faculty ID, provided by query
+	ID uuid.UUID
+}
+
+// UpdateCourse Request Payload
+//	@Description	Information that should be available when you add a course
+type UpdateCourseRequestPayload struct {
+	// Web Token that was appended to the link
+	UpdateCourseToken string
+
+	// Course ID, Provided by query
+	ID string `json:"id"`
+
+	// Course Name
+	Name string `json:"name" validate:"required"`
+
+	// Course Major Abbreviation
+	MajAbbr string `json:"majabbr" validate:"required_without=MajorID"`
+
+	// Major Id, will be set by the server
+	MajorID uuid.UUID `json:"major_id"`
+
+	// Course Description (Can be left empty)
+	Description string `json:"description"`
+
+	// Contributor Email
+	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
+
+	// Course Name Abbreviation
+	Abbreviation string `json:"abbreviation" validate:"required"`
+
+	// Course Lecturer
+	Lecturer string `json:"lecturer" validate:"required"`
+}
+
+
diff --git a/model/web/course/update/request.go b/model/web/course/update/request.go
deleted file mode 100644
index 59d2b4c9f91503df99ca15808f7b73d2412e8e07..0000000000000000000000000000000000000000
--- a/model/web/course/update/request.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package update
-
-import "github.com/google/uuid"
-
-// UpdateCourse Request Payload
-// @Description Information that should be available when you add a course
-type UpdateCourseRequestPayload struct {
-	// Web Token that was appended to the link
-	UpdateCourseToken string
-
-	// Course ID, Provided by query
-	ID string
-
-	// Course Name
-	Name string `json:"name" validate:"required"`
-
-	// Course Major Abbreviation
-	MajAbbr string `json:"majabbr" validate:"required_without=MajorID"`
-
-	// Major Id, will be set by the server
-	MajorID uuid.UUID `json:"major_id"`
-
-	// Course Description (Can be left empty)
-	Description string `json:"description"`
-
-	// Contributor Email
-	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
-
-	// Course Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
-
-	// Course Lecturer
-	Lecturer string `json:"lecturer" validate:"required"`
-}
diff --git a/model/web/material/content.go b/model/web/material/content.go
new file mode 100644
index 0000000000000000000000000000000000000000..d3575b4a9314057b0816d2316bade8e250f610aa
--- /dev/null
+++ b/model/web/material/content.go
@@ -0,0 +1,21 @@
+package material
+
+import (
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
+)
+
+type NewContentRequest struct {
+	Type       material.MaterialType `json:"type" validate:"required"`
+	Link       string                `json:"link"`
+	MaterialId uuid.UUID             `json:"-"`
+}
+
+type NewContentResponse struct {
+	UploadLink string `json:"upload_link"`
+}
+
+type DeleteContentRequest struct {
+	ContentId  uuid.UUID `json:"content_id"`
+	MaterialId uuid.UUID `json:"-"`
+}
diff --git a/model/web/material/material.go b/model/web/material/material.go
new file mode 100644
index 0000000000000000000000000000000000000000..98f8c6cdae84025cf0079c2df683a3be1767420b
--- /dev/null
+++ b/model/web/material/material.go
@@ -0,0 +1,15 @@
+package material
+
+import "github.com/google/uuid"
+
+type CreateMaterialRequest struct {
+	Name string `json:"name" validate:"required"`
+}
+
+type CreateMaterialResponse struct {
+	MaterialId uuid.UUID `json:"material_id"`
+}
+
+type DeleteMaterialRequest struct {
+	MaterialId uuid.UUID `json:"material_id"`
+}
diff --git a/model/web/quiz/finish.go b/model/web/quiz/finish.go
new file mode 100644
index 0000000000000000000000000000000000000000..80c7335963d5977527460cf5ada30201865723e4
--- /dev/null
+++ b/model/web/quiz/finish.go
@@ -0,0 +1,7 @@
+package quiz
+
+import "gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
+
+type FinishQuizPayload struct {
+	Data []quiz.Response `json:"data"`
+}
diff --git a/model/web/reset/confirm/request.go b/model/web/reset/confirm/request.go
index 6d864a35e49373198dfff3fe18da82094519c052..78e16a1ca1ade345d4b76c693034a17d8f6e9043 100644
--- a/model/web/reset/confirm/request.go
+++ b/model/web/reset/confirm/request.go
@@ -1,7 +1,7 @@
 package confirm
 
 // Confirm Request Payload
-// @Description Information that should be available when you confirm a password reset
+//	@Description	Information that should be available when you confirm a password reset
 type ConfirmRequestPayload struct {
 	// Web Token that was appended to the link
 	ConfirmToken string
diff --git a/model/web/reset/request/request.go b/model/web/reset/request/request.go
index cdd5d15bfbbf4cdccbe381d1af776bf58a299b36..c589cce1e380c001b0f8d5d248f7f2c513bf19d9 100644
--- a/model/web/reset/request/request.go
+++ b/model/web/reset/request/request.go
@@ -1,7 +1,7 @@
 package request
 
 // Request Request Payload
-// @Description Information that should be available when password reset is requested
+//	@Description	Information that should be available when password reset is requested
 type RequestRequestPayload struct {
 	// User Email
 	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
diff --git a/model/web/reset/validate/request.go b/model/web/reset/validate/request.go
index f13973a086b4048d637a660d08c75076a5ec3378..72f94995730c4a8410eb5efe37dcd24d6bb9b349 100644
--- a/model/web/reset/validate/request.go
+++ b/model/web/reset/validate/request.go
@@ -1,7 +1,7 @@
 package validate
 
 // Validate Request Payload
-// @Description Information that should be available when link validation is done
+//	@Description	Information that should be available when link validation is done
 type ValidateRequestPayload struct {
 	// Web Token that was appended to the link
 	ValidateToken string
diff --git a/provider/storage/manager.go b/provider/storage/manager.go
index cc87edd73acda90734470345e5fd3ea1230a1280..cfeae57144fe4d23729a2382984360253e5d4659 100644
--- a/provider/storage/manager.go
+++ b/provider/storage/manager.go
@@ -9,3 +9,16 @@ import (
 func (s S3Storage) Delete(ctx context.Context, path string) error {
 	return s.minio.RemoveObject(ctx, s.env.BucketName, path, minio.RemoveObjectOptions{})
 }
+
+func (s S3Storage) Get(ctx context.Context, path string) ([]byte, error) {
+	result := []byte{}
+	obj, err := s.minio.GetObject(ctx, s.env.BucketName, path, minio.GetObjectOptions{})
+
+	if err != nil {
+		return result, err
+	}
+
+	_, err = obj.Read(result)
+
+	return result, err
+}
diff --git a/provider/storage/s3.go b/provider/storage/s3.go
index 3f746712f3fa34c1ae77ea87fe4491282e4a6609..52aaaaba702a12c947c98df8ecef737db8ed3009 100644
--- a/provider/storage/s3.go
+++ b/provider/storage/s3.go
@@ -14,10 +14,15 @@ type S3Storage struct {
 func NewS3(
 	env *env.Environment,
 ) (*S3Storage, error) {
-	client, err := minio.New(env.BucketEndpoint, &minio.Options{
+	if !env.UseBucket {
+		return nil, nil
+	}
+
+	settings := &minio.Options{
 		Creds:  credentials.NewStaticV4(env.BucketAccessKey, env.BucketSecretKey, env.BucketTokenKey),
 		Secure: env.BucketUseSSL,
-	})
+	}
+	client, err := minio.New(env.BucketEndpoint, settings)
 
 	if err != nil {
 		return nil, err
diff --git a/provider/storage/type.go b/provider/storage/type.go
index dc7cdd2f97597d8760d26aa2b75791989a12ff9f..19f2a46fb4d9044839660ba4234f47f5f661f0d2 100644
--- a/provider/storage/type.go
+++ b/provider/storage/type.go
@@ -9,4 +9,5 @@ type Storage interface {
 	CreatePutSignedLink(ctx context.Context, path string) (string, error)
 	CreateGetSignedLink(ctx context.Context, path string, reqParam url.Values) (string, error)
 	Delete(ctx context.Context, path string) error
+	Get(ctx context.Context, path string) ([]byte, error)
 }
diff --git a/repository/course/course.go b/repository/course/course.go
index 6b5d06ee1121b393081d5f4421b41d825614a844..1dbeee3dd4f0ed06fbb3daf9655e10fc67a8c579 100644
--- a/repository/course/course.go
+++ b/repository/course/course.go
@@ -33,6 +33,20 @@ func (repo CourseRepositoryImpl) IsCourseExist(id string) (bool, error) {
 	return true, nil
 }
 
+func (repo CourseRepositoryImpl) IsUserCourseContributor(id string, email string) (bool, error) {
+	err := repo.db.Where("course_id = ? AND email = ?").Find(&course.Course{}).Error
+
+	if err == nil {
+		return true, nil
+	}
+
+	if errors.Is(err, gorm.ErrRecordNotFound) {
+		return false, nil
+	}
+
+	return false, err
+}
+
 func (repo CourseRepositoryImpl) IsMajorExist(id uuid.UUID) (bool, error) {
 	_, err := repo.GetMajor(id)
 
@@ -66,10 +80,18 @@ func (repo CourseRepositoryImpl) AddCourse(course course.Course) error {
 }
 
 func (repo CourseRepositoryImpl) AddMajor(major course.Major) error {
+	if id, err := uuid.NewUUID(); err != nil {
+		major.ID = id
+	}
+
 	return repo.db.Create(&major).Error
 }
 
 func (repo CourseRepositoryImpl) AddFaculty(faculty course.Faculty) error {
+	if id, err := uuid.NewUUID(); err != nil {
+		faculty.ID = id
+	}
+
 	return repo.db.Create(&faculty).Error
 }
 
@@ -141,7 +163,7 @@ func (repo CourseRepositoryImpl) GetAllFaculty() ([]course.Faculty, error) {
 
 func (repo CourseRepositoryImpl) GetAllCourseByMajor(id uuid.UUID) ([]course.Course, error) {
 	var result []course.Course
-	err := repo.db.InnerJoins("Major", repo.db.Where(&course.Major{ID: id})).Find(&result).Error
+	err := repo.db.Where("major_id = ?", id).Find(&result).Error
 
 	if err != nil {
 		return nil, err
@@ -152,7 +174,11 @@ func (repo CourseRepositoryImpl) GetAllCourseByMajor(id uuid.UUID) ([]course.Cou
 
 func (repo CourseRepositoryImpl) GetAllCourseByFaculty(id uuid.UUID) ([]course.Course, error) {
 	var result []course.Course
-	err := repo.db.InnerJoins("Faculty", repo.db.Where(&course.Faculty{ID: id})).InnerJoins("Major").Find(&result).Error
+	err := repo.db.
+		Joins("JOIN major ON major.id = course.major_id").
+		Joins("JOIN faculty ON faculty.id = major.fac_id").
+		Where("faculty.id = ?", id).
+		Find(&result).Error
 
 	if err != nil {
 		return nil, err
@@ -163,7 +189,7 @@ func (repo CourseRepositoryImpl) GetAllCourseByFaculty(id uuid.UUID) ([]course.C
 
 func (repo CourseRepositoryImpl) GetAllMajorByFaculty(id uuid.UUID) ([]course.Major, error) {
 	var result []course.Major
-	err := repo.db.InnerJoins("Faculty", repo.db.Where(&course.Faculty{ID: id})).Find(&result).Error
+	err := repo.db.Where("fac_id = ?", id).Find(&result).Error
 
 	if err != nil {
 		return nil, err
@@ -208,4 +234,4 @@ func (repo CourseRepositoryImpl) GetFacultyByAbbr(abbr string) (*course.Faculty,
 	}
 
 	return result, nil
-}
\ No newline at end of file
+}
diff --git a/repository/course/type.go b/repository/course/type.go
index 252eb470be01f16794cbbb37dc3f85fee1ecfca0..7346d0a0551bed19e126fb1922a8cb4cacacdc1d 100644
--- a/repository/course/type.go
+++ b/repository/course/type.go
@@ -25,9 +25,10 @@ type CourseRepository interface {
 	IsCourseExist(id string) (bool, error)
 	IsMajorExist(id uuid.UUID) (bool, error)
 	IsFacultyExist(id uuid.UUID) (bool, error)
+	IsUserCourseContributor(id string, email string) (bool, error)
 
 	// Internal Method Only
-	
+
 	GetMajorByAbbr(abbr string) (*course.Major, error)
 	GetFacultyByAbbr(abbr string) (*course.Faculty, error)
 }
diff --git a/repository/di.go b/repository/di.go
index 9136c031788ba4f56d8d3bfe4c46f2864b641571..b564bd5406f7d94427c5c0f80ccc518bc23fd5b2 100644
--- a/repository/di.go
+++ b/repository/di.go
@@ -2,12 +2,13 @@ package repository
 
 import (
 	"github.com/google/wire"
-	"gitlab.informatika.org/ocw/ocw-backend/repository/user"
-	"gitlab.informatika.org/ocw/ocw-backend/repository/course"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/cache"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/content"
+	"gitlab.informatika.org/ocw/ocw-backend/repository/course"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/material"
+	"gitlab.informatika.org/ocw/ocw-backend/repository/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/transaction"
+	"gitlab.informatika.org/ocw/ocw-backend/repository/user"
 )
 
 var RepositoryBasicSet = wire.NewSet(
@@ -37,6 +38,9 @@ var RepositoryBasicSet = wire.NewSet(
 	transaction.NewBuilder,
 	wire.Bind(new(transaction.Transaction), new(*transaction.TransactionRepositoryImpl)),
 	wire.Bind(new(transaction.TransactionBuilder), new(*transaction.TransactionBuilderImpl)),
+
+	quiz.New,
+	wire.Bind(new(quiz.QuizRepository), new(*quiz.QuizRepositoryImpl)),
 )
 
 var RepositorySet = wire.NewSet(
diff --git a/repository/material/content.go b/repository/material/content.go
index 0f321a1b58f824fecb3bfeb5b5ea5b26c331b434..919d17b8fa531fe88c867194c154b52a3bd710ae 100644
--- a/repository/material/content.go
+++ b/repository/material/content.go
@@ -3,17 +3,35 @@ package material
 import (
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/db"
+	"gitlab.informatika.org/ocw/ocw-backend/repository/course"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/transaction"
+	"gorm.io/gorm"
 )
 
 type MaterialContentRepositoryImpl struct {
 	builder transaction.TransactionBuilder
+	course.CourseRepository
+	MaterialRepository
+	db *gorm.DB
 }
 
 func NewMaterialContent(
 	builder transaction.TransactionBuilder,
+	course course.CourseRepository,
+	database db.Database,
+	material MaterialRepository,
 ) *MaterialContentRepositoryImpl {
-	return &MaterialContentRepositoryImpl{builder}
+	return &MaterialContentRepositoryImpl{builder, course, material, database.Connect()}
+}
+
+func (m MaterialContentRepositoryImpl) IsUserContributor(id uuid.UUID, email string) (bool, error) {
+	result := &material.Content{}
+	if err := m.db.Where("id = ?", id).Find(result).Error; err != nil {
+		return false, err
+	}
+
+	return m.MaterialRepository.IsUserContributor(result.MaterialID, email)
 }
 
 func (m MaterialContentRepositoryImpl) New(
@@ -35,7 +53,8 @@ func (m MaterialContentRepositoryImpl) NewWithTransaction(
 	materialType material.MaterialType,
 	link string) (uuid.UUID, error) {
 	contentData := material.Content{
-		MaterialId: materialId,
+		Id:         uuid.New(),
+		MaterialID: materialId,
 		Type:       materialType,
 		Link:       link,
 	}
diff --git a/repository/material/material.go b/repository/material/material.go
index a20281eab9223275befc37993d0a0a3383e9dc86..87cbd435c379d505d4be048f8d1d5e878ffba019 100644
--- a/repository/material/material.go
+++ b/repository/material/material.go
@@ -3,27 +3,48 @@ package material
 import (
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/db"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/transaction"
+	"gorm.io/gorm"
 )
 
 type MaterialRepositoryImpl struct {
 	builder transaction.TransactionBuilder
+	db      *gorm.DB
 }
 
 func NewMaterial(
 	builder transaction.TransactionBuilder,
+	db db.Database,
 ) *MaterialRepositoryImpl {
-	return &MaterialRepositoryImpl{builder}
+	return &MaterialRepositoryImpl{builder, db.Connect()}
 }
 
-func (m MaterialRepositoryImpl) New(courseId string, creatorEmail string) (uuid.UUID, error) {
-	return m.NewWithTransaction(m.builder.Build(), courseId, creatorEmail)
+func (m MaterialRepositoryImpl) Get(materialId uuid.UUID) (*material.Material, error) {
+	res := &material.Material{}
+	err := m.db.Preload("Contents").Where("id = ?", materialId).Find(res).Error
+	return res, err
 }
 
-func (m MaterialRepositoryImpl) NewWithTransaction(tx transaction.Transaction, courseId string, creatorEmail string) (uuid.UUID, error) {
+func (m MaterialRepositoryImpl) IsUserContributor(id uuid.UUID, email string) (bool, error) {
+	err := m.db.Where("creator_email = ? AND id = ?", email, id).Find(&material.Material{}).Error
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+func (m MaterialRepositoryImpl) New(courseId string, creatorEmail string, name string) (uuid.UUID, error) {
+	return m.NewWithTransaction(m.builder.Build(), courseId, creatorEmail, name)
+}
+
+func (m MaterialRepositoryImpl) NewWithTransaction(tx transaction.Transaction, courseId string, creatorEmail string, name string) (uuid.UUID, error) {
 	materialData := &material.Material{
+		ID:           uuid.New(),
 		CourseId:     courseId,
 		CreatorEmail: creatorEmail,
+		Name:         name,
 	}
 
 	err := tx.GetTransaction().Create(materialData).Error
@@ -32,7 +53,7 @@ func (m MaterialRepositoryImpl) NewWithTransaction(tx transaction.Transaction, c
 		return uuid.Nil, err
 	}
 
-	return materialData.Id, nil
+	return materialData.ID, nil
 }
 
 func (m MaterialRepositoryImpl) Delete(id uuid.UUID) error {
@@ -49,7 +70,12 @@ func (m MaterialRepositoryImpl) GetAll(courseId string) ([]material.Material, er
 
 func (m MaterialRepositoryImpl) GetAllWithTransaction(tx transaction.Transaction, courseId string) ([]material.Material, error) {
 	result := []material.Material{}
-	err := tx.GetTransaction().Joins("Contents").Where("CourseId = ?", courseId).Find(&result).Error
+	trx := tx.GetTransaction()
+	err := trx.
+		Model(&material.Material{}).
+		Preload("Contents").
+		Where("course_id = ?", courseId).
+		Find(&result).Error
 
 	return result, err
 }
diff --git a/repository/material/type.go b/repository/material/type.go
index 8343c4df1757d7f4f585efd43fe3cc18e4f325d4..4014763d006c08c2eabeb294a8f043ae023d0b17 100644
--- a/repository/material/type.go
+++ b/repository/material/type.go
@@ -7,16 +7,20 @@ import (
 )
 
 type MaterialRepository interface {
-	New(courseId string, creatorEmail string) (uuid.UUID, error)
+	New(courseId string, creatorEmail string, name string) (uuid.UUID, error)
 	Delete(id uuid.UUID) error
+	Get(materialId uuid.UUID) (*material.Material, error)
 	GetAll(courseId string) ([]material.Material, error)
 
-	NewWithTransaction(tx transaction.Transaction, courseId string, creatorEmail string) (uuid.UUID, error)
+	IsUserContributor(id uuid.UUID, email string) (bool, error)
+
+	NewWithTransaction(tx transaction.Transaction, courseId string, creatorEmail string, name string) (uuid.UUID, error)
 	DeleteWithTransaction(tx transaction.Transaction, id uuid.UUID) error
 	GetAllWithTransaction(tx transaction.Transaction, courseId string) ([]material.Material, error)
 }
 
 type MaterialContentRepository interface {
+	IsUserContributor(id uuid.UUID, email string) (bool, error)
 	New(materialId uuid.UUID, materialType material.MaterialType, link string) (uuid.UUID, error)
 	GetAll(materialId uuid.UUID) ([]material.Content, error)
 	Delete(contentId uuid.UUID) error
diff --git a/repository/quiz/impl.go b/repository/quiz/impl.go
new file mode 100644
index 0000000000000000000000000000000000000000..e51495422f1a10911dd47bf00b1764eb541446ab
--- /dev/null
+++ b/repository/quiz/impl.go
@@ -0,0 +1,97 @@
+package quiz
+
+import (
+	"errors"
+	"time"
+
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/db"
+	"gorm.io/gorm"
+)
+
+type QuizRepositoryImpl struct {
+	db *gorm.DB
+}
+
+func New(
+	db db.Database,
+) *QuizRepositoryImpl {
+	return &QuizRepositoryImpl{db.Connect()}
+}
+
+func (q *QuizRepositoryImpl) GetQuizes(courseId string) ([]quiz.Quiz, error) {
+	result := &[]quiz.Quiz{}
+	err := q.db.Where("course_id = ?", courseId).Find(result).Error
+
+	return *result, err
+}
+
+func (q *QuizRepositoryImpl) GetQuizDetail(quizId uuid.UUID) (*quiz.Quiz, error) {
+	result := &quiz.Quiz{}
+	err := q.db.Where("id = ?", quizId).First(result).Error
+
+	if errors.Is(err, gorm.ErrRecordNotFound) {
+		return nil, web.NewResponseError("Record not found", "ERR_NOT_FOUND")
+	}
+
+	return result, nil
+}
+
+func (q *QuizRepositoryImpl) UpdateScore(takeId uuid.UUID, score int) error {
+	return q.db.
+		Model(&quiz.QuizTake{}).
+		Update("score", score).
+		Update("is_finished", true).
+		Where("id = ?", takeId).Error
+}
+
+func (q *QuizRepositoryImpl) NewTake(quizId uuid.UUID, userEmail string) (uuid.UUID, error) {
+	id := uuid.New()
+	err := q.db.Create(
+		&quiz.QuizTake{
+			Id:         id,
+			Email:      userEmail,
+			StartTime:  time.Now(),
+			QuizId:     quizId,
+			IsFinished: false,
+			Score:      0,
+		},
+	).Error
+
+	return id, err
+}
+
+func (q *QuizRepositoryImpl) IsActiveTake(quizId uuid.UUID, userEmail string) (bool, error) {
+	result := struct{ cnt int }{}
+	err := q.db.
+		Select("COUNT(*) as cnt").
+		Where("quiz_id = ? AND email = ? AND is_finished = false", quizId, userEmail).
+		Find(result).
+		Error
+
+	if err != nil {
+		return false, nil
+	}
+
+	return result.cnt > 0, nil
+}
+
+func (q *QuizRepositoryImpl) GetAllTake(quizId uuid.UUID, userEmail string) ([]quiz.QuizTake, error) {
+	result := []quiz.QuizTake{}
+	err := q.db.
+		Where("quiz_id = ? AND email = ?", quizId, userEmail).
+		Find(result).Error
+
+	return result, err
+}
+
+func (q *QuizRepositoryImpl) GetLastTake(quizId uuid.UUID, userEmail string) (*quiz.QuizTake, error) {
+	result := &quiz.QuizTake{}
+	err := q.db.
+		Where("quiz_id = ? AND email = ?", quizId, userEmail).
+		Last(result).Error
+
+	return result, err
+}
diff --git a/repository/quiz/type.go b/repository/quiz/type.go
new file mode 100644
index 0000000000000000000000000000000000000000..1b4e0cbeca391ec136dfc8c696d1c058d49e55e4
--- /dev/null
+++ b/repository/quiz/type.go
@@ -0,0 +1,16 @@
+package quiz
+
+import (
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
+)
+
+type QuizRepository interface {
+	GetQuizes(courseId string) ([]quiz.Quiz, error)
+	GetQuizDetail(quizId uuid.UUID) (*quiz.Quiz, error)
+	UpdateScore(takeId uuid.UUID, score int) error
+	NewTake(quizId uuid.UUID, userEmail string) (uuid.UUID, error)
+	IsActiveTake(quizId uuid.UUID, userEmail string) (bool, error)
+	GetAllTake(quizId uuid.UUID, userEmail string) ([]quiz.QuizTake, error)
+	GetLastTake(quizId uuid.UUID, userEmail string) (*quiz.QuizTake, error)
+}
diff --git a/routes/admin/route.go b/routes/admin/route.go
index d1ff589b86faa181e6e671bf7111ab3efed0b239..d1fe8e2213ad86d7b7bdd1ecf4fcac90ab8f60a5 100644
--- a/routes/admin/route.go
+++ b/routes/admin/route.go
@@ -14,7 +14,7 @@ type AdminRoutes struct {
 
 func (adr AdminRoutes) Register(r chi.Router) {
 	r.Route("/admin", func(r chi.Router) {
-		r.Use(adr.GuardBuilder.BuildSimple(user.Admin))
+		r.Use(adr.GuardBuilder.Build(user.Admin))
 
 		r.Get("/user", adr.AdminHandler.GetAllUser)
 		r.Get("/user/{email}", adr.AdminHandler.GetUserByEmail)
diff --git a/routes/course/route.go b/routes/course/route.go
index 6fb5f6ac2019b24687bbc28d593011846bed1057..43a8305f4187ad99c9e7baadea375a59f373ad37 100644
--- a/routes/course/route.go
+++ b/routes/course/route.go
@@ -3,15 +3,19 @@ package course
 import (
 	"github.com/go-chi/chi/v5"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/course"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/material"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 )
 
 type CourseRoutes struct {
 	course.CourseHandler
+	material.MaterialHandler
+	*guard.GuardBuilder
 }
 
 func (c CourseRoutes) Register(r chi.Router) {
 	r.Route("/course", func(r chi.Router) {
-		// Get
 		r.Get("/", c.CourseHandler.GetCourses)
 		r.Get("/{id}", c.CourseHandler.GetCourse)
 		r.Get("/faculty", c.CourseHandler.GetFaculties)
@@ -21,18 +25,18 @@ func (c CourseRoutes) Register(r chi.Router) {
 		r.Get("/major", c.CourseHandler.GetMajors)
 		r.Get("/major/{id}", c.CourseHandler.GetMajor)
 		r.Get("/major/courses/{id}", c.CourseHandler.GetCoursesByMajor)
-
-		// Add
 		r.Put("/", c.CourseHandler.AddCourse)
 		r.Put("/faculty", c.CourseHandler.AddFaculty)
 		r.Put("/major", c.CourseHandler.AddMajor)
-
-		// Update
 		r.Patch("/{id}", c.CourseHandler.UpdateCourse)
 		r.Patch("/faculty/{id}", c.CourseHandler.UpdateFaculty)
 		r.Patch("/major/{id}", c.CourseHandler.UpdateMajor)
-
-		// Delete
 		r.Delete("/{id}", c.CourseHandler.DeleteCourse)
+		r.Get("/{id}/materials", c.MaterialHandler.GetMaterial)
+	})
+
+	r.Route("/course/{id}/material", func(r chi.Router) {
+		r.Use(c.Build(user.Contributor))
+		r.Post("/", c.MaterialHandler.CreateMaterial)
 	})
 }
diff --git a/routes/di.go b/routes/di.go
index a51997ed13bc22c420ab390bcd1c46de58b20bce..ddae40f95c5cde473aadc4f6d26a357c98b5f089 100644
--- a/routes/di.go
+++ b/routes/di.go
@@ -6,6 +6,8 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/routes/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/common"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/course"
+	"gitlab.informatika.org/ocw/ocw-backend/routes/material"
+	"gitlab.informatika.org/ocw/ocw-backend/routes/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/reset"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/swagger"
 )
@@ -17,6 +19,8 @@ var routesCollectionSet = wire.NewSet(
 	wire.Struct(new(admin.AdminRoutes), "*"),
 	wire.Struct(new(reset.ResetRoutes), "*"),
 	wire.Struct(new(course.CourseRoutes), "*"),
+	wire.Struct(new(material.MaterialRoutes), "*"),
+	wire.Struct(new(quiz.QuizRoutes), "*"),
 )
 
 var RoutesSet = wire.NewSet(
diff --git a/routes/material/route.go b/routes/material/route.go
new file mode 100644
index 0000000000000000000000000000000000000000..41126ecf7b9b60c1f56f9bd77208e9486db51ef0
--- /dev/null
+++ b/routes/material/route.go
@@ -0,0 +1,30 @@
+package material
+
+import (
+	"github.com/go-chi/chi/v5"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/material"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+)
+
+type MaterialRoutes struct {
+	material.MaterialHandler
+	*guard.GuardBuilder
+}
+
+func (c MaterialRoutes) Register(r chi.Router) {
+	r.Route("/material/{material-id}", func(r chi.Router) {
+		r.Get("/", c.DetailMaterial)
+
+		r.Route("/", func(r chi.Router) {
+			r.Use(c.GuardBuilder.Build(user.Contributor))
+
+			// Add
+			r.Post("/content", c.AddContent)
+
+			// Delete
+			r.Delete("/", c.DeleteMaterial)
+			r.Delete("/content/{content-id}", c.DeleteContent)
+		})
+	})
+}
diff --git a/routes/quiz/route.go b/routes/quiz/route.go
new file mode 100644
index 0000000000000000000000000000000000000000..b89269412c9add8ccc39a190a965f187a13c15b9
--- /dev/null
+++ b/routes/quiz/route.go
@@ -0,0 +1,39 @@
+package quiz
+
+import (
+	"github.com/go-chi/chi/v5"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/middleware/guard"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+)
+
+type QuizRoutes struct {
+	quiz.QuizHandler
+	*guard.GuardBuilder
+}
+
+func (q QuizRoutes) Register(r chi.Router) {
+	r.Get("/course/{id}/quiz", q.QuizHandler.GetAllQuizes)
+	r.Get("/quiz/{id}", q.QuizHandler.GetQuizDetail)
+
+	guard := q.GuardBuilder.Build(
+		user.Student,
+		user.Contributor,
+		user.Admin,
+	)
+
+	r.Route("/quiz/{id}/take", func(r chi.Router) {
+		r.Use(guard)
+		r.Post("/", q.QuizHandler.TakeQuiz)
+	})
+
+	r.Route("/quiz/{id}/finish", func(r chi.Router) {
+		r.Use(guard)
+		r.Post("/", q.QuizHandler.FinishQuiz)
+	})
+
+	r.Route("/quiz/{id}/solution", func(r chi.Router) {
+		r.Use(guard)
+		r.Get("/", q.QuizHandler.GetQuizSolution)
+	})
+}
diff --git a/routes/routes.go b/routes/routes.go
index da4d5b4a4f8efd320ee9b8151f0b8ae4cf4a3757..096f4d5005e2bfe01f82bfe53552edc99b1d0258 100644
--- a/routes/routes.go
+++ b/routes/routes.go
@@ -5,6 +5,8 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/routes/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/common"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/course"
+	"gitlab.informatika.org/ocw/ocw-backend/routes/material"
+	"gitlab.informatika.org/ocw/ocw-backend/routes/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/reset"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/swagger"
 
@@ -18,7 +20,9 @@ type AppRouter struct {
 	common.CommonRoutes
 	auth.AuthRoutes
 	reset.ResetRoutes
+	quiz.QuizRoutes
 	course.CourseRoutes
+	material.MaterialRoutes
 
 	// Utility
 	Logger logger.Logger
diff --git a/service/auth/login.go b/service/auth/login.go
index 33d52237aec5b52a8a56796b5c410f54e0fe6189..8d4b77df57c9a7689688c1d7d9c85ad20d279e3c 100644
--- a/service/auth/login.go
+++ b/service/auth/login.go
@@ -31,15 +31,16 @@ func (auth AuthServiceImpl) Login(payload login.LoginRequestPayload) (*login.Log
 		return nil, web.NewResponseError("username and password combination not found", web.InvalidLogin)
 	}
 
-	if !user.IsActivated {
-		return nil, web.NewResponseError("user is not activated yet", web.InactiveUser)
-	}
+	// if !user.IsActivated {
+	// 	return nil, web.NewResponseError("user is not activated yet", web.InactiveUser)
+	// }
 
 	refreshClaim := tokenModel.UserClaim{
-		Name:  user.Name,
-		Email: user.Email,
-		Role:  user.Role,
-		Type:  tokenModel.Refresh,
+		Name:       user.Name,
+		Email:      user.Email,
+		Role:       user.Role,
+		Type:       tokenModel.Refresh,
+		IsVerified: user.IsActivated,
 		RegisteredClaims: jwt.RegisteredClaims{
 			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(auth.TokenRefreshExpired) * time.Millisecond)),
 			Issuer:    auth.TokenIssuer,
@@ -48,10 +49,11 @@ func (auth AuthServiceImpl) Login(payload login.LoginRequestPayload) (*login.Log
 	}
 
 	accessClaim := tokenModel.UserClaim{
-		Name:  user.Name,
-		Email: user.Email,
-		Role:  user.Role,
-		Type:  tokenModel.Access,
+		Name:       user.Name,
+		Email:      user.Email,
+		Role:       user.Role,
+		Type:       tokenModel.Access,
+		IsVerified: user.IsActivated,
 		RegisteredClaims: jwt.RegisteredClaims{
 			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(auth.TokenAccessExpired) * time.Millisecond)),
 			Issuer:    auth.TokenIssuer,
diff --git a/service/course/add.go b/service/course/add.go
index 531d0ec4410bfa1fc3b87de40826ed94d93f3c91..a94a59b6e56c8d465adf46559d3877dff50b34e0 100644
--- a/service/course/add.go
+++ b/service/course/add.go
@@ -3,17 +3,18 @@ package course
 import (
 	"errors"
 
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
+	"github.com/google/uuid"
+	domCourse "gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
-	cadd "gitlab.informatika.org/ocw/ocw-backend/model/web/course/add"
-	fadd "gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty/add"
-	madd "gitlab.informatika.org/ocw/ocw-backend/model/web/course/major/add"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major"
 	"gorm.io/gorm"
 )
 
-func (c CourseServiceImpl) AddCourse(payload cadd.AddCourseRequestPayload) error {
+func (c CourseServiceImpl) AddCourse(payload course.AddCourseRequestPayload) error {
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.AddCourseToken, token.Access)
 
@@ -53,7 +54,7 @@ func (c CourseServiceImpl) AddCourse(payload cadd.AddCourseRequestPayload) error
 		return web.NewResponseError("Course ID Already Exists", web.IDExists)
 	}
 
-	err = c.CourseRepository.AddCourse(course.Course{
+	err = c.CourseRepository.AddCourse(domCourse.Course{
 		ID:           payload.ID,
 		Name:         payload.Name,
 		Major_id:     payload.MajorID,
@@ -70,7 +71,7 @@ func (c CourseServiceImpl) AddCourse(payload cadd.AddCourseRequestPayload) error
 	return nil
 }
 
-func (c CourseServiceImpl) AddMajor(payload madd.AddMajorRequestPayload) error {
+func (c CourseServiceImpl) AddMajor(payload major.AddMajorRequestPayload) error {
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.AddMajorToken, token.Access)
 
@@ -99,7 +100,14 @@ func (c CourseServiceImpl) AddMajor(payload madd.AddMajorRequestPayload) error {
 		payload.FacultyID = faculty.ID
 	}
 
-	err = c.CourseRepository.AddMajor(course.Major{
+	id, err := uuid.NewUUID()
+
+	if err != nil {
+		return err
+	}
+
+	err = c.CourseRepository.AddMajor(domCourse.Major{
+		ID:           id,
 		Name:         payload.Name,
 		Fac_id:       payload.FacultyID,
 		Abbreviation: payload.Abbreviation,
@@ -113,7 +121,7 @@ func (c CourseServiceImpl) AddMajor(payload madd.AddMajorRequestPayload) error {
 	return nil
 }
 
-func (c CourseServiceImpl) AddFaculty(payload fadd.AddFacultyRequestPayload) error {
+func (c CourseServiceImpl) AddFaculty(payload faculty.AddFacultyRequestPayload) error {
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.AddFacultyToken, token.Access)
 
@@ -124,10 +132,17 @@ func (c CourseServiceImpl) AddFaculty(payload fadd.AddFacultyRequestPayload) err
 
 	// Unauthorized Role
 	if claim.Role != user.Admin {
-		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+		return web.NewResponseError("user is not allowed to access this resources", web.UnauthorizedAccess)
 	}
-	
-	err = c.CourseRepository.AddFaculty(course.Faculty{
+
+	id, err := uuid.NewUUID()
+
+	if err != nil {
+		return err
+	}
+
+	err = c.CourseRepository.AddFaculty(domCourse.Faculty{
+		ID:           id,
 		Name:         payload.Name,
 		Abbreviation: payload.Abbreviation,
 	})
diff --git a/service/course/delete.go b/service/course/delete.go
index a8bda5bc6baf2331980b2b7056282b34b2b272d8..92b73e22d8bd6f3f9380cd421550108d67b280d0 100644
--- a/service/course/delete.go
+++ b/service/course/delete.go
@@ -4,12 +4,10 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/delete"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 )
 
-// TODO: Authorization Checks
-
-func (c CourseServiceImpl) DeleteCourse(payload delete.DeleteByStringRequestPayload) error {
+func (c CourseServiceImpl) DeleteCourse(payload course.DeleteByStringRequestPayload) error {
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.DeleteCourseToken, token.Access)
 
diff --git a/service/course/get.go b/service/course/get.go
index 001217d32d6604eae10f6150b1519935e2ffbe7a..3745ea3d47fa2182e3968050fe5a0011c5edf98b 100644
--- a/service/course/get.go
+++ b/service/course/get.go
@@ -3,13 +3,13 @@ package course
 import (
 	"errors"
 
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
+	domCourse "gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 	"gorm.io/gorm"
 )
 
-func (c CourseServiceImpl) GetCourse(payload get.GetByStringRequestPayload) (*course.Course, error) {
+func (c CourseServiceImpl) GetCourse(payload course.GetByStringRequestPayload) (*domCourse.Course, error) {
 	packet, err := c.CourseRepository.GetCourse(payload.ID)
 
 	if err != nil {
@@ -23,7 +23,7 @@ func (c CourseServiceImpl) GetCourse(payload get.GetByStringRequestPayload) (*co
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetMajor(payload get.GetByUUIDRequestPayload) (*course.Major, error) {
+func (c CourseServiceImpl) GetMajor(payload course.GetByUUIDRequestPayload) (*domCourse.Major, error) {
 	packet, err := c.CourseRepository.GetMajor(payload.ID)
 
 	if err != nil {
@@ -37,7 +37,7 @@ func (c CourseServiceImpl) GetMajor(payload get.GetByUUIDRequestPayload) (*cours
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetFaculty(payload get.GetByUUIDRequestPayload) (*course.Faculty, error) {
+func (c CourseServiceImpl) GetFaculty(payload course.GetByUUIDRequestPayload) (*domCourse.Faculty, error) {
 	packet, err := c.CourseRepository.GetFaculty(payload.ID)
 
 	if err != nil {
@@ -51,7 +51,7 @@ func (c CourseServiceImpl) GetFaculty(payload get.GetByUUIDRequestPayload) (*cou
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetAllCourse() ([]course.Course, error) {
+func (c CourseServiceImpl) GetAllCourse() ([]domCourse.Course, error) {
 	packet, err := c.CourseRepository.GetAllCourse()
 
 	if err != nil {
@@ -65,7 +65,7 @@ func (c CourseServiceImpl) GetAllCourse() ([]course.Course, error) {
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetAllMajor() ([]course.Major, error) {
+func (c CourseServiceImpl) GetAllMajor() ([]domCourse.Major, error) {
 	packet, err := c.CourseRepository.GetAllMajor()
 
 	if err != nil {
@@ -79,7 +79,7 @@ func (c CourseServiceImpl) GetAllMajor() ([]course.Major, error) {
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetAllFaculty() ([]course.Faculty, error) {
+func (c CourseServiceImpl) GetAllFaculty() ([]domCourse.Faculty, error) {
 	packet, err := c.CourseRepository.GetAllFaculty()
 
 	if err != nil {
@@ -94,7 +94,7 @@ func (c CourseServiceImpl) GetAllFaculty() ([]course.Faculty, error) {
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetAllCourseByMajor(payload get.GetByUUIDRequestPayload) ([]course.Course, error) {
+func (c CourseServiceImpl) GetAllCourseByMajor(payload course.GetByUUIDRequestPayload) ([]domCourse.Course, error) {
 	packet, err := c.CourseRepository.GetAllCourseByMajor(payload.ID)
 
 	if err != nil {
@@ -108,7 +108,7 @@ func (c CourseServiceImpl) GetAllCourseByMajor(payload get.GetByUUIDRequestPaylo
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetAllCourseByFaculty(payload get.GetByUUIDRequestPayload) ([]course.Course, error) {
+func (c CourseServiceImpl) GetAllCourseByFaculty(payload course.GetByUUIDRequestPayload) ([]domCourse.Course, error) {
 	packet, err := c.CourseRepository.GetAllCourseByFaculty(payload.ID)
 
 	if err != nil {
@@ -122,7 +122,7 @@ func (c CourseServiceImpl) GetAllCourseByFaculty(payload get.GetByUUIDRequestPay
 	return packet, nil
 }
 
-func (c CourseServiceImpl) GetAllMajorByFaculty(payload get.GetByUUIDRequestPayload) ([]course.Major, error) {
+func (c CourseServiceImpl) GetAllMajorByFaculty(payload course.GetByUUIDRequestPayload) ([]domCourse.Major, error) {
 	packet, err := c.CourseRepository.GetAllMajorByFaculty(payload.ID)
 
 	if err != nil {
diff --git a/service/course/type.go b/service/course/type.go
index 33f45503ef7a54876001a7d15f15464c9a6cdfe4..0fbc7ecc14c129a318fe93f77d37f3299f0e2f4c 100644
--- a/service/course/type.go
+++ b/service/course/type.go
@@ -1,33 +1,28 @@
 package course
 
 import (
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/get"
-	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/delete"
-	cadd "gitlab.informatika.org/ocw/ocw-backend/model/web/course/add"
-	madd "gitlab.informatika.org/ocw/ocw-backend/model/web/course/major/add"
-	fadd "gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty/add"
-	cupdate "gitlab.informatika.org/ocw/ocw-backend/model/web/course/update"
-	mupdate "gitlab.informatika.org/ocw/ocw-backend/model/web/course/major/update"
-	fupdate "gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty/update"
+	domCourse "gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty"
 
 )
 
 type CourseService interface {
-	AddCourse(payload cadd.AddCourseRequestPayload) error
-	AddMajor(payload madd.AddMajorRequestPayload) error
-	AddFaculty(payload fadd.AddFacultyRequestPayload) error
-	GetCourse(payload get.GetByStringRequestPayload) (*course.Course, error)
-	GetMajor(payload get.GetByUUIDRequestPayload) (*course.Major, error)
-	GetFaculty(payload get.GetByUUIDRequestPayload) (*course.Faculty, error)
-	GetAllCourse() ([]course.Course, error)
-	GetAllMajor() ([]course.Major, error)
-	GetAllFaculty() ([]course.Faculty, error)
-	GetAllCourseByMajor(payload get.GetByUUIDRequestPayload) ([]course.Course, error)
-	GetAllCourseByFaculty(payload get.GetByUUIDRequestPayload) ([]course.Course, error)
-	GetAllMajorByFaculty(payload get.GetByUUIDRequestPayload) ([]course.Major, error)
-	UpdateCourse(payload cupdate.UpdateCourseRequestPayload) error
-	UpdateMajor(payload mupdate.UpdateMajorRequestPayload) error
-	UpdateFaculty(payload fupdate.UpdateFacultyRequestPayload) error
-	DeleteCourse(payload delete.DeleteByStringRequestPayload) error
+	AddCourse(payload course.AddCourseRequestPayload) error
+	AddMajor(payload major.AddMajorRequestPayload) error
+	AddFaculty(payload faculty.AddFacultyRequestPayload) error
+	GetCourse(payload course.GetByStringRequestPayload) (*domCourse.Course, error)
+	GetMajor(payload course.GetByUUIDRequestPayload) (*domCourse.Major, error)
+	GetFaculty(payload course.GetByUUIDRequestPayload) (*domCourse.Faculty, error)
+	GetAllCourse() ([]domCourse.Course, error)
+	GetAllMajor() ([]domCourse.Major, error)
+	GetAllFaculty() ([]domCourse.Faculty, error)
+	GetAllCourseByMajor(payload course.GetByUUIDRequestPayload) ([]domCourse.Course, error)
+	GetAllCourseByFaculty(payload course.GetByUUIDRequestPayload) ([]domCourse.Course, error)
+	GetAllMajorByFaculty(payload course.GetByUUIDRequestPayload) ([]domCourse.Major, error)
+	UpdateCourse(payload course.UpdateCourseRequestPayload) error
+	UpdateMajor(payload major.UpdateMajorRequestPayload) error
+	UpdateFaculty(payload faculty.UpdateFacultyRequestPayload) error
+	DeleteCourse(payload course.DeleteByStringRequestPayload) error
 }
diff --git a/service/course/update.go b/service/course/update.go
index a08d0b3573c456651ab7287c4e9c9f160285edd3..76df6c292d130c3595bbd85a1d0061c1a20ff553 100644
--- a/service/course/update.go
+++ b/service/course/update.go
@@ -3,19 +3,19 @@ package course
 import (
 	"errors"
 
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
+	domCourse "gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
-	fupdate "gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty/update"
-	mupdate "gitlab.informatika.org/ocw/ocw-backend/model/web/course/major/update"
-	cupdate "gitlab.informatika.org/ocw/ocw-backend/model/web/course/update"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/faculty"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course/major"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/course"
 	"gorm.io/gorm"
 )
 
 // TODO: Authorization Checks
 
-func (c CourseServiceImpl) UpdateCourse(payload cupdate.UpdateCourseRequestPayload) error {
+func (c CourseServiceImpl) UpdateCourse(payload course.UpdateCourseRequestPayload) error {
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.UpdateCourseToken, token.Access)
 
@@ -44,7 +44,7 @@ func (c CourseServiceImpl) UpdateCourse(payload cupdate.UpdateCourseRequestPaylo
 		payload.MajorID = major.ID
 	}
 
-	err = c.CourseRepository.UpdateCourse(course.Course{
+	err = c.CourseRepository.UpdateCourse(domCourse.Course{
 		ID: payload.ID,
 		Name: payload.Name,
 		Major_id: payload.MajorID,
@@ -65,7 +65,7 @@ func (c CourseServiceImpl) UpdateCourse(payload cupdate.UpdateCourseRequestPaylo
 	return nil
 }
 
-func (c CourseServiceImpl) UpdateMajor(payload mupdate.UpdateMajorRequestPayload) error {
+func (c CourseServiceImpl) UpdateMajor(payload major.UpdateMajorRequestPayload) error {
 	
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.UpdateMajorToken, token.Access)
@@ -95,7 +95,7 @@ func (c CourseServiceImpl) UpdateMajor(payload mupdate.UpdateMajorRequestPayload
 		payload.FacultyID = faculty.ID
 	}
 	
-	err = c.CourseRepository.UpdateMajor(course.Major{
+	err = c.CourseRepository.UpdateMajor(domCourse.Major{
 		ID: payload.ID,
 		Name: payload.Name,
 		Fac_id: payload.FacultyID,
@@ -113,7 +113,7 @@ func (c CourseServiceImpl) UpdateMajor(payload mupdate.UpdateMajorRequestPayload
 	return nil
 }
 
-func (c CourseServiceImpl) UpdateFaculty(payload fupdate.UpdateFacultyRequestPayload) error {
+func (c CourseServiceImpl) UpdateFaculty(payload faculty.UpdateFacultyRequestPayload) error {
 	// Validate Role
 	claim, err := c.TokenUtil.Validate(payload.UpdateFacultyToken, token.Access)
 
@@ -127,7 +127,7 @@ func (c CourseServiceImpl) UpdateFaculty(payload fupdate.UpdateFacultyRequestPay
 		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
 	}
 	
-	err = c.CourseRepository.UpdateFaculty(course.Faculty{
+	err = c.CourseRepository.UpdateFaculty(domCourse.Faculty{
 		ID: payload.ID,
 		Name: payload.Name,
 		Abbreviation: payload.Abbreviation,
diff --git a/service/di.go b/service/di.go
index 6cdb051667f746ccdc3ff0244fd29bdf19f69561..3a133f5fc0ccdaba5c7260c52fa6a068306cf8a2 100644
--- a/service/di.go
+++ b/service/di.go
@@ -5,13 +5,14 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/service/admin"
 	"gitlab.informatika.org/ocw/ocw-backend/service/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/service/common"
+	"gitlab.informatika.org/ocw/ocw-backend/service/course"
 	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
 	"gitlab.informatika.org/ocw/ocw-backend/service/logger/hooks"
 	"gitlab.informatika.org/ocw/ocw-backend/service/material"
+	"gitlab.informatika.org/ocw/ocw-backend/service/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/service/reporter"
 	"gitlab.informatika.org/ocw/ocw-backend/service/reset"
 	"gitlab.informatika.org/ocw/ocw-backend/service/verification"
-	"gitlab.informatika.org/ocw/ocw-backend/service/course"
 )
 
 var ServiceTestSet = wire.NewSet(
@@ -64,6 +65,12 @@ var ServiceTestSet = wire.NewSet(
 		wire.Bind(new(material.MaterialContentService), new(*material.MaterialContentServiceImpl)),
 		wire.Bind(new(material.MaterialService), new(*material.MaterialServiceImpl)),
 	),
+
+	// Quiz service
+	wire.NewSet(
+		wire.Struct(new(quiz.QuizServiceImpl), "*"),
+		wire.Bind(new(quiz.QuizService), new(*quiz.QuizServiceImpl)),
+	),
 )
 
 var ServiceSet = wire.NewSet(
diff --git a/service/material/content.go b/service/material/content.go
index 5bf0b5638d0e44d4857932fc3d782a6d0a36c45b..e54a1a0ac1eca2445939847036620231d885d801 100644
--- a/service/material/content.go
+++ b/service/material/content.go
@@ -1,47 +1,98 @@
 package material
 
 import (
+	"context"
+	"errors"
+	"fmt"
+	"strings"
+
 	"github.com/google/uuid"
 	materialDomain "gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/storage"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/material"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/transaction"
+	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/env"
+	"gorm.io/gorm"
 )
 
 type MaterialContentServiceImpl struct {
 	transaction.TransactionBuilder
 	material.MaterialContentRepository
+	material.MaterialRepository
+	storage.Storage
+	logger.Logger
+	*env.Environment
+}
+
+func (m MaterialContentServiceImpl) isMaterialContributor(materialId uuid.UUID, email string) error {
+	_, err := m.MaterialRepository.IsUserContributor(materialId, email)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return web.NewResponseError("materials and user combination not found", "NOT_OWNER")
+		}
+
+		return err
+	}
+
+	return nil
 }
 
-func (m MaterialContentServiceImpl) AddContent(materialId uuid.UUID, user user.User, contents []materialDomain.Content) error {
+func (m MaterialContentServiceImpl) AddContent(materialId uuid.UUID, user string, content materialDomain.Content) (string, error) {
+	// TODO : Check user aman ga nambah konten
+	if err := m.isMaterialContributor(materialId, user); err != nil {
+		return "", err
+	}
+
 	isSuccess := false
 	tx := m.Build()
 
 	tx.Begin()
 	defer tx.Auto(&isSuccess)
 
-	// TODO : Check user aman ga nambah konten
+	if content.Type == materialDomain.Handout {
+		path := fmt.Sprintf("%s/%s.pdf", m.BucketMaterialBasePath, strings.ReplaceAll(uuid.New().String(), "-", ""))
+		uploadLink, err := m.Storage.CreatePutSignedLink(context.Background(), path)
 
-	for _, content := range contents {
-		_, err := m.MaterialContentRepository.NewWithTransaction(tx, materialId, content.Type, content.Link)
+		if err != nil {
+			m.Logger.Error("Some error happened when generate link")
+			m.Logger.Error(err.Error())
+			return "", err
+		}
+
+		_, err = m.MaterialContentRepository.NewWithTransaction(tx, materialId, content.Type, path)
 
 		if err != nil {
-			return err
+			return "", err
 		}
-	}
 
-	isSuccess = true
-	return nil
+		isSuccess = true
+
+		return uploadLink, nil
+	} else {
+		if content.Link == "" {
+			return "", web.NewResponseError("content is empty", "ERR_CONTENT_LINK_EMPTY")
+		}
+
+		_, err := m.MaterialContentRepository.NewWithTransaction(tx, materialId, content.Type, content.Link)
+
+		if err == nil {
+			isSuccess = true
+		}
+
+		return "", err
+	}
 }
 
 func (m MaterialContentServiceImpl) DeleteContent(
-	materialId uuid.UUID, user user.User, contentId uuid.UUID,
+	materialId uuid.UUID, user string, contentId uuid.UUID,
 ) error {
 	// TODO: check user aman ga delete konten
-	return m.MaterialContentRepository.Delete(contentId)
-}
+	if err := m.isMaterialContributor(materialId, user); err != nil {
+		return err
+	}
 
-func (m MaterialContentServiceImpl) UpdateContentLink(materialId uuid.UUID, user user.User, contentId uuid.UUID, link string) error {
-	// TODO: Check user aman ga update link
-	return m.MaterialContentRepository.UpdateLink(contentId, link)
+	return m.MaterialContentRepository.Delete(contentId)
 }
diff --git a/service/material/impl.go b/service/material/impl.go
index 1e7c95ff7014ec943f19982a4b95892baa52e2bf..c50b67586123fcf70acf3c2c0a4ee7f42b53034c 100644
--- a/service/material/impl.go
+++ b/service/material/impl.go
@@ -1,11 +1,14 @@
 package material
 
 import (
+	"errors"
+
 	"github.com/google/uuid"
-	materialRepo "gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+	materialDomain "gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/material"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/transaction"
+	"gorm.io/gorm"
 )
 
 type MaterialServiceImpl struct {
@@ -14,32 +17,49 @@ type MaterialServiceImpl struct {
 	material.MaterialRepository
 }
 
-func (m MaterialServiceImpl) Create(courseId string, user user.User, contents []materialRepo.Content) (uuid.UUID, error) {
+func (m MaterialServiceImpl) Get(courseId string) ([]materialDomain.Material, error) {
+	materials, err := m.MaterialRepository.GetAll(courseId)
+	return materials, err
+}
+
+func (m MaterialServiceImpl) GetById(materialId uuid.UUID) (*materialDomain.Material, error) {
+	material, err := m.MaterialRepository.Get(materialId)
+
+	if errors.Is(err, gorm.ErrRecordNotFound) {
+		return nil, web.NewResponseErrorFromError(err, "ID_NOT_FOUND")
+	}
+
+	return material, err
+}
+
+func (m MaterialServiceImpl) Create(courseId string, email string, name string) (uuid.UUID, error) {
 	isSuccess := false
 	tx := m.TransactionBuilder.Build()
 
 	tx.Begin()
 	defer tx.Auto(&isSuccess)
 
-	id, err := m.MaterialRepository.NewWithTransaction(tx, courseId, user.Email)
+	id, err := m.MaterialRepository.NewWithTransaction(tx, courseId, email, name)
 
 	if err != nil {
 		return uuid.Nil, err
 	}
 
-	for _, content := range contents {
-		_, err = m.MaterialContentRepository.NewWithTransaction(tx, id, content.Type, content.Link)
-
-		if err != nil {
-			return uuid.Nil, err
-		}
-	}
-
 	isSuccess = true
 	return id, err
 }
 
-func (m MaterialServiceImpl) Delete(materialId uuid.UUID, user user.User) error {
+func (m MaterialServiceImpl) Delete(materialId uuid.UUID, email string) error {
 	// TODO: Pengecekan user apakah kontributor course bukan
+	_, err := m.MaterialRepository.IsUserContributor(materialId, email)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return web.NewResponseError("User is not the owner of material", "NOT_OWNER")
+		}
+
+		return err
+	}
+
 	return m.MaterialRepository.Delete(materialId)
 }
diff --git a/service/material/type.go b/service/material/type.go
index 66fe99b49e176c375812c020389aaf855fb3d7bb..ca617ce6fdce82217b439b2f4b1f0a0b58d3545d 100644
--- a/service/material/type.go
+++ b/service/material/type.go
@@ -3,16 +3,16 @@ package material
 import (
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
-	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 )
 
 type MaterialService interface {
-	Create(courseId string, user user.User, contents []material.Content) (uuid.UUID, error)
-	Delete(materialId uuid.UUID, user user.User) error
+	Create(courseId string, email string, name string) (uuid.UUID, error)
+	Delete(materialId uuid.UUID, email string) error
+	Get(courseId string) ([]material.Material, error)
+	GetById(materialId uuid.UUID) (*material.Material, error)
 }
 
 type MaterialContentService interface {
-	AddContent(materialId uuid.UUID, user user.User, contents []material.Content) error
-	DeleteContent(materialId uuid.UUID, user user.User, contentId uuid.UUID) error
-	UpdateContentLink(materialId uuid.UUID, user user.User, contentId uuid.UUID, link string) error
+	AddContent(materialId uuid.UUID, email string, content material.Content) (string, error)
+	DeleteContent(materialId uuid.UUID, email string, contentId uuid.UUID) error
 }
diff --git a/service/quiz/impl.go b/service/quiz/impl.go
new file mode 100644
index 0000000000000000000000000000000000000000..3898cd448978c6604f71f68e7561077c9c396a00
--- /dev/null
+++ b/service/quiz/impl.go
@@ -0,0 +1,172 @@
+package quiz
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/storage"
+	quizRepo "gitlab.informatika.org/ocw/ocw-backend/repository/quiz"
+)
+
+type QuizServiceImpl struct {
+	quizRepo.QuizRepository
+	storage.Storage
+}
+
+func (q QuizServiceImpl) ListAllQuiz(courseId string) ([]quiz.Quiz, error) {
+	return q.QuizRepository.GetQuizes(courseId)
+}
+
+func (q QuizServiceImpl) GetQuizDetail(quizId uuid.UUID) (*quiz.Quiz, error) {
+	return q.QuizRepository.GetQuizDetail(quizId)
+}
+
+func (q QuizServiceImpl) getQuizDetail(ctx context.Context, quizId uuid.UUID) (*quiz.QuizDetail, error) {
+	detail, err := q.QuizRepository.GetQuizDetail(quizId)
+
+	if err != nil {
+		return nil, err
+	}
+
+	payload, err := q.Storage.Get(ctx, detail.QuizPath)
+
+	if err != nil {
+		return nil, err
+	}
+
+	result := &quiz.QuizDetail{}
+
+	decoder := json.NewDecoder(bytes.NewReader(payload))
+	err = decoder.Decode(result)
+
+	return result, err
+}
+
+func (q QuizServiceImpl) DoTakeQuiz(ctx context.Context, quizId uuid.UUID, email string) (*quiz.QuizDetail, error) {
+	result, err := q.getQuizDetail(ctx, quizId)
+
+	if err != nil {
+		return nil, err
+	}
+
+	taken, err := q.IsActiveTake(quizId, email)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if !taken {
+		_, err = q.NewTake(quizId, email)
+
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	for i := range result.Problems {
+		for j := range result.Problems[i].Answer {
+			result.Problems[i].Answer[j].IsSolution = nil
+		}
+	}
+
+	return result, nil
+}
+
+func (q QuizServiceImpl) GetSolutionQuiz(ctx context.Context, quizId uuid.UUID, email string) (*quiz.QuizDetail, error) {
+	result, err := q.getQuizDetail(ctx, quizId)
+
+	if err != nil {
+		return nil, err
+	}
+
+	_, err = q.GetLastTake(quizId, email)
+
+	if err != nil {
+		return nil, err
+	}
+
+	taken, err := q.IsActiveTake(quizId, email)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if taken {
+		return nil, web.NewResponseError("user is not allow to access this data", "ERR_NOT_ALLOWED")
+	}
+
+	return result, nil
+}
+
+func (q QuizServiceImpl) checkAnswer(detail *quiz.QuizDetail, studentAnswer []quiz.Response) float64 {
+	answerDict := map[uuid.UUID][]uuid.UUID{}
+	totalProblem := len(detail.Problems)
+
+	for _, problem := range detail.Problems {
+		correctAnswerId := []uuid.UUID{}
+		for _, answer := range problem.Answer {
+			if *answer.IsSolution {
+				correctAnswerId = append(correctAnswerId, answer.Id)
+			}
+		}
+
+		answerDict[problem.Id] = correctAnswerId
+	}
+
+	correctAnswer := 0
+	for _, responseItem := range studentAnswer {
+		numCorrect := 0
+
+		for _, correctId := range answerDict[responseItem.ProblemId] {
+			if responseItem.AnswerId == correctId {
+				numCorrect++
+			}
+		}
+
+		if numCorrect == len(answerDict[responseItem.ProblemId]) {
+			correctAnswer++
+		}
+	}
+
+	return float64(correctAnswer) / float64(totalProblem) * 100
+}
+
+func (q QuizServiceImpl) DoFinishQuiz(ctx context.Context, quizId uuid.UUID, email string, studentAnswer []quiz.Response) (*quiz.QuizTake, error) {
+	taken, err := q.IsActiveTake(quizId, email)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if !taken {
+		return nil, web.NewResponseError("user not yet do take the quiz", "NOT_TAKEN_QUIZ_YET")
+	}
+
+	result, err := q.getQuizDetail(ctx, quizId)
+
+	if err != nil {
+		return nil, err
+	}
+
+	score := q.checkAnswer(result, studentAnswer)
+
+	data, err := q.QuizRepository.GetLastTake(quizId, email)
+	data.IsFinished = true
+	data.Score = int(score)
+
+	if err != nil {
+		return nil, err
+	}
+
+	err = q.QuizRepository.UpdateScore(data.Id, int(score))
+
+	if err != nil {
+		return nil, err
+	}
+
+	return data, nil
+}
diff --git a/service/quiz/type.go b/service/quiz/type.go
new file mode 100644
index 0000000000000000000000000000000000000000..7c97e4965500fb25f75c19a4117c536559fcf9a8
--- /dev/null
+++ b/service/quiz/type.go
@@ -0,0 +1,17 @@
+package quiz
+
+import (
+	"context"
+
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
+)
+
+type QuizService interface {
+	ListAllQuiz(courseId string) ([]quiz.Quiz, error)
+	GetQuizDetail(quizId uuid.UUID) (*quiz.Quiz, error)
+
+	DoTakeQuiz(ctx context.Context, quizId uuid.UUID, email string) (*quiz.QuizDetail, error)
+	DoFinishQuiz(ctx context.Context, quizId uuid.UUID, email string, studentAnswer []quiz.Response) (*quiz.QuizTake, error)
+	GetSolutionQuiz(ctx context.Context, quizId uuid.UUID, email string) (*quiz.QuizDetail, error)
+}
diff --git a/service/reset/request.go b/service/reset/request.go
index f3d645f4a08c7f809a117614acde439cca870a08..746fc55ea1365108ad29b6a74ce45d40d3214ec8 100644
--- a/service/reset/request.go
+++ b/service/reset/request.go
@@ -41,6 +41,8 @@ func (rs ResetServiceImpl) Request(payload request.RequestRequestPayload) error
 		Email: user.Email,
 		Role:  user.Role,
 		Type:  tokenModel.Access,
+		IsVerified: user.IsActivated,
+
 		RegisteredClaims: jwt.RegisteredClaims{
 			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(rs.TokenAccessExpired*6) * time.Millisecond)),
 			Issuer:    rs.TokenIssuer,
diff --git a/utils/env/env.go b/utils/env/env.go
index f53df6088f224fa4822983591509d93e7f4e93c4..ff09c00b0ff32c969ddd850d791ca8e35ad8fc9d 100644
--- a/utils/env/env.go
+++ b/utils/env/env.go
@@ -62,7 +62,9 @@ type Environment struct {
 	BucketSignedPutDuration int64 `env:"BUCKET_SIGNED_PUT_DURATION_S" envDefault:"36000"`
 	BucketSignedGetDuration int64 `env:"BUCKET_SIGNED_GET_DURATION_S" envDefault:"1800"`
 
-	BucketMaterialBasePath string `env:"BUCKET_MATERIAL_BASE_PATH" envDefault:"materials/"`
+	BucketMaterialBasePath string `env:"BUCKET_MATERIAL_BASE_PATH" envDefault:"materials"`
+
+	UseBucket bool `env:"USE_BUCKET" envDefault:"true"`
 }
 
 func New() (*Environment, error) {