first commit
This commit is contained in:
122
internal/controllers/auth.go
Normal file
122
internal/controllers/auth.go
Normal file
@ -0,0 +1,122 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AuthController interface {
|
||||
Register(*gin.Context)
|
||||
Login(*gin.Context)
|
||||
}
|
||||
|
||||
type authController struct {
|
||||
service services.AuthService
|
||||
tokenService services.TokenService
|
||||
}
|
||||
|
||||
func NewAuthController(service services.AuthService, tokenService services.TokenService) AuthController {
|
||||
return &authController{
|
||||
service: service,
|
||||
tokenService: tokenService,
|
||||
}
|
||||
}
|
||||
|
||||
// Register
|
||||
//
|
||||
// @Summary 회원가입
|
||||
// @Description 회원가입
|
||||
// @Tags 회원가입
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Param registerBody body models.RegisterRequest true "Register Body"
|
||||
//
|
||||
// @Success 200 {object} models.RegisterResponse
|
||||
// @Router /auth/register [post]
|
||||
func (controller *authController) Register(c *gin.Context) {
|
||||
var params models.RegisterRequest
|
||||
if c.BindJSON(¶ms) != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
|
||||
return
|
||||
}
|
||||
|
||||
user, err := controller.service.Register(¶ms)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
token, err := controller.tokenService.Create(user.ID, user.UserRole)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"user": user, "token": token.Token, "refresh_token": token.RefreshToken})
|
||||
}
|
||||
|
||||
// Login 사용자 로그인
|
||||
//
|
||||
// @Summary 사용자 로그인 로그인
|
||||
// @Description 사용자가 로그인합니다.
|
||||
// @Tags 로그인
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Param loginBody body models.LoginRequest true "Login Body"
|
||||
//
|
||||
// @Success 200 {object} models.LoginResponse
|
||||
// @Router /auth/login [post]
|
||||
func (controller *authController) Login(c *gin.Context) {
|
||||
var request models.LoginRequest
|
||||
if err := c.BindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
user, err := controller.service.Login(&request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
token, err := controller.tokenService.Create(user.ID, user.UserRole)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"user": user,
|
||||
"token": token.Token,
|
||||
"refresh_token": token.RefreshToken,
|
||||
})
|
||||
}
|
||||
|
||||
// Logout
|
||||
func (controller *authController) Logout(c *gin.Context) {
|
||||
token := c.GetHeader("Authorization")
|
||||
if token == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
|
||||
return
|
||||
}
|
||||
|
||||
err := controller.tokenService.Delete(token)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.SetCookie("Authorization", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("RefreshToken", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("ExpiresAt", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("RefreshExpiresAt", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("RefreshTokenExpiresAt", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("RefreshTokenExpiresAt", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("RefreshTokenExpiresAt", "", -1, "/", "localhost", false, true)
|
||||
c.JSON(http.StatusOK, gin.H{"message": "logout"})
|
||||
}
|
220
internal/controllers/center.go
Normal file
220
internal/controllers/center.go
Normal file
@ -0,0 +1,220 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CenterController interface {
|
||||
List(*gin.Context)
|
||||
Find(*gin.Context)
|
||||
Create(*gin.Context)
|
||||
Update(*gin.Context)
|
||||
}
|
||||
|
||||
type centerController struct {
|
||||
service services.CenterService
|
||||
tokenService services.TokenService
|
||||
}
|
||||
|
||||
func NewCenterController(service services.CenterService, tokenService services.TokenService) CenterController {
|
||||
return ¢erController{
|
||||
service: service,
|
||||
tokenService: tokenService,
|
||||
}
|
||||
}
|
||||
|
||||
// Center List
|
||||
//
|
||||
// @Summary 센터 목록 가져오기
|
||||
// @Description 센터 목록을 가져옵니다.
|
||||
// @Tags 센터
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param q query string false "검색어"
|
||||
// @Param page query int false "페이지"
|
||||
// @Param limit query int false "페이지 사이즈"
|
||||
//
|
||||
// @Success 200 {object} models.CenterListResponse
|
||||
// @Router /center [get]
|
||||
func (controller *centerController) List(c *gin.Context) {
|
||||
q := c.DefaultQuery("q", "")
|
||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if err != nil {
|
||||
fmt.Println("error : page")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if err != nil {
|
||||
fmt.Println("error : limit")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.List(q, page, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
totalNumber, err := controller.service.Total(q)
|
||||
if err != nil {
|
||||
fmt.Println("error : list")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
totalPage := int64(totalNumber/int64(limit) + 1)
|
||||
|
||||
response := models.CenterListResponse{
|
||||
Data: *result,
|
||||
Total: totalPage,
|
||||
Page: page,
|
||||
TotalPage: totalPage,
|
||||
PageSize: limit,
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Get Center
|
||||
//
|
||||
// @Summary 센터 정보 가져오기
|
||||
// @Description ID로 센터 정보를 가져옵니다.
|
||||
// @Tags 센터
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "센터 ID"
|
||||
//
|
||||
// @Success 200 {object} models.Center
|
||||
// @Router /center/{id} [get]
|
||||
func (controller *centerController) Find(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Create Center
|
||||
//
|
||||
// @Summary 센터 생성
|
||||
// @Description 센터를 만듭니다.
|
||||
// @Tags 센터
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param quizBody body models.CenterRequest true "Center Body"
|
||||
//
|
||||
// @Success 200 {object} models.Center
|
||||
// @Router /quiz [post]
|
||||
func (controller *centerController) Create(c *gin.Context) {
|
||||
var request models.CenterRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
center := &models.Center{
|
||||
GUID: uuid.NewString(),
|
||||
Title: request.Title,
|
||||
Name: request.Name,
|
||||
OwnerID: request.OwnerID,
|
||||
Content: request.Content,
|
||||
Info: request.Info,
|
||||
Memo: request.Memo,
|
||||
Status: request.Status,
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
result, err := controller.service.Create(center)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Update Center
|
||||
//
|
||||
// @Summary 센터 수정
|
||||
// @Description 센터를 수정합니다.
|
||||
// @Tags 센터
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path int64 true "Center ID"
|
||||
// @Param centerBody body models.CenterRequest true "Center Body"
|
||||
//
|
||||
// @Success 200 {object} models.Center
|
||||
// @Router /center/{id} [put]
|
||||
func (controller *centerController) Update(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.CenterRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
center, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
center.OwnerID = request.OwnerID
|
||||
center.Title = request.Title
|
||||
center.Name = request.Name
|
||||
center.Content = request.Content
|
||||
center.Info = request.Info
|
||||
center.Memo = request.Memo
|
||||
center.Status = request.Status
|
||||
center.UpdatedAt = time.Now()
|
||||
|
||||
result, err := controller.service.Update(center)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
243
internal/controllers/quiz.go
Normal file
243
internal/controllers/quiz.go
Normal file
@ -0,0 +1,243 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type QuizController interface {
|
||||
List(*gin.Context)
|
||||
Find(*gin.Context)
|
||||
Create(*gin.Context)
|
||||
Update(*gin.Context)
|
||||
}
|
||||
|
||||
type quizController struct {
|
||||
service services.QuizService
|
||||
}
|
||||
|
||||
func NewQuizController(service services.QuizService) QuizController {
|
||||
return &quizController{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// Quiz List
|
||||
//
|
||||
// @Summary 퀴즈 목록 가져오기
|
||||
// @Description 퀴즈 목록을 가져옵니다.
|
||||
// @Tags 퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param quiz_paper_id query string true "퀴즈페이퍼 ID"
|
||||
// @Param q query string false "검색어"
|
||||
// @Param page query int false "페이지"
|
||||
// @Param limit query int false "페이지 사이즈"
|
||||
//
|
||||
// @Success 200 {object} models.QuizListResponse
|
||||
// @Router /quiz [get]
|
||||
func (controller *quizController) List(c *gin.Context) {
|
||||
quiz_paper_id, err := strconv.ParseInt(c.DefaultQuery("quiz_paper_id", ""), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if err != nil {
|
||||
fmt.Println("error : page")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if err != nil {
|
||||
fmt.Println("error : limit")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.List(quiz_paper_id, page, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
totalNumber, err := controller.service.Total(quiz_paper_id)
|
||||
if err != nil {
|
||||
fmt.Println("error : list")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
totalPage := int64(totalNumber/int64(limit) + 1)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": result, "total": totalNumber, "page": page, "totalPage": totalPage, "pageSize": limit})
|
||||
}
|
||||
|
||||
// Get Quiz
|
||||
//
|
||||
// @Summary 퀴즈 가져오기
|
||||
// @Description ID로 퀴즈를 가져옵니다.
|
||||
// @Tags 퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "퀴즈 ID"
|
||||
//
|
||||
// @Success 200 {object} models.QuizResponse
|
||||
// @Router /quiz/{id} [get]
|
||||
func (controller *quizController) Find(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Create Quiz
|
||||
//
|
||||
// @Summary 퀴즈 생성
|
||||
// @Description 퀴즈를 만듭니다.
|
||||
// @Tags 퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param quizBody body models.QuizRequest true "Quiz Body"
|
||||
//
|
||||
// @Success 200 {object} models.QuizResponse
|
||||
// @Router /quiz [post]
|
||||
func (controller *quizController) Create(c *gin.Context) {
|
||||
var request models.QuizRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var content datatypes.JSON
|
||||
content, err := json.Marshal(request.Content)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var answer datatypes.JSON
|
||||
answer, err = json.Marshal(request.Answer)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
quiz := &models.Quiz{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: request.CenterID,
|
||||
QuizPaperID: request.QuizPaperID,
|
||||
No: request.No,
|
||||
QuestionType: request.QuestionType,
|
||||
Question: request.Question,
|
||||
Content: content,
|
||||
Answer: answer,
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
result, err := controller.service.Create(quiz)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Update Quiz
|
||||
//
|
||||
// @Summary 퀴즈 수정
|
||||
// @Description 퀴즈를 수정합니다.
|
||||
// @Tags 퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path int64 true "Quiz ID"
|
||||
// @Param quizBody body models.QuizRequest true "Quiz Body"
|
||||
//
|
||||
// @Success 200 {object} models.QuizResponse
|
||||
// @Router /quiz/{id} [put]
|
||||
func (controller *quizController) Update(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.QuizRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
quiz, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var content datatypes.JSON
|
||||
content, err = json.Marshal(request.Content)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var answer datatypes.JSON
|
||||
answer, err = json.Marshal(request.Answer)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
quiz.QuizPaperID = request.QuizPaperID
|
||||
quiz.No = request.No
|
||||
quiz.QuestionType = request.QuestionType
|
||||
quiz.Question = request.Question
|
||||
quiz.Content = content
|
||||
quiz.Answer = answer
|
||||
quiz.UpdatedAt = time.Now()
|
||||
|
||||
result, err := controller.service.Update(quiz)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
314
internal/controllers/quizpaper.go
Normal file
314
internal/controllers/quizpaper.go
Normal file
@ -0,0 +1,314 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type QuizPaperController interface {
|
||||
List(*gin.Context)
|
||||
Find(*gin.Context)
|
||||
Create(*gin.Context)
|
||||
Update(*gin.Context)
|
||||
Copy(*gin.Context)
|
||||
}
|
||||
|
||||
type quizPaperController struct {
|
||||
service services.QuizPaperService
|
||||
quizService services.QuizService
|
||||
}
|
||||
|
||||
func NewQuizPaperController(service services.QuizPaperService, quizService services.QuizService) QuizPaperController {
|
||||
return &quizPaperController{
|
||||
service: service,
|
||||
quizService: quizService,
|
||||
}
|
||||
}
|
||||
|
||||
// QuizPaper List
|
||||
//
|
||||
// @Summary 퀴즈페이퍼 목록 가져오기
|
||||
// @Description 퀴즈페이퍼 목록을 가져옵니다.
|
||||
// @Tags 퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param tag query string false "태그"
|
||||
// @Param q query string false "검색어"
|
||||
// @Param page query int false "페이지"
|
||||
// @Param limit query int false "페이지 사이즈"
|
||||
//
|
||||
// @Success 200 {object} models.QuizPaperListResponse
|
||||
// @Router /quizpaper [get]
|
||||
func (controller *quizPaperController) List(c *gin.Context) {
|
||||
tag := c.DefaultQuery("tag", "")
|
||||
q := c.DefaultQuery("q", "")
|
||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if err != nil {
|
||||
fmt.Println("error : page")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if err != nil {
|
||||
fmt.Println("error : limit")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.List(q, tag, page, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
totalNumber, err := controller.service.Total(q, tag)
|
||||
if err != nil {
|
||||
fmt.Println("error : list")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
totalPage := int64(totalNumber/int64(limit) + 1)
|
||||
|
||||
response := models.QuizPaperListResponse{
|
||||
Data: *result,
|
||||
Total: totalPage,
|
||||
Page: page,
|
||||
TotalPage: totalPage,
|
||||
PageSize: limit,
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Get quizPaper
|
||||
//
|
||||
// @Summary 퀴즈 퀴즈페이퍼 가져오기
|
||||
// @Description ID로 퀴즈 퀴즈페이퍼을 가져옵니다.
|
||||
// @Tags 퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "퀴즈 퀴즈페이퍼 ID"
|
||||
//
|
||||
// @Success 200 {object} models.QuizPaperResponse
|
||||
// @Router /quizpaper/{id} [get]
|
||||
func (controller *quizPaperController) Find(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Create QuizPaper
|
||||
//
|
||||
// @Summary 퀴즈 퀴즈페이퍼 생성
|
||||
// @Description 퀴즈 퀴즈페이퍼을 만듭니다.
|
||||
// @Tags 퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param quizPaperBody body models.QuizPaperRequest true "QuizPaper Body"
|
||||
//
|
||||
// @Success 200 {object} models.QuizPaperResponse
|
||||
// @Router /quizpaper [post]
|
||||
func (controller *quizPaperController) Create(c *gin.Context) {
|
||||
var request models.QuizPaperRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
user_id := c.GetInt64("sub")
|
||||
|
||||
quizPaper := &models.QuizPaper{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: request.CenterID,
|
||||
ManagerID: user_id,
|
||||
Title: request.Title,
|
||||
Content: request.Content,
|
||||
Category: request.Category,
|
||||
Tag: request.Tag,
|
||||
Status: request.Status,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
result, err := controller.service.Create(quizPaper)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Update QuizPaper
|
||||
//
|
||||
// @Summary 퀴즈 퀴즈페이퍼 수정
|
||||
// @Description 퀴즈 퀴즈페이퍼을 수정합니다.
|
||||
// @Tags 퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "퀴즈 퀴즈페이퍼 ID"
|
||||
// @Param quizPaperUpdateBody body models.QuizPaperRequest true "QuizPaper Body"
|
||||
//
|
||||
// @Success 200 {object} models.QuizPaperResponse
|
||||
// @Router /quizpaper/{id} [put]
|
||||
func (controller *quizPaperController) Update(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.QuizPaperRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
quizPaper, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
user_id := c.GetInt64("sub")
|
||||
quizPaper.ManagerID = user_id
|
||||
quizPaper.CenterID = request.CenterID
|
||||
quizPaper.Title = request.Title
|
||||
quizPaper.Content = request.Content
|
||||
quizPaper.Category = request.Category
|
||||
quizPaper.Tag = request.Tag
|
||||
quizPaper.Status = request.Status
|
||||
quizPaper.UpdatedAt = time.Now()
|
||||
|
||||
result, err := controller.service.Update(quizPaper)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Copy QuizPaper
|
||||
//
|
||||
// @Summary 퀴즈 퀴즈페이퍼 복사
|
||||
// @Description 퀴즈 퀴즈페이퍼와 퀴즈를 복사합니다.
|
||||
// @Tags 퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "퀴즈페이퍼 ID"
|
||||
// @Param quizPaperCopyBody body models.QuizPaperCopyRequest true "QuizPaper Copy Body"
|
||||
//
|
||||
// @Success 200 {object} models.QuizPaperCopyResponse
|
||||
// @Router /quizpaper/{id}/copy [post]
|
||||
func (controller *quizPaperController) Copy(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
fmt.Println("id : ", c.Param("id"))
|
||||
if err != nil {
|
||||
fmt.Println("id convert err")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.QuizPaperCopyRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
fmt.Println("req err")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
user_id := c.GetInt64("sub")
|
||||
template, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
newQuizPaper := &models.QuizPaper{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: request.CenterID,
|
||||
ManagerID: user_id,
|
||||
Title: request.Title,
|
||||
Content: template.Content,
|
||||
Category: template.Category,
|
||||
Tag: template.Tag,
|
||||
Status: template.Status,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
quizPaper, err := controller.service.Create(newQuizPaper)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
quizTemplates, err := controller.quizService.List(id, 1, 10000)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// iterate quizTemplate
|
||||
var quizzes []*models.Quiz
|
||||
for _, quiz := range *quizTemplates {
|
||||
newQuiz := &models.Quiz{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: request.CenterID,
|
||||
QuizPaperID: quizPaper.ID,
|
||||
No: quiz.No,
|
||||
QuestionType: quiz.QuestionType,
|
||||
Question: quiz.Question,
|
||||
Content: quiz.Content,
|
||||
Answer: quiz.Answer,
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
result, err := controller.quizService.Create(newQuiz)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
quizzes = append(quizzes, result)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"quiz_paper": quizPaper, "quiz": quizzes})
|
||||
}
|
22
internal/controllers/swagger.go
Normal file
22
internal/controllers/swagger.go
Normal file
@ -0,0 +1,22 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SwaggerController interface {
|
||||
Get(*gin.Context)
|
||||
}
|
||||
|
||||
type swaggerController struct {
|
||||
}
|
||||
|
||||
func NewSwaggerController() SwaggerController {
|
||||
return &swaggerController{}
|
||||
}
|
||||
|
||||
func (controller *swaggerController) Get(c *gin.Context) {
|
||||
c.Redirect(http.StatusFound, "/swagger/index.html")
|
||||
}
|
53
internal/controllers/token.go
Normal file
53
internal/controllers/token.go
Normal file
@ -0,0 +1,53 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type TokenController interface {
|
||||
Refresh(*gin.Context)
|
||||
}
|
||||
|
||||
type tokenController struct {
|
||||
service services.TokenService
|
||||
}
|
||||
|
||||
func NewTokenController(service services.TokenService) TokenController {
|
||||
return &tokenController{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh Token
|
||||
//
|
||||
// @Summary AccessToken Refresh
|
||||
// @Description AccessToken을 RefreshToken으로 갱신합니다.
|
||||
// @Tags Token
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Param refresh_token body string true "RefreshToken"
|
||||
//
|
||||
// @Router /token/refresh [post]
|
||||
// @Success 200 {object} models.Token
|
||||
func (controller *tokenController) Refresh(c *gin.Context) {
|
||||
var request models.RefreshTokenRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Refresh(request.RefreshToken)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
131
internal/controllers/user.go
Normal file
131
internal/controllers/user.go
Normal file
@ -0,0 +1,131 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UserController interface {
|
||||
List(*gin.Context)
|
||||
Find(*gin.Context)
|
||||
}
|
||||
|
||||
type userController struct {
|
||||
service services.UserService
|
||||
tokenService services.TokenService
|
||||
}
|
||||
|
||||
func NewUserController(service services.UserService, tokenService services.TokenService) UserController {
|
||||
return &userController{
|
||||
service: service,
|
||||
tokenService: tokenService,
|
||||
}
|
||||
}
|
||||
|
||||
// User List
|
||||
//
|
||||
// @Summary 사용자 목록 가져오기
|
||||
// @Description 사용자 목록을 가져옵니다.
|
||||
// @Tags 사용자
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param q query string false "검색어"
|
||||
// @Param page query int false "페이지"
|
||||
// @Param limit query int false "페이지 사이즈"
|
||||
//
|
||||
// @Success 200 {object} models.UserListResponse
|
||||
// @Router /user [get]
|
||||
func (controller *userController) List(c *gin.Context) {
|
||||
q := c.DefaultQuery("q", "")
|
||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if err != nil {
|
||||
fmt.Println("error : page")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if err != nil {
|
||||
fmt.Println("error : limit")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.List(q, page, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
totalNumber, err := controller.service.Total(q)
|
||||
if err != nil {
|
||||
fmt.Println("error : list")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
totalPage := int64(totalNumber/int64(limit) + 1)
|
||||
|
||||
response := models.UserListResponse{
|
||||
Data: *result,
|
||||
Total: totalPage,
|
||||
Page: page,
|
||||
TotalPage: totalPage,
|
||||
PageSize: limit,
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Get User
|
||||
//
|
||||
// @Summary 사용자 정보 가져오기
|
||||
// @Description ID로 사용자 정보를 가져옵니다.
|
||||
// @Tags 사용자
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "사용자 ID"
|
||||
//
|
||||
// @Success 200 {object} models.User
|
||||
// @Router /user/{id} [get]
|
||||
func (controller *userController) Find(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
sub := c.GetString("sub")
|
||||
user_id, err := strconv.ParseInt(sub, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if user_id != id {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Wrong user"})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
236
internal/controllers/userquiz.go
Normal file
236
internal/controllers/userquiz.go
Normal file
@ -0,0 +1,236 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type UserQuizController interface {
|
||||
List(*gin.Context)
|
||||
Find(*gin.Context)
|
||||
Create(*gin.Context)
|
||||
Update(*gin.Context)
|
||||
}
|
||||
|
||||
type userQuizController struct {
|
||||
service services.UserQuizService
|
||||
}
|
||||
|
||||
func NewUserQuizController(service services.UserQuizService) QuizController {
|
||||
return &userQuizController{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// UserQuiz List
|
||||
//
|
||||
// @Summary 사용자퀴즈 목록 가져오기
|
||||
// @Description 사용자퀴즈 목록을 가져옵니다.
|
||||
// @Tags 사용자퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param user_quiz_paper_id query string true "사용자퀴즈페이퍼 ID"
|
||||
// @Param q query string false "검색어"
|
||||
// @Param page query int false "페이지"
|
||||
// @Param limit query int false "페이지 사이즈"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizListResponse
|
||||
// @Router /userquiz [get]
|
||||
func (controller *userQuizController) List(c *gin.Context) {
|
||||
quiz_paper_id, err := strconv.ParseInt(c.DefaultQuery("user_quiz_paper_id", ""), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if err != nil {
|
||||
fmt.Println("error : page")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if err != nil {
|
||||
fmt.Println("error : limit")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.List(quiz_paper_id, page, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
totalNumber, err := controller.service.Total(quiz_paper_id)
|
||||
if err != nil {
|
||||
fmt.Println("error : list")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
totalPage := int64(totalNumber/int64(limit) + 1)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": result, "total": totalNumber, "page": page, "totalPage": totalPage, "pageSize": limit})
|
||||
}
|
||||
|
||||
// Get UserQuiz
|
||||
//
|
||||
// @Summary 사용자퀴즈 가져오기
|
||||
// @Description ID로 사용자퀴즈를 가져옵니다.
|
||||
// @Tags 사용자퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "사용자퀴즈 ID"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizResponse
|
||||
// @Router /userquiz/{id} [get]
|
||||
func (controller *userQuizController) Find(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Create Quiz
|
||||
//
|
||||
// @Summary 사용자퀴즈 생성
|
||||
// @Description 사용자퀴즈를 만듭니다.
|
||||
// @Tags 사용자퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param quizBody body models.UserQuizRequest true "UserQuiz Body"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizResponse
|
||||
// @Router /userquiz [post]
|
||||
func (controller *userQuizController) Create(c *gin.Context) {
|
||||
var request models.UserQuizRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var content datatypes.JSON
|
||||
content, err := json.Marshal(request.Content)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var answer datatypes.JSON
|
||||
answer, err = json.Marshal([]string{})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
quiz := &models.UserQuiz{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: request.CenterID,
|
||||
UserQuizPaperID: request.UserQuizPaperID,
|
||||
No: request.No,
|
||||
QuestionType: request.QuestionType,
|
||||
Question: request.Question,
|
||||
Content: content,
|
||||
Answer: answer,
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
result, err := controller.service.Create(quiz)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Update Quiz
|
||||
//
|
||||
// @Summary 사용자퀴즈 수정
|
||||
// @Description 사용자퀴즈를 수정합니다.
|
||||
// @Tags 사용자퀴즈
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path int64 true "Quiz ID"
|
||||
// @Param quizBody body models.UserQuizRequest true "Quiz Body"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizResponse
|
||||
// @Router /userquiz/{id} [put]
|
||||
func (controller *userQuizController) Update(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.UserQuizRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
userquiz, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// CenterID int64 `json:"center_id" example:"1000001"`
|
||||
// UserQuizPaperID int64 `json:"quiz_paper_id" example:"1000001"`
|
||||
// UserID int64 `json:"user_id" example:"1000001"`
|
||||
// No int `json:"vol_no" example:"1"`
|
||||
// QuestionType string `json:"question_type" example:"choice"`
|
||||
// Question string `json:"question" example:"질문입니다."`
|
||||
// Content datatypes.JSON `json:"content"`
|
||||
// Answer datatypes.JSON `json:"answer"`
|
||||
// Status string `json:"status" example:"waiting"`
|
||||
// Result string `json:"result" example:"success"`
|
||||
// Score float32 `json:"score" example:"10"`
|
||||
|
||||
userquiz.CenterID = request.CenterID
|
||||
userquiz.UserQuizPaperID = request.UserQuizPaperID
|
||||
|
||||
result, err := controller.service.Update(userquiz)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
331
internal/controllers/userquizpaper.go
Normal file
331
internal/controllers/userquizpaper.go
Normal file
@ -0,0 +1,331 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UserQuizPaperController interface {
|
||||
List(*gin.Context)
|
||||
Find(*gin.Context)
|
||||
Create(*gin.Context)
|
||||
Update(*gin.Context)
|
||||
Patch(*gin.Context)
|
||||
}
|
||||
|
||||
type userQuizPaperController struct {
|
||||
service services.UserQuizPaperService
|
||||
userService services.UserService
|
||||
quizPaperService services.QuizPaperService
|
||||
userQuizService services.UserQuizService
|
||||
}
|
||||
|
||||
func NewUserQuizPaperController(
|
||||
service services.UserQuizPaperService,
|
||||
userService services.UserService,
|
||||
quizPaperService services.QuizPaperService,
|
||||
userQuizService services.UserQuizService,
|
||||
) UserQuizPaperController {
|
||||
return &userQuizPaperController{
|
||||
service: service,
|
||||
userService: userService,
|
||||
quizPaperService: quizPaperService,
|
||||
userQuizService: userQuizService,
|
||||
}
|
||||
}
|
||||
|
||||
// UserQuizPaper List
|
||||
//
|
||||
// @Summary 응시 목록 가져오기
|
||||
// @Description 응시 목록을 가져옵니다.
|
||||
// @Tags 사용자퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param q query string false "검색어"
|
||||
// @Param page query int false "페이지"
|
||||
// @Param limit query int false "페이지 사이즈"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizPaperListResponse
|
||||
// @Router /userquizpaper [get]
|
||||
func (controller *userQuizPaperController) List(c *gin.Context) {
|
||||
q := c.DefaultQuery("q", "")
|
||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if err != nil {
|
||||
fmt.Println("error : page")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if err != nil {
|
||||
fmt.Println("error : limit")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.List(q, page, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
totalNumber, err := controller.service.Total(q)
|
||||
if err != nil {
|
||||
fmt.Println("error : list")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
totalPage := int64(totalNumber/int64(limit) + 1)
|
||||
|
||||
response := models.UserQuizPaperListResponse{
|
||||
Data: *result,
|
||||
Total: totalNumber,
|
||||
Page: page,
|
||||
TotalPage: totalPage,
|
||||
PageSize: limit,
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Get userQuizPaper
|
||||
//
|
||||
// @Summary 응시 정보 가져오기
|
||||
// @Description ID로 응시 정보를 가져옵니다.
|
||||
// @Tags 사용자퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path string true "응시 ID"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizPaperResponse
|
||||
// @Router /userquizpaper/{id} [get]
|
||||
func (controller *userQuizPaperController) Find(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Create UserQuizPaper
|
||||
//
|
||||
// @Summary 응시 매칭 생성
|
||||
// @Description 응시 매칭을 만듭니다.
|
||||
// @Tags 사용자퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param userQuizPaperBody body models.UserQuizPaperRequest true "UserQuizPaper Body"
|
||||
//
|
||||
// @Success 200 {object} []models.UserQuizPaper
|
||||
// @Router /userquizpaper [post]
|
||||
func (controller *userQuizPaperController) Create(c *gin.Context) {
|
||||
var request models.UserQuizPaperRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("users", request.Users)
|
||||
|
||||
quizPaper, err := controller.quizPaperService.Find(request.QuizPaperID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var users []int64
|
||||
err = json.Unmarshal(request.Users, &users)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
templates := controller.service.Generate(users, quizPaper)
|
||||
userQuizPapers, err := controller.service.Insert(templates)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var userquizzes []models.UserQuiz
|
||||
for _, userQuizPaper := range userQuizPapers {
|
||||
items, err := controller.userQuizService.Generate(request.QuizPaperID, &userQuizPaper)
|
||||
if err == nil {
|
||||
userquizzes = append(userquizzes, items...)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = controller.userQuizService.Insert(userquizzes)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"userQuizPaper": userQuizPapers})
|
||||
}
|
||||
|
||||
// Update UserQuizPaper
|
||||
//
|
||||
// @Summary 응시 수정
|
||||
// @Description 응시를 수정합니다.
|
||||
// @Tags 사용자퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path int64 true "UserQuizPaper ID"
|
||||
// @Param userQuizPaperUpdateBody body models.UserQuizPaperUpdateRequest true "UserQuizPaper Update Body"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizPaperResponse
|
||||
// @Router /userquizpaper/{id} [put]
|
||||
func (controller *userQuizPaperController) Update(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.UserQuizPaperUpdateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("request", request)
|
||||
userQuizPaper, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
userQuizPaper.QuizPaperID = request.QuizPaperID
|
||||
userQuizPaper.UserID = request.UserID
|
||||
userQuizPaper.Status = request.Status
|
||||
userQuizPaper.UserScore = request.UserScore
|
||||
userQuizPaper.TotalScore = request.TotalScore
|
||||
|
||||
if request.StartAt != "" {
|
||||
fmt.Println("request.StartAt", request.StartAt)
|
||||
start_at, err := time.Parse("2006-01-02T15:04:05-07:00", request.StartAt)
|
||||
if err == nil {
|
||||
userQuizPaper.StartAt = &start_at
|
||||
}
|
||||
fmt.Println("start_at", start_at)
|
||||
}
|
||||
|
||||
if request.DoneAt != "" {
|
||||
fmt.Println("request.EndAt", request.DoneAt)
|
||||
done_at, err := time.Parse("2006-01-02T15:04:05-07:00", request.DoneAt)
|
||||
if err == nil {
|
||||
userQuizPaper.DoneAt = &done_at
|
||||
}
|
||||
fmt.Println("done_at", done_at)
|
||||
}
|
||||
fmt.Println("userQuizPaper", userQuizPaper)
|
||||
result, err := controller.service.Update(userQuizPaper)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("result", result)
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// Patch UserQuizPaper
|
||||
//
|
||||
// @Summary 응시 정보 변경
|
||||
// @Description 응시 정보를 변경합니다.
|
||||
// @Tags 사용자퀴즈페이퍼
|
||||
//
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
//
|
||||
// @Security Bearer
|
||||
//
|
||||
// @Param id path int64 true "UserQuizPaper ID"
|
||||
// @Param userQuizPaperPatchBody body models.UserQuizPaperPatchRequest true "UserQuizPaper Patch Body (변경할 필드만 입력)"
|
||||
//
|
||||
// @Success 200 {object} models.UserQuizPaperResponse
|
||||
// @Router /userquizpaper/{id} [patch]
|
||||
func (controller *userQuizPaperController) Patch(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var request models.UserQuizPaperPatchRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("request", request)
|
||||
userQuizPaper, err := controller.service.Find(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if request.Status != "" {
|
||||
userQuizPaper.Status = request.Status
|
||||
}
|
||||
|
||||
if request.StartAt != "" {
|
||||
fmt.Println("request.StartAt", request.StartAt)
|
||||
start_at, err := time.Parse("2006-01-02T15:04:05-07:00", request.StartAt)
|
||||
if err == nil {
|
||||
userQuizPaper.StartAt = &start_at
|
||||
}
|
||||
fmt.Println("start_at", start_at)
|
||||
}
|
||||
|
||||
if request.DoneAt != "" {
|
||||
fmt.Println("request.EndAt", request.DoneAt)
|
||||
done_at, err := time.Parse("2006-01-02T15:04:05-07:00", request.DoneAt)
|
||||
if err == nil {
|
||||
userQuizPaper.DoneAt = &done_at
|
||||
}
|
||||
fmt.Println("done_at", done_at)
|
||||
}
|
||||
|
||||
fmt.Println("userQuizPaper", userQuizPaper)
|
||||
result, err := controller.service.Update(userQuizPaper)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("result", result)
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
44
internal/database/database.go
Normal file
44
internal/database/database.go
Normal file
@ -0,0 +1,44 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
config "learnsteam/cslms-api/configs"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
*gorm.DB
|
||||
}
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
func Init() {
|
||||
DB = ConnectDB((config.DATABASE_URL))
|
||||
}
|
||||
|
||||
func ConnectDB(url string) *gorm.DB {
|
||||
gorm_config := gorm.Config{NamingStrategy: schema.NamingStrategy{SingularTable: true}}
|
||||
db, err := gorm.Open(mysql.Open(url), &gorm_config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func GetDB() *gorm.DB {
|
||||
return DB
|
||||
}
|
||||
|
||||
func AutoMigrate() {
|
||||
fmt.Println("AugoMigrate")
|
||||
// DB.AutoMigrate(
|
||||
// &models.User{},
|
||||
// &models.Token{},
|
||||
// &models.Program{},
|
||||
// &models.Quiz{},
|
||||
// &models.Exam{},
|
||||
// )
|
||||
}
|
86
internal/helpers/cipher/cipher.go
Normal file
86
internal/helpers/cipher/cipher.go
Normal file
@ -0,0 +1,86 @@
|
||||
package cipher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Crypto interface {
|
||||
Encrypt(plainText string) (string, error)
|
||||
Decrypt(cipherIvKey string) (string, error)
|
||||
}
|
||||
|
||||
type niceCrypto struct {
|
||||
cipherKey string
|
||||
cipherIvKey string
|
||||
}
|
||||
|
||||
func (c niceCrypto) Encrypt(plainText string) (string, error) {
|
||||
if strings.TrimSpace(plainText) == "" {
|
||||
return plainText, nil
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher([]byte(c.cipherKey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
encrypter := cipher.NewCBCEncrypter(block, []byte(c.cipherIvKey))
|
||||
paddedPlainText := padPKCS7([]byte(plainText), encrypter.BlockSize())
|
||||
|
||||
cipherText := make([]byte, len(paddedPlainText))
|
||||
// CryptBlocks 함수에 데이터(paddedPlainText)와 암호화 될 데이터를 저장할 슬라이스(cipherText)를 넣으면 암호화가 된다.
|
||||
encrypter.CryptBlocks(cipherText, paddedPlainText)
|
||||
|
||||
return base64.StdEncoding.EncodeToString(cipherText), nil
|
||||
}
|
||||
|
||||
func (c niceCrypto) Decrypt(cipherText string) (string, error) {
|
||||
if strings.TrimSpace(cipherText) == "" {
|
||||
return cipherText, nil
|
||||
}
|
||||
|
||||
decodedCipherText, err := base64.StdEncoding.DecodeString(cipherText)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher([]byte(c.cipherKey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
decrypter := cipher.NewCBCDecrypter(block, []byte(c.cipherIvKey))
|
||||
plainText := make([]byte, len(decodedCipherText))
|
||||
|
||||
decrypter.CryptBlocks(plainText, decodedCipherText)
|
||||
trimmedPlainText := trimPKCS5(plainText)
|
||||
|
||||
return string(trimmedPlainText), nil
|
||||
}
|
||||
|
||||
func NewNiceCrypto(cipherKey, cipherIvKey string) (Crypto, error) {
|
||||
if ck := len(cipherKey); ck != 32 {
|
||||
return nil, aes.KeySizeError(ck)
|
||||
}
|
||||
|
||||
if cik := len(cipherIvKey); cik != 16 {
|
||||
return nil, aes.KeySizeError(cik)
|
||||
}
|
||||
|
||||
return &niceCrypto{cipherKey, cipherIvKey}, nil
|
||||
}
|
||||
|
||||
func padPKCS7(plainText []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(plainText)%blockSize
|
||||
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(plainText, padText...)
|
||||
}
|
||||
|
||||
func trimPKCS5(text []byte) []byte {
|
||||
padding := text[len(text)-1]
|
||||
return text[:len(text)-int(padding)]
|
||||
}
|
19
internal/helpers/helpers.go
Normal file
19
internal/helpers/helpers.go
Normal file
@ -0,0 +1,19 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InLambda() bool {
|
||||
if lambdaTaskRoot := os.Getenv("LAMBDA_TASK_ROOT"); lambdaTaskRoot != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Datetime(timeString string) (time.Time, error) {
|
||||
layout := "2006-01-02T15:04:05.000Z"
|
||||
result, err := time.Parse(layout, timeString)
|
||||
return result, err
|
||||
}
|
150
internal/helpers/securityutil/securityutil.go
Normal file
150
internal/helpers/securityutil/securityutil.go
Normal file
@ -0,0 +1,150 @@
|
||||
package securityutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func SHA256(data string) string {
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(data))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPasswordHash(password string, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func AES256Encode(plaintext string, key string, iv string, blockSize int) string {
|
||||
bKey := []byte(key)
|
||||
bIV := []byte(iv)
|
||||
bPlaintext := PKCS5Padding([]byte(plaintext), blockSize, len(plaintext))
|
||||
block, err := aes.NewCipher(bKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ciphertext := make([]byte, len(bPlaintext))
|
||||
mode := cipher.NewCBCEncrypter(block, bIV)
|
||||
mode.CryptBlocks(ciphertext, bPlaintext)
|
||||
// return hex.EncodeToString(ciphertext)
|
||||
fmt.Printf("hex.EncodeToString(ciphertext) : %s\n", hex.EncodeToString(ciphertext))
|
||||
fmt.Printf("base64.StdEncoding.EncodeToString(ciphertext) : %s\n", base64.StdEncoding.EncodeToString(ciphertext))
|
||||
fmt.Printf("base64.RawStdEncoding.EncodeToString(ciphertext) : %s\n", base64.RawStdEncoding.EncodeToString(ciphertext))
|
||||
return base64.StdEncoding.EncodeToString(ciphertext)
|
||||
}
|
||||
|
||||
func AES256Decode(cipherText string, encKey string, iv string) (decryptedString string) {
|
||||
bKey := []byte(encKey)
|
||||
bIV := []byte(iv)
|
||||
// cipherTextDecoded, err := hex.DecodeString(cipherText)
|
||||
cipherTextDecoded, err := base64.StdEncoding.DecodeString(cipherText)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(bKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, bIV)
|
||||
mode.CryptBlocks([]byte(cipherTextDecoded), []byte(cipherTextDecoded))
|
||||
return string(cipherTextDecoded)
|
||||
}
|
||||
|
||||
func PKCS5Padding(ciphertext []byte, blockSize int, after int) []byte {
|
||||
padding := (blockSize - len(ciphertext)%blockSize)
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
// func pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
|
||||
// if blocksize <= 0 {
|
||||
// return nil, ErrInvalidBlockSize
|
||||
// }
|
||||
// if b == nil || len(b) == 0 {
|
||||
// return nil, ErrInvalidPKCS7Data
|
||||
// }
|
||||
// n := blocksize - (len(b) % blocksize)
|
||||
// pb := make([]byte, len(b)+n)
|
||||
// copy(pb, b)
|
||||
// copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
|
||||
// return pb, nil
|
||||
// }
|
||||
|
||||
// // pkcs7Unpad validates and unpads data from the given bytes slice.
|
||||
// // The returned value will be 1 to n bytes smaller depending on the
|
||||
// // amount of padding, where n is the block size.
|
||||
// func pkcs7Unpad(b []byte, blocksize int) ([]byte, error) {
|
||||
// if blocksize <= 0 {
|
||||
// return nil, ErrInvalidBlockSize
|
||||
// }
|
||||
// if b == nil || len(b) == 0 {
|
||||
// return nil, ErrInvalidPKCS7Data
|
||||
// }
|
||||
// if len(b)%blocksize != 0 {
|
||||
// return nil, ErrInvalidPKCS7Padding
|
||||
// }
|
||||
// c := b[len(b)-1]
|
||||
// n := int(c)
|
||||
// if n == 0 || n > len(b) {
|
||||
// return nil, ErrInvalidPKCS7Padding
|
||||
// }
|
||||
// for i := 0; i < n; i++ {
|
||||
// if b[len(b)-n+i] != c {
|
||||
// return nil, ErrInvalidPKCS7Padding
|
||||
// }
|
||||
// }
|
||||
// return b[:len(b)-n], nil
|
||||
// }
|
||||
|
||||
// // func Encrypt(b cipher.Block, plaintext []byte) []byte {
|
||||
// // if mod := len(plaintext) % aes.BlockSize; mod != 0 { // 블록 크기의 배수가 되어야함
|
||||
// // padding := make([]byte, aes.BlockSize-mod) // 블록 크기에서 모자라는 부분을
|
||||
// // plaintext = append(plaintext, padding...) // 채워줌
|
||||
// // }
|
||||
|
||||
// // ciphertext := make([]byte, aes.BlockSize+len(plaintext)) // 초기화 벡터 공간(aes.BlockSize)만큼 더 생성
|
||||
// // // iv := ciphertext[:aes.BlockSize] // 부분 슬라이스로 초기화 벡터 공간을 가져옴
|
||||
// // // if _, err := io.ReadFull(rand.Reader, iv); err != nil { // 랜덤 값을 초기화 벡터에 넣어줌
|
||||
// // // fmt.Println(err)
|
||||
// // // return nil
|
||||
// // // }
|
||||
// // iv := []byte("0000000000000000")
|
||||
// // mode := cipher.NewCBCEncrypter(b, iv) // 암호화 블록과 초기화 벡터를 넣어서 암호화 블록 모드 인스턴스 생성
|
||||
// // mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) // 암호화 블록 모드 인스턴스로
|
||||
// // // 암호화
|
||||
|
||||
// // return ciphertext
|
||||
// // }
|
||||
|
||||
// // func Decrypt(b cipher.Block, ciphertext []byte) []byte {
|
||||
// // if len(ciphertext)%aes.BlockSize != 0 { // 블록 크기의 배수가 아니면 리턴
|
||||
// // fmt.Println("암호화된 데이터의 길이는 블록 크기의 배수가 되어야합니다.")
|
||||
// // return nil
|
||||
// // }
|
||||
|
||||
// // // iv := ciphertext[:aes.BlockSize] // 부분 슬라이스로 초기화 벡터 공간을 가져옴
|
||||
// // iv := []byte("0000000000000000")
|
||||
// // ciphertext = ciphertext[aes.BlockSize:] // 부분 슬라이스로 암호화된 데이터를 가져옴
|
||||
|
||||
// // plaintext := make([]byte, len(ciphertext)) // 평문 데이터를 저장할 공간 생성
|
||||
// // mode := cipher.NewCBCDecrypter(b, iv) // 암호화 블록과 초기화 벡터를 넣어서
|
||||
// // // 복호화 블록 모드 인스턴스 생성
|
||||
// // mode.CryptBlocks(plaintext, ciphertext) // 복호화 블록 모드 인스턴스로 복호화
|
||||
|
||||
// // return plaintext
|
||||
// // }
|
136
internal/middleware/auth.go
Normal file
136
internal/middleware/auth.go
Normal file
@ -0,0 +1,136 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
config "learnsteam/cslms-api/configs"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
func Auth(permission string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
sub, err := UserID(c.Request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
role, err := Role(c.Request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if permission != "member" && *role != permission {
|
||||
fmt.Println("permission", permission, "role", *role)
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("token", extract(c.Request))
|
||||
fmt.Println("sub", sub)
|
||||
|
||||
c.Set("token", extract(c.Request))
|
||||
c.Set("sub", sub)
|
||||
c.Set("role", role)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func Permission(permission *string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
sub, err := UserID(c.Request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
role, err := Role(c.Request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if role != permission {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("token", extract(c.Request))
|
||||
fmt.Println("sub", sub)
|
||||
|
||||
c.Set("token", extract(c.Request))
|
||||
c.Set("sub", sub)
|
||||
c.Set("role", role)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func extract(r *http.Request) string {
|
||||
authorization := r.Header.Get("Authorization")
|
||||
strArr := strings.Split(authorization, " ")
|
||||
if len(strArr) == 2 {
|
||||
return strArr[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func verify(r *http.Request) (*jwt.Token, error) {
|
||||
tokenString := extract(r)
|
||||
jwtToken, err := jwt.Parse(tokenString, func(jwtToken *jwt.Token) (interface{}, error) {
|
||||
if _, ok := jwtToken.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", jwtToken.Header["alg"])
|
||||
}
|
||||
return []byte(config.SECRET_KEY), nil
|
||||
})
|
||||
|
||||
return jwtToken, err
|
||||
}
|
||||
|
||||
func UserID(r *http.Request) (int64, error) {
|
||||
jwtToken, err := verify(r)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
claims, ok := jwtToken.Claims.(jwt.MapClaims)
|
||||
if !ok || !jwtToken.Valid {
|
||||
return -1, errors.New("refresh token is invalid")
|
||||
}
|
||||
|
||||
sub := claims["sub"].(float64)
|
||||
user_id := int64(sub)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
fmt.Println(user_id)
|
||||
|
||||
return user_id, nil
|
||||
}
|
||||
|
||||
func Role(r *http.Request) (*string, error) {
|
||||
jwtToken, err := verify(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims, ok := jwtToken.Claims.(jwt.MapClaims)
|
||||
if !ok || !jwtToken.Valid {
|
||||
return nil, errors.New("refresh token is invalid")
|
||||
}
|
||||
|
||||
role := claims["role"].(string)
|
||||
|
||||
return &role, nil
|
||||
}
|
44
internal/middleware/transaction.go
Normal file
44
internal/middleware/transaction.go
Normal file
@ -0,0 +1,44 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func StatusInList(status int, statusList []int) bool {
|
||||
for _, i := range statusList {
|
||||
for i == status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Transaction(db *gorm.DB) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
txHandle := db.Begin()
|
||||
log.Print("begining database transaction")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
txHandle.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
c.Set("db_trx", txHandle)
|
||||
c.Next()
|
||||
|
||||
if StatusInList(c.Writer.Status(), []int{http.StatusOK, http.StatusCreated}) {
|
||||
log.Print("committing transactions")
|
||||
if err := txHandle.Commit().Error; err != nil {
|
||||
log.Print("transaction commit error: ", err)
|
||||
} else {
|
||||
log.Print("rollback transaction due to status code: ", c.Writer.Status())
|
||||
txHandle.Rollback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
internal/models/auth.go
Normal file
29
internal/models/auth.go
Normal file
@ -0,0 +1,29 @@
|
||||
package models
|
||||
|
||||
type LoginRequest struct {
|
||||
Username string `json:"user_name" example:"admin0"`
|
||||
Password string `json:"password" example:"testme"`
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
User User `json:"user"`
|
||||
Token string `json:"token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE3MDI3MTMwMjcsInN1"`
|
||||
RefreshToken string `json:"refresh_token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE3MDc4OTcwMjcs"`
|
||||
}
|
||||
|
||||
type RegisterRequest struct {
|
||||
FirstName string `json:"first_name" example:"길순"`
|
||||
LastName string `json:"last_name" example:"홍"`
|
||||
Username string `json:"user_name" example:"gilsoon"`
|
||||
Password string `json:"password" example:"StrongPass!@#$"`
|
||||
Gender string `json:"gender" example:"F"`
|
||||
UserRole string `json:"user_role" example:"member"`
|
||||
Phone string `json:"phone_cs" example:"01012345678"`
|
||||
Image string `json:"upload_image" example:""`
|
||||
}
|
||||
|
||||
type RegisterResponse struct {
|
||||
User User `json:"user"`
|
||||
Token string `json:"token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE3MDI3MTMwMjcsInN1"`
|
||||
RefreshToken string `json:"refresh_token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE3MDc4OTcwMjcs"`
|
||||
}
|
57
internal/models/center.go
Normal file
57
internal/models/center.go
Normal file
@ -0,0 +1,57 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// CREATE TABLE `Centers` (
|
||||
// `id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
// `guid_id` varchar(36) DEFAULT '',
|
||||
// `center_title` varchar(50) DEFAULT '' COMMENT '강동런스팀로봇코딩학원',
|
||||
// `center_name` varchar(50) DEFAULT '' COMMENT 'learnsteam_kd',
|
||||
// `owner_id` bigint(20) DEFAULT 0,
|
||||
// `content_page` text DEFAULT '' COMMENT '학원상세페이지, html/마크다운/text',
|
||||
// `company_info` text DEFAULT '' COMMENT '사업자정보-json\r\n기타 정보 추가 가능\r\n\r\n{\r\n "company_ceo": "대표자이름",\r\n "company_code": "사업자번호",\r\n "company_phone": "대표전화번호",\r\n "company_email": "대표전자메일",\r\n "company_homepage": "대표홈페이지 url",\r\n "company_logo": "로고이미지 url",\r\n "company_cover_image": "대표 이미지", \r\n}',
|
||||
// `memo` varchar(256) DEFAULT '',
|
||||
// `created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
// `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
// `status` varchar(10) DEFAULT NULL,
|
||||
// PRIMARY KEY (`id`)
|
||||
// ) ENGINE=InnoDB AUTO_INCREMENT=1000005 DEFAULT CHARSET=utf8mb4 COMMENT='Centers의 이미지/영상은 Links에서 관리됨. ';
|
||||
|
||||
type Center struct {
|
||||
ID int64 `json:"id" db:"id" example:"100001" gorm:"column:id;primary_key;"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6" gorm:"column:guid_id;size:255;index;"`
|
||||
Title string `json:"center_title" db:"center_title" example:"강동런스팀로봇코딩학원" gorm:"column:center_title;size:50;index;"`
|
||||
Name string `json:"center_name" db:"center_name" example:"learnsteam_kd" gorm:"column:center_name;size:50;index;"`
|
||||
OwnerID int64 `json:"owner_id" db:"owner_id" example:"100001" gorm:"column:owner_id;index;"`
|
||||
Content string `json:"content_page" db:"content_page" example:"학원상세페이지, html/마크다운/text" gorm:"column:content_page;size:2048;"`
|
||||
Info string `json:"company_info" db:"company_info" example:"사업자정보-json 기타 정보 추가 가능" gorm:"column:company_info;size:2048;"`
|
||||
Memo string `json:"memo" db:"memo" example:"메모" gorm:"column:memo;size:1024;"`
|
||||
Status string `json:"status" db:"status" example:"on" gorm:"column:status;size:10;index;"`
|
||||
UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"`
|
||||
CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (Center) TableName() string {
|
||||
return "Centers"
|
||||
}
|
||||
|
||||
type CenterRequest struct {
|
||||
Title string `json:"center_title" example:"강동런스팀로봇코딩학원"`
|
||||
Name string `json:"center_name" example:"learnsteam_kd"`
|
||||
OwnerID int64 `json:"owner_id" example:"100001"`
|
||||
Content string `json:"content_page" example:"학원상세페이지, html/마크다운/text"`
|
||||
Info string `json:"company_info" example:"사업자정보-json 기타 정보 추가 가능"`
|
||||
Memo string `json:"memo" example:"메모"`
|
||||
Status string `json:"status" example:"on"`
|
||||
}
|
||||
|
||||
type CenterListResponse struct {
|
||||
Data []Center `json:"data"`
|
||||
Total int64 `json:"total" example:"5"`
|
||||
Page int `json:"page" example:"1"`
|
||||
TotalPage int64 `json:"totalPage" example:"1"`
|
||||
PageSize int `json:"pageSize" example:"10"`
|
||||
}
|
78
internal/models/quiz.go
Normal file
78
internal/models/quiz.go
Normal file
@ -0,0 +1,78 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// 문항 json,
|
||||
// option1~4는 구분이름일 뿐, 실제로는 셔플되어서 반환됨.
|
||||
/*
|
||||
{
|
||||
"option1": {"content": "markdown 문서로 작성됨", "is_answer": false},
|
||||
"option2": {"content": "markdown 문서로 작성됨", "is_answer": false},
|
||||
"option3": {"content": "markdown 문서로 작성됨", "is_answer": false},
|
||||
"option4": {"content": "markdown 문서로 작성됨", "is_answer": true},
|
||||
"hint": "markdown문서로 작성됨",
|
||||
"score": 10
|
||||
}
|
||||
*/
|
||||
|
||||
type Quiz struct {
|
||||
ID int64 `json:"id" db:"id" example:"1000001" gorm:"column:id;primary_key;"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6" gorm:"column:guid_id;size:255;index;"`
|
||||
CenterID int64 `json:"center_id" db:"center_id" example:"100001" gorm:"column:center_id;index;"`
|
||||
QuizPaperID int64 `json:"quiz_paper_id" db:"quiz_paper_id" example:"100001" gorm:"column:quiz_paper_id;index;"`
|
||||
No int `json:"vol_no" db:"vol_no" example:"5" gorm:"column:vol_no;index;"`
|
||||
QuestionType string `json:"question_type" db:"question_type" example:"choice" gorm:"column:question_type;size:10;index;"`
|
||||
Question string `json:"question" db:"question" example:"퀴즈 질문입니다." gorm:"column:question;size:512;"`
|
||||
Content datatypes.JSON `json:"content" db:"content" gorm:"column:content;"`
|
||||
Answer datatypes.JSON `json:"answer" db:"answer" gorm:"column:answer;"`
|
||||
UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"`
|
||||
CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (Quiz) TableName() string {
|
||||
return "Quizs"
|
||||
}
|
||||
|
||||
type QuizRequest struct {
|
||||
QuizPaperID int64 `json:"quiz_paper_id" example:"1000001"`
|
||||
CenterID int64 `json:"center_id" example:"1000001"`
|
||||
No int `json:"vol_no" example:"1"`
|
||||
QuestionType string `json:"question_type" example:"choice"`
|
||||
Question string `json:"question" example:"질문입니다."`
|
||||
Content QuizContent `json:"content"`
|
||||
Answer []string `json:"answer" example:"option1,option2"`
|
||||
}
|
||||
|
||||
type QuizResponse struct {
|
||||
ID int64 `json:"id" example:"1000001"`
|
||||
QuizPaperID int64 `json:"quiz_paper_id" example:"1000001"`
|
||||
No int `json:"vol_no" example:"5"`
|
||||
QuestionType string `json:"question_type" example:"check"`
|
||||
Question string `json:"question" example:"퀴즈 질문입니다."`
|
||||
Content QuizContent `json:"content"`
|
||||
Answer []string `json:"answer" example:"option1,option2"`
|
||||
}
|
||||
|
||||
type QuizListResponse struct {
|
||||
Data []Quiz `json:"data"`
|
||||
Total int64 `json:"total" example:"5"`
|
||||
Page int `json:"page" example:"1"`
|
||||
TotalPage int64 `json:"totalPage" example:"1"`
|
||||
PageSize int `json:"pageSize" example:"10"`
|
||||
}
|
||||
|
||||
type QuizContent struct {
|
||||
Option1 string `json:"option1" example:"markdown 문서로 작성됨"`
|
||||
Option2 string `json:"option2" example:"markdown 문서로 작성됨"`
|
||||
Option3 string `json:"option3" example:"markdown 문서로 작성됨"`
|
||||
Option4 string `json:"option4" example:"markdown 문서로 작성됨"`
|
||||
Hint string `json:"hint" example:"markdown문서로 작성됨"`
|
||||
}
|
||||
|
||||
type QuizAnswer struct {
|
||||
}
|
82
internal/models/quizpaper.go
Normal file
82
internal/models/quizpaper.go
Normal file
@ -0,0 +1,82 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// CREATE TABLE `QuizPapers` (
|
||||
// `id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
// `guid_id` char(36) NOT NULL DEFAULT '0',
|
||||
// `center_id` bigint(20) NOT NULL DEFAULT 0,
|
||||
// `manager_id` bigint(20) NOT NULL DEFAULT 0,
|
||||
// `title` varchar(256) NOT NULL DEFAULT '' COMMENT '퀴즈시트 제목',
|
||||
// `status` varchar(10) NOT NULL DEFAULT '0' COMMENT 'on/off',
|
||||
// `content` text NOT NULL DEFAULT '' COMMENT 'markdown 문서',
|
||||
// `tags` varchar(256) NOT NULL DEFAULT '' COMMENT '출력,hello world,for반복문...',
|
||||
// `category` varchar(256) NOT NULL DEFAULT '파이썬기본',
|
||||
// `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
// `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
// PRIMARY KEY (`id`) USING BTREE,
|
||||
// KEY `guid_id` (`guid_id`) USING BTREE,
|
||||
// KEY `center_id` (`center_id`) USING BTREE,
|
||||
// KEY `manager_id` (`manager_id`) USING BTREE
|
||||
// ) ENGINE=InnoDB AUTO_INCREMENT=10000001 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='퀴즈시험지 관리 테이블\r\n\r\n';
|
||||
|
||||
type QuizPaper struct {
|
||||
ID int64 `json:"id" db:"id" example:"100001" gorm:"column:id;primary_key;"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"ef74c59a-c707-4162-a52b-455906c81ec1" gorm:"column:guid_id;size:255;index;"`
|
||||
CenterID int64 `json:"center_id" db:"center_id" example:"100001" gorm:"column:center_id;index;"`
|
||||
ManagerID int64 `json:"manager_id" db:"manager_id" example:"100001" gorm:"column:manager_id;index;"`
|
||||
Title string `json:"title" db:"title" example:"퀴즈 시트 제목" gorm:"column:title;size:255;index;"`
|
||||
Content string `json:"content" db:"content" example:"퀴즈 시트 설명" gorm:"column:content;size:512;"`
|
||||
Category string `json:"category" db:"category" example:"파이썬기본" gorm:"column:title;size:255;"`
|
||||
Tag datatypes.JSON `json:"tag" db:"tag" gorm:"column:tag;"`
|
||||
Status string `json:"status" example:"on" gorm:"column:status;size:10;index;"`
|
||||
UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"`
|
||||
CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (QuizPaper) TableName() string {
|
||||
return "QuizPapers"
|
||||
}
|
||||
|
||||
type QuizPaperRequest struct {
|
||||
CenterID int64 `json:"center_id" example:"100001"`
|
||||
Title string `json:"title" example:"퀴즈 시트 제목"`
|
||||
Content string `json:"content" example:"퀴즈 시트 설명"`
|
||||
Category string `json:"category" example:"파이썬기본"`
|
||||
Tag datatypes.JSON `json:"tag"`
|
||||
Status string `json:"status" example:"on"`
|
||||
}
|
||||
|
||||
type QuizPaperResponse struct {
|
||||
ID int64 `json:"id" example:"100001"`
|
||||
CenterID int64 `json:"center_id" example:"100001"`
|
||||
ManagerID int64 `json:"manager_id" example:"100001"`
|
||||
Title string `json:"title" example:"퀴즈 시트 제목"`
|
||||
Content string `json:"content" example:"퀴즈 시트 설명"`
|
||||
Category string `json:"category" example:"파이썬기본"`
|
||||
Tag datatypes.JSON `json:"tag"`
|
||||
Status string `json:"status" example:"on"`
|
||||
}
|
||||
|
||||
type QuizPaperListResponse struct {
|
||||
Data []QuizPaper `json:"data"`
|
||||
Total int64 `json:"total" example:"999"`
|
||||
Page int `json:"page" example:"1"`
|
||||
TotalPage int64 `json:"totalPage" example:"99"`
|
||||
PageSize int `json:"pageSize" example:"10"`
|
||||
}
|
||||
|
||||
type QuizPaperCopyRequest struct {
|
||||
Title string `json:"title" example:"퀴즈 시트 제목"`
|
||||
CenterID int64 `json:"center_id" example:"100002"`
|
||||
}
|
||||
|
||||
type QuizPaperCopyResponse struct {
|
||||
QuizPaper QuizPaper `json:"quiz_paper"`
|
||||
Quiz []Quiz `json:"quiz"`
|
||||
}
|
46
internal/models/token.go
Normal file
46
internal/models/token.go
Normal file
@ -0,0 +1,46 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// CREATE TABLE `UserTokens` (
|
||||
// `id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
// `user_id` bigint(20) DEFAULT 0,
|
||||
// `token` varchar(256) DEFAULT '',
|
||||
// `refresh_token` varchar(256) DEFAULT '',
|
||||
// `status` varchar(3) DEFAULT 'on' COMMENT 'on/off',
|
||||
// `register_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
// `ending_at` timestamp NULL DEFAULT NULL COMMENT '종료날짜',
|
||||
// PRIMARY KEY (`id`) USING BTREE
|
||||
// ) ENGINE=InnoDB AUTO_INCREMENT=1000017 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
type Token struct {
|
||||
ID int64 `json:"-" db:"id" gorm:"primary_key"`
|
||||
UserID int64 `json:"user_id" db:"user_id" gorm:"index;"`
|
||||
Token string `json:"token" db:"token" gorm:"size:255;index;"`
|
||||
RefreshToken string `json:"refresh_token" db:"refresh_token" gorm:"size:255;index;"`
|
||||
|
||||
Status string `json:"status" gorm:"size:3;index"`
|
||||
|
||||
RegisterAt time.Time `json:"register_at" db:"register_at"`
|
||||
EndingAt time.Time `json:"ending_at" db:"ending_at"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (Token) TableName() string {
|
||||
return "UserTokens"
|
||||
}
|
||||
|
||||
type RefreshTokenRequest struct {
|
||||
RefreshToken string `json:"refresh_token" binding:"required"`
|
||||
}
|
||||
|
||||
type TokenResponse struct {
|
||||
Token string `json:"token"`
|
||||
TokenBody TokenBody `json:"tokenBody"`
|
||||
}
|
||||
|
||||
type TokenBody struct {
|
||||
ExpireAt time.Time `json:"tokenExpiredDate"`
|
||||
TokenIdx int `json:"tokenIdx"`
|
||||
TokenType int `json:"tokenType"`
|
||||
}
|
52
internal/models/user.go
Normal file
52
internal/models/user.go
Normal file
@ -0,0 +1,52 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// CREATE TABLE `Users` (
|
||||
// `id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
// `guid_id` longtext DEFAULT NULL,
|
||||
// `first_name` longtext DEFAULT NULL,
|
||||
// `last_name` longtext DEFAULT NULL,
|
||||
// `user_name` longtext DEFAULT NULL,
|
||||
// `password` longtext DEFAULT NULL,
|
||||
// `gender` char(1) DEFAULT 'M' COMMENT 'M(남)/F(여)',
|
||||
// `user_role` longtext DEFAULT NULL,
|
||||
// `memo_cs` longtext DEFAULT NULL,
|
||||
// `register_at` datetime(3) DEFAULT NULL,
|
||||
// `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() COMMENT '업데이트될때마다 자동저장',
|
||||
// `phone_cs` longtext DEFAULT NULL,
|
||||
// `upload_image` longtext DEFAULT NULL,
|
||||
// PRIMARY KEY (`id`) USING BTREE,
|
||||
// KEY `guid_id` (`guid_id`(768)),
|
||||
// KEY `first_name` (`first_name`(768)),
|
||||
// KEY `last_name` (`last_name`(768)),
|
||||
// KEY `user_name` (`user_name`(768))
|
||||
// ) ENGINE=InnoDB AUTO_INCREMENT=1000023 DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
type User struct {
|
||||
ID int64 `json:"id" db:"id" example:"100001" gorm:"column:id;primary_key;"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"137c1683-2ad6-4201-b256-253828b61c49" gorm:"column:guid_id;size:255;"`
|
||||
FirstName string `json:"first_name" db:"first_name" example:"길순" gorm:"column:first_name;size:255;"`
|
||||
LastName string `json:"last_name" db:"last_name" example:"홍" gorm:"column:last_name;size:255;"`
|
||||
Username string `json:"user_name" db:"user_name" example:"user0" gorm:"column:user_name;size:50;uniqueIndex;"`
|
||||
Password string `json:"-" db:"password" gorm:"column:password;size:255;not null;"`
|
||||
Gender string `json:"gender" db:"gender" example:"F" gorm:"column:gender;size:1;"`
|
||||
UserRole string `json:"user_role" db:"user_role" example:"member" gorm:"column:user_role;size:255;"`
|
||||
Memo string `json:"memo_cs" db:"memo_cs" example:"사용자 메모" gorm:"column:memo_cs;size:255;"`
|
||||
Phone string `json:"phone_cs" db:"phone_cs" example:"010-1234-5678" gorm:"column:phone_cs;size:255;"`
|
||||
Image string `json:"upload_image" db:"upload_image" example:"image_url" gorm:"column:upload_image;size:255;"`
|
||||
RegisterAt time.Time `json:"register_at" db:"regiser_at" gorm:"column:register_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (User) TableName() string {
|
||||
return "Users"
|
||||
}
|
||||
|
||||
type UserListResponse struct {
|
||||
Data []User `json:"data"`
|
||||
Total int64 `json:"total" example:"90"`
|
||||
Page int `json:"page" example:"1"`
|
||||
TotalPage int64 `json:"totalPage" example:"9"`
|
||||
PageSize int `json:"pageSize" example:"10"`
|
||||
}
|
68
internal/models/userquiz.go
Normal file
68
internal/models/userquiz.go
Normal file
@ -0,0 +1,68 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type UserQuiz struct {
|
||||
ID int64 `json:"id" db:"id" example:"1000001" gorm:"column:id;primary_key;"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6" gorm:"column:guid_id;size:255;index;"`
|
||||
CenterID int64 `json:"center_id" db:"center_id" example:"100001" gorm:"column:center_id;index;"`
|
||||
UserQuizPaperID int64 `json:"user_quiz_paper_id" db:"user_quiz_paper_id" example:"1000001" gorm:"column:user_quiz_paper_id;index;"`
|
||||
UserID int64 `json:"user_id" db:"user_id" example:"1000001" gorm:"column:user_id;index;"`
|
||||
No int `json:"vol_no" db:"vol_no" example:"5" gorm:"column:vol_no;index;"`
|
||||
QuestionType string `json:"question_type" db:"question_type" example:"choice" gorm:"column:question_type;size:10;index;"`
|
||||
Question string `json:"question" db:"question" example:"퀴즈 질문입니다." gorm:"column:question;size:512;"`
|
||||
Content datatypes.JSON `json:"content" db:"content" gorm:"column:content;"`
|
||||
Answer datatypes.JSON `json:"answer,omitempty" db:"answer" gorm:"column:answer;default:'[]';"`
|
||||
Status string `json:"status" db:"status" example:"waiting" gorm:"column:status;size:10;index;"`
|
||||
Result string `json:"result" db:"result" example:"success" gorm:"column:result;size:10;index;"`
|
||||
Score float32 `json:"score" db:"score" example:"10" gorm:"column:score;"`
|
||||
UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"`
|
||||
CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (UserQuiz) TableName() string {
|
||||
return "UserQuizs"
|
||||
}
|
||||
|
||||
type UserQuizRequest struct {
|
||||
CenterID int64 `json:"center_id" example:"1000001"`
|
||||
UserQuizPaperID int64 `json:"quiz_paper_id" example:"1000001"`
|
||||
UserID int64 `json:"user_id" example:"1000001"`
|
||||
No int `json:"vol_no" example:"1"`
|
||||
QuestionType string `json:"question_type" example:"choice"`
|
||||
Question string `json:"question" example:"질문입니다."`
|
||||
Content QuizContent `json:"content"`
|
||||
Answer []string `json:"answer" example:"option1,option2"`
|
||||
Status string `json:"status" example:"waiting"`
|
||||
Result string `json:"result" example:"success"`
|
||||
Score float32 `json:"score" example:"10"`
|
||||
}
|
||||
|
||||
type UserQuizResponse struct {
|
||||
ID int64 `json:"id" example:"1000001"`
|
||||
GUID string `json:"guid_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6"`
|
||||
CenterD string `json:"center_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6"`
|
||||
UserQuizPaperID int64 `json:"user_quiz_paper_id" example:"1000001"`
|
||||
UserID int64 `json:"user_id" example:"1000001"`
|
||||
No int `json:"vol_no" example:"5"`
|
||||
QuestionType string `json:"question_type" example:"check"`
|
||||
Question string `json:"question" example:"퀴즈 질문입니다."`
|
||||
Content QuizContent `json:"content"`
|
||||
Answer []string `json:"answer" example:"option1,option2"`
|
||||
Status string `json:"status" example:"waiting"`
|
||||
Result string `json:"result" example:"success"`
|
||||
Score float32 `json:"score" example:"10"`
|
||||
}
|
||||
|
||||
type UserQuizListResponse struct {
|
||||
Data []UserQuizResponse `json:"data"`
|
||||
Total int64 `json:"total" example:"5"`
|
||||
Page int `json:"page" example:"1"`
|
||||
TotalPage int64 `json:"totalPage" example:"1"`
|
||||
PageSize int `json:"pageSize" example:"10"`
|
||||
}
|
91
internal/models/userquizpaper.go
Normal file
91
internal/models/userquizpaper.go
Normal file
@ -0,0 +1,91 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// CREATE TABLE `UserQuizPapers` (
|
||||
// `id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
// `guid_id` char(36) NOT NULL DEFAULT '0',
|
||||
// `center_id` bigint(20) NOT NULL DEFAULT 0,
|
||||
// `quiz_paper_id` bigint(20) NOT NULL DEFAULT 0,
|
||||
// `status` varchar(10) NOT NULL DEFAULT '0' COMMENT '매칭된 학생퀴즈시험지 상태: \r\nwaiting(대기)/processing(시험진행중)/abort(취소)/marking(채점중)/done(완료) ',
|
||||
// `user_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '매칭된 학생',
|
||||
// `user_score` float NOT NULL DEFAULT 5 COMMENT '10',
|
||||
// `total_score` float NOT NULL DEFAULT 100 COMMENT '100.0, 5.0',
|
||||
// `start_at` timestamp NULL DEFAULT NULL COMMENT '학생시험시작시각',
|
||||
// `done_at` timestamp NULL DEFAULT NULL COMMENT '학생시험종료시각',
|
||||
// `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
// `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
// PRIMARY KEY (`id`) USING BTREE,
|
||||
// KEY `guid_id` (`guid_id`) USING BTREE,
|
||||
// KEY `center_id` (`center_id`) USING BTREE,
|
||||
// KEY `user_id` (`user_id`),
|
||||
// KEY `manager_id` (`quiz_paper_id`) USING BTREE
|
||||
// ) ENGINE=InnoDB AUTO_INCREMENT=10000001 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='학생퀴즈시험지 매칭\r\n';
|
||||
|
||||
type UserQuizPaper struct {
|
||||
ID int64 `json:"id" db:"id" example:"1000015" gorm:"column:id;primary_key;"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"7f9329f5-2e36-4638-92d2-73064b7291a4" gorm:"column:guid_id;size:255;uniqueIndex"`
|
||||
CenterID int64 `json:"center_id" db:"center_id" example:"1000015" gorm:"column:center_id;index;"`
|
||||
QuizPaperID int64 `json:"quiz_paper_id" db:"quiz_paper_id" example:"1000001" gorm:"column:quiz_paper_id;index;"`
|
||||
UserID int64 `json:"user_id" db:"user_id" example:"1000002" gorm:"column:user_id;index;"`
|
||||
UserScore float32 `json:"user_score" db:"user_score" example:"5" gorm:"column:user_score;"`
|
||||
TotalScore float32 `json:"total_score" db:"total_score" example:"100" gorm:"column:total_score;"`
|
||||
Status string `json:"status" example:"wating" gorm:"column:status;size:10;index;"`
|
||||
StartAt *time.Time `json:"start_at" gorm:"column:start_at;index;"`
|
||||
DoneAt *time.Time `json:"done_at" gorm:"column:done_at;index;"`
|
||||
UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"`
|
||||
CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"`
|
||||
}
|
||||
|
||||
// 테이블이름 정의
|
||||
func (UserQuizPaper) TableName() string {
|
||||
return "UserQuizPapers"
|
||||
}
|
||||
|
||||
type UserQuizPaperRequest struct {
|
||||
QuizPaperID int64 `json:"quiz_paper_id" example:"1000002"`
|
||||
Users datatypes.JSON `json:"users"`
|
||||
}
|
||||
|
||||
type UserQuizPaperResponse struct {
|
||||
ID int64 `json:"id" db:"id" example:"1000015"`
|
||||
GUID string `json:"guid_id" db:"guid_id" example:"7f9329f5-2e36-4638-92d2-73064b7291a4"`
|
||||
CenterID int64 `json:"center_id" db:"center_id" example:"1000015"`
|
||||
QuizPaperID int64 `json:"quiz_paper_id" db:"quiz_paper_id" example:"1000001"`
|
||||
UserID int64 `json:"user_id" db:"user_id" example:"1000002"`
|
||||
UserScore float32 `json:"user_score" db:"user_score" example:"5"`
|
||||
TotalScore float32 `json:"total_score" db:"total_score" example:"100"`
|
||||
Status string `json:"status" example:"wating"`
|
||||
StartAt *time.Time `json:"start_at"`
|
||||
DoneAt *time.Time `json:"done_at"`
|
||||
}
|
||||
|
||||
type UserQuizPaperUpdateRequest struct {
|
||||
QuizPaperID int64 `json:"quiz_paper_id" example:"1000002"`
|
||||
UserID int64 `json:"user_id" example:"1000003"`
|
||||
UserScore float32 `json:"user_score" example:"5"`
|
||||
TotalScore float32 `json:"total_score" example:"100"`
|
||||
Status string `json:"status" example:"ready"`
|
||||
StartAt string `json:"start_at,omitempty" example:"2023-11-10T13:10:00+09:00"`
|
||||
DoneAt string `json:"done_at,omitempty" example:"2023-11-10T13:25:00+09:00"`
|
||||
}
|
||||
|
||||
type UserQuizPaperPatchRequest struct {
|
||||
UserScore float32 `json:"user_score" example:"4"`
|
||||
TotalScore float32 `json:"total_score" example:"80"`
|
||||
Status string `json:"status" example:"ready"`
|
||||
StartAt string `json:"start_at,omitempty" example:"2023-11-10T13:10:00+09:00"`
|
||||
DoneAt string `json:"done_at,omitempty" example:"2023-11-10T13:25:00+09:00"`
|
||||
}
|
||||
|
||||
type UserQuizPaperListResponse struct {
|
||||
Data []UserQuizPaper `json:"data"`
|
||||
Total int64 `json:"total" example:"999"`
|
||||
Page int `json:"page" example:"1"`
|
||||
TotalPage int64 `json:"totalPage" example:"99"`
|
||||
PageSize int `json:"pageSize" example:"10"`
|
||||
}
|
89
internal/repositories/center.go
Normal file
89
internal/repositories/center.go
Normal file
@ -0,0 +1,89 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type centerRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewCenterRepository(db *gorm.DB) CenterRepository {
|
||||
return ¢erRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type CenterRepository interface {
|
||||
List(string, int, int) (*[]models.Center, error)
|
||||
Total(string) (int64, error)
|
||||
Find(int64) (*models.Center, error)
|
||||
FindByTitle(string) (*models.Center, error)
|
||||
Create(*models.Center) (*models.Center, error)
|
||||
Update(*models.Center) (*models.Center, error)
|
||||
Delete(int64) error
|
||||
}
|
||||
|
||||
func (r *centerRepository) List(q string, page int, limit int) (*[]models.Center, error) {
|
||||
var centers *[]models.Center
|
||||
var err error
|
||||
offset := limit * (page - 1)
|
||||
fmt.Println("q", q)
|
||||
if q != "" {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("center_title ASC").Where("center_title LIKE ? OR center_name LIKE ?", "%"+q+"%", "%"+q+"%").Find(¢ers).Error
|
||||
} else {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("center_title ASC").Find(¢ers).Error
|
||||
}
|
||||
return centers, err
|
||||
}
|
||||
|
||||
func (r *centerRepository) Total(q string) (int64, error) {
|
||||
var total int64
|
||||
var err error
|
||||
if q != "" {
|
||||
err = r.DB.Model(&models.Center{}).Where("center_title LIKE ? OR center_name LIKE ?", "%"+q+"%", "%"+q+"%").Count(&total).Error
|
||||
} else {
|
||||
err = r.DB.Model(&models.Center{}).Count(&total).Error
|
||||
}
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *centerRepository) Find(id int64) (*models.Center, error) {
|
||||
var center *models.Center
|
||||
err := r.DB.Where("id = ?", id).First(¢er).Error
|
||||
return center, err
|
||||
}
|
||||
|
||||
func (r *centerRepository) FindByTitle(center_title string) (*models.Center, error) {
|
||||
var center *models.Center
|
||||
err := r.DB.Where("center_title = ?", center_title).First(¢er).Error
|
||||
return center, err
|
||||
}
|
||||
|
||||
func (r *centerRepository) Create(center *models.Center) (*models.Center, error) {
|
||||
err := r.DB.Create(¢er).Error
|
||||
return center, err
|
||||
}
|
||||
|
||||
func (r *centerRepository) Update(center *models.Center) (*models.Center, error) {
|
||||
var row *models.Center
|
||||
if err := r.DB.Where("id=?", center.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(¢er).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *centerRepository) Delete(id int64) error {
|
||||
var center *models.Center
|
||||
if err := r.DB.Where("id=?", id).First(¢er).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(¢er).Error
|
||||
return err
|
||||
}
|
81
internal/repositories/quiz.go
Normal file
81
internal/repositories/quiz.go
Normal file
@ -0,0 +1,81 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type quizRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewQuizRepository(db *gorm.DB) QuizRepository {
|
||||
return &quizRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type QuizRepository interface {
|
||||
List(int64, int, int) (*[]models.Quiz, error)
|
||||
Total(int64) (int64, error)
|
||||
|
||||
Find(int64) (*models.Quiz, error)
|
||||
Create(*models.Quiz) (*models.Quiz, error)
|
||||
Update(*models.Quiz) (*models.Quiz, error)
|
||||
Delete(int64) error
|
||||
}
|
||||
|
||||
func (r *quizRepository) List(quiz_paper_id int64, page int, limit int) (*[]models.Quiz, error) {
|
||||
var quizzes *[]models.Quiz
|
||||
var err error
|
||||
offset := limit * (page - 1)
|
||||
if quiz_paper_id > 0 {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("vol_no ASC").Where("quiz_paper_id = ?", quiz_paper_id).Find(&quizzes).Error
|
||||
} else {
|
||||
err = r.DB.Offset(offset).Limit(limit).Find(&quizzes).Error
|
||||
}
|
||||
return quizzes, err
|
||||
}
|
||||
|
||||
func (r *quizRepository) Total(quiz_paper_id int64) (int64, error) {
|
||||
var total int64
|
||||
var err error
|
||||
if quiz_paper_id > 0 {
|
||||
err = r.DB.Model(&models.Quiz{}).Where("quiz_paper_id = ?", quiz_paper_id).Count(&total).Error
|
||||
} else {
|
||||
err = r.DB.Model(&models.Quiz{}).Count(&total).Error
|
||||
}
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *quizRepository) Find(id int64) (*models.Quiz, error) {
|
||||
var quiz *models.Quiz
|
||||
err := r.DB.Where("id = ?", id).First(&quiz).Error
|
||||
return quiz, err
|
||||
}
|
||||
|
||||
func (r *quizRepository) Create(quiz *models.Quiz) (*models.Quiz, error) {
|
||||
err := r.DB.Create(&quiz).Error
|
||||
return quiz, err
|
||||
}
|
||||
|
||||
func (r *quizRepository) Update(quiz *models.Quiz) (*models.Quiz, error) {
|
||||
var row *models.Quiz
|
||||
if err := r.DB.Where("id=?", quiz.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(&quiz).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *quizRepository) Delete(id int64) error {
|
||||
var quiz *models.Quiz
|
||||
if err := r.DB.Where("id=?", id).First(&quiz).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(&quiz).Error
|
||||
return err
|
||||
}
|
90
internal/repositories/quizpaper.go
Normal file
90
internal/repositories/quizpaper.go
Normal file
@ -0,0 +1,90 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type quizPaperRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewQuizPaperRepository(db *gorm.DB) QuizPaperRepository {
|
||||
return &quizPaperRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type QuizPaperRepository interface {
|
||||
List(string, string, int, int) (*[]models.QuizPaper, error)
|
||||
Total(string, string) (int64, error)
|
||||
|
||||
Find(int64) (*models.QuizPaper, error)
|
||||
Create(*models.QuizPaper) (*models.QuizPaper, error)
|
||||
Update(*models.QuizPaper) (*models.QuizPaper, error)
|
||||
Delete(string) error
|
||||
}
|
||||
|
||||
func (r *quizPaperRepository) List(q string, tag string, page int, limit int) (*[]models.QuizPaper, error) {
|
||||
var quizPapers *[]models.QuizPaper
|
||||
var err error
|
||||
offset := limit * (page - 1)
|
||||
fmt.Println("q", q)
|
||||
if q != "" {
|
||||
fmt.Println(" 1 q", q)
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("created_at DESC").Where("title LIKE ? OR category LIKE ? OR tag LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%").Find(&quizPapers).Error
|
||||
} else if tag != "" {
|
||||
fmt.Println(" tag", tag)
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("created_at DESC").Where("tag LIKE ?", "%"+tag+"%").Find(&quizPapers).Error
|
||||
} else {
|
||||
fmt.Println(" query")
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("created_at DESC").Find(&quizPapers).Error
|
||||
}
|
||||
return quizPapers, err
|
||||
}
|
||||
|
||||
func (r *quizPaperRepository) Total(q string, tag string) (int64, error) {
|
||||
var total int64
|
||||
var err error
|
||||
if q != "" {
|
||||
err = r.DB.Model(&models.QuizPaper{}).Where("title LIKE ? OR category LIKE ? OR tag LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%").Count(&total).Error
|
||||
} else if tag != "" {
|
||||
err = r.DB.Model(&models.QuizPaper{}).Where("tag LIKE ?", "%"+tag+"%").Count(&total).Error
|
||||
} else {
|
||||
err = r.DB.Model(&models.QuizPaper{}).Count(&total).Error
|
||||
}
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *quizPaperRepository) Find(id int64) (*models.QuizPaper, error) {
|
||||
var quizPaper *models.QuizPaper
|
||||
err := r.DB.Where("id = ?", id).First(&quizPaper).Error
|
||||
return quizPaper, err
|
||||
}
|
||||
|
||||
func (r *quizPaperRepository) Create(quizPaper *models.QuizPaper) (*models.QuizPaper, error) {
|
||||
err := r.DB.Create(&quizPaper).Error
|
||||
return quizPaper, err
|
||||
}
|
||||
|
||||
func (r *quizPaperRepository) Update(quizPaper *models.QuizPaper) (*models.QuizPaper, error) {
|
||||
var row *models.QuizPaper
|
||||
if err := r.DB.Where("id=?", quizPaper.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(&quizPaper).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *quizPaperRepository) Delete(id string) error {
|
||||
var quizPaper *models.QuizPaper
|
||||
if err := r.DB.Where("id=?", id).First(&quizPaper).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(&quizPaper).Error
|
||||
return err
|
||||
}
|
79
internal/repositories/token.go
Normal file
79
internal/repositories/token.go
Normal file
@ -0,0 +1,79 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
config "learnsteam/cslms-api/configs"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type tokenRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewTokenRepository(db *gorm.DB) TokenRepository {
|
||||
return &tokenRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type TokenRepository interface {
|
||||
Generate(int64, int64, string) (string, error)
|
||||
Find(int64) (*models.Token, error)
|
||||
FindByRefreshToken(int64, string) (*models.Token, error)
|
||||
Create(*models.Token) (*models.Token, error)
|
||||
Update(*models.Token) (*models.Token, error)
|
||||
Delete(string) error
|
||||
}
|
||||
|
||||
func (s *tokenRepository) Generate(user_id int64, expire_at int64, role string) (string, error) {
|
||||
fmt.Println(user_id, role)
|
||||
claims := jwt.MapClaims{}
|
||||
claims["authorized"] = true
|
||||
claims["sub"] = user_id
|
||||
claims["exp"] = expire_at
|
||||
claims["role"] = role
|
||||
at := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
token, err := at.SignedString([]byte(config.SECRET_KEY))
|
||||
|
||||
fmt.Println(token)
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (r *tokenRepository) Find(id int64) (*models.Token, error) {
|
||||
var token *models.Token
|
||||
err := r.DB.Where("id = ?", id).First(&token).Error
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (r *tokenRepository) FindByRefreshToken(user_id int64, refreshToken string) (*models.Token, error) {
|
||||
var token *models.Token
|
||||
err := r.DB.Where("user_id = ? AND refresh_token = ?", user_id, refreshToken).First(&token).Error
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (r *tokenRepository) Create(token *models.Token) (*models.Token, error) {
|
||||
err := r.DB.Create(&token).Error
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (r *tokenRepository) Update(token *models.Token) (*models.Token, error) {
|
||||
var row *models.Token
|
||||
if err := r.DB.Where("id=?", token.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(&token).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *tokenRepository) Delete(id string) error {
|
||||
var token *models.Token
|
||||
if err := r.DB.Where("id=?", id).First(&token).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(&token).Error
|
||||
return err
|
||||
}
|
90
internal/repositories/user.go
Normal file
90
internal/repositories/user.go
Normal file
@ -0,0 +1,90 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type userRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserRepository(db *gorm.DB) UserRepository {
|
||||
return &userRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type UserRepository interface {
|
||||
List(string, int, int) (*[]models.User, error)
|
||||
Total(string) (int64, error)
|
||||
Find(int64) (*models.User, error)
|
||||
FindByUsername(string) (*models.User, error)
|
||||
Create(*models.User) (*models.User, error)
|
||||
Update(*models.User) (*models.User, error)
|
||||
Delete(string) error
|
||||
}
|
||||
|
||||
func (r *userRepository) List(q string, page int, limit int) (*[]models.User, error) {
|
||||
var users *[]models.User
|
||||
var err error
|
||||
offset := limit * (page - 1)
|
||||
fmt.Println("q", q)
|
||||
if q != "" {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("last_name ASC, first_name ASC").Where("user_role = ?", "member").Where("name LIKE ? OR user_name LIKE ?", "%"+q+"%", "%"+q+"%").Find(&users).Error
|
||||
} else {
|
||||
fmt.Println(" query")
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("last_name ASC, first_name ASC").Where("user_role = ?", "member").Find(&users).Error
|
||||
}
|
||||
return users, err
|
||||
}
|
||||
|
||||
func (r *userRepository) Total(q string) (int64, error) {
|
||||
var total int64
|
||||
var err error
|
||||
if q != "" {
|
||||
err = r.DB.Model(&models.User{}).Where("user_role = ?", "member").Where("name LIKE ? OR user_name LIKE ?", "%"+q+"%", "%"+q+"%").Count(&total).Error
|
||||
} else {
|
||||
err = r.DB.Model(&models.User{}).Where("user_role = ?", "member").Count(&total).Error
|
||||
}
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *userRepository) Find(id int64) (*models.User, error) {
|
||||
var user *models.User
|
||||
err := r.DB.Where("id = ?", id).First(&user).Error
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (r *userRepository) FindByUsername(username string) (*models.User, error) {
|
||||
var user *models.User
|
||||
err := r.DB.Where("user_name = ?", username).First(&user).Error
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (r *userRepository) Create(user *models.User) (*models.User, error) {
|
||||
err := r.DB.Create(&user).Error
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (r *userRepository) Update(user *models.User) (*models.User, error) {
|
||||
var row *models.User
|
||||
if err := r.DB.Where("id=?", user.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(&user).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *userRepository) Delete(id string) error {
|
||||
var user *models.User
|
||||
if err := r.DB.Where("id=?", id).First(&user).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(&user).Error
|
||||
return err
|
||||
}
|
89
internal/repositories/userquiz.go
Normal file
89
internal/repositories/userquiz.go
Normal file
@ -0,0 +1,89 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type userQuizRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserQuizRepository(db *gorm.DB) UserQuizRepository {
|
||||
return &userQuizRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type UserQuizRepository interface {
|
||||
List(int64, int, int) (*[]models.UserQuiz, error)
|
||||
Total(int64) (int64, error)
|
||||
|
||||
Find(int64) (*models.UserQuiz, error)
|
||||
Create(*models.UserQuiz) (*models.UserQuiz, error)
|
||||
Insert([]models.UserQuiz) ([]models.UserQuiz, error)
|
||||
Update(*models.UserQuiz) (*models.UserQuiz, error)
|
||||
Delete(int64) error
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) List(user_quiz_paper_id int64, page int, limit int) (*[]models.UserQuiz, error) {
|
||||
var rows *[]models.UserQuiz
|
||||
var err error
|
||||
offset := limit * (page - 1)
|
||||
if user_quiz_paper_id > 0 {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("vol_no ASC").Where("user_quiz_paper_id = ?", user_quiz_paper_id).Find(&rows).Error
|
||||
} else {
|
||||
err = r.DB.Offset(offset).Limit(limit).Find(&rows).Error
|
||||
}
|
||||
return rows, err
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) Total(user_quiz_paper_id int64) (int64, error) {
|
||||
var total int64
|
||||
var err error
|
||||
if user_quiz_paper_id > 0 {
|
||||
err = r.DB.Model(&models.UserQuiz{}).Where("user_quiz_paper_id = ?", user_quiz_paper_id).Count(&total).Error
|
||||
} else {
|
||||
err = r.DB.Model(&models.UserQuiz{}).Count(&total).Error
|
||||
}
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) Find(id int64) (*models.UserQuiz, error) {
|
||||
var row *models.UserQuiz
|
||||
err := r.DB.Where("id = ?", id).First(&row).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) Create(row *models.UserQuiz) (*models.UserQuiz, error) {
|
||||
err := r.DB.Create(&row).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) Insert(items []models.UserQuiz) ([]models.UserQuiz, error) {
|
||||
fmt.Println(items)
|
||||
err := r.DB.Create(&items).Error
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) Update(quiz *models.UserQuiz) (*models.UserQuiz, error) {
|
||||
var row *models.UserQuiz
|
||||
if err := r.DB.Where("id=?", quiz.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(&quiz).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *userQuizRepository) Delete(id int64) error {
|
||||
var row *models.UserQuiz
|
||||
if err := r.DB.Where("id=?", id).First(&row).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(&row).Error
|
||||
return err
|
||||
}
|
87
internal/repositories/userquizpaper.go
Normal file
87
internal/repositories/userquizpaper.go
Normal file
@ -0,0 +1,87 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type userQuizPaperRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserQuizPaperRepository(db *gorm.DB) UserQuizPaperRepository {
|
||||
return &userQuizPaperRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
type UserQuizPaperRepository interface {
|
||||
List(string, int, int) (*[]models.UserQuizPaper, error)
|
||||
Total(string) (int64, error)
|
||||
|
||||
Find(int64) (*models.UserQuizPaper, error)
|
||||
Create(*models.UserQuizPaper) (*models.UserQuizPaper, error)
|
||||
Insert([]models.UserQuizPaper) ([]models.UserQuizPaper, error)
|
||||
Update(*models.UserQuizPaper) (*models.UserQuizPaper, error)
|
||||
Delete(string) error
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) List(q string, page int, limit int) (*[]models.UserQuizPaper, error) {
|
||||
var userQuizPapers *[]models.UserQuizPaper
|
||||
var err error
|
||||
offset := limit * (page - 1)
|
||||
if q != "" {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("created_at DESC").Where("subject LIKE ? OR program LIKE ? OR name LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%").Find(&userQuizPapers).Error
|
||||
} else {
|
||||
err = r.DB.Offset(offset).Limit(limit).Order("created_at DESC").Find(&userQuizPapers).Error
|
||||
}
|
||||
return userQuizPapers, err
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) Total(q string) (int64, error) {
|
||||
var total int64
|
||||
var err error
|
||||
if q != "" {
|
||||
err = r.DB.Model(&models.UserQuizPaper{}).Where("subject LIKE ? OR program LIKE ? OR name LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%").Count(&total).Error
|
||||
} else {
|
||||
err = r.DB.Model(&models.UserQuizPaper{}).Count(&total).Error
|
||||
}
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) Find(id int64) (*models.UserQuizPaper, error) {
|
||||
var userQuizPaper *models.UserQuizPaper
|
||||
err := r.DB.Where("id = ?", id).First(&userQuizPaper).Error
|
||||
return userQuizPaper, err
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) Create(userQuizPaper *models.UserQuizPaper) (*models.UserQuizPaper, error) {
|
||||
err := r.DB.Create(&userQuizPaper).Error
|
||||
return userQuizPaper, err
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) Insert(items []models.UserQuizPaper) ([]models.UserQuizPaper, error) {
|
||||
err := r.DB.Create(&items).Error
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) Update(userQuizPaper *models.UserQuizPaper) (*models.UserQuizPaper, error) {
|
||||
var row *models.UserQuizPaper
|
||||
if err := r.DB.Where("id=?", userQuizPaper.ID).First(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.DB.Model(&row).Select("*").Updates(&userQuizPaper).Error
|
||||
return row, err
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRepository) Delete(id string) error {
|
||||
var userQuizPaper *models.UserQuizPaper
|
||||
if err := r.DB.Where("id=?", id).First(&userQuizPaper).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.DB.Delete(&userQuizPaper).Error
|
||||
return err
|
||||
}
|
53
internal/routers/auth.go
Normal file
53
internal/routers/auth.go
Normal file
@ -0,0 +1,53 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitAuthRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewAuthRouter(db, router)
|
||||
r.SetAuthRouter()
|
||||
}
|
||||
|
||||
type AuthRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type authRouter struct {
|
||||
db *gorm.DB
|
||||
userRepository repositories.UserRepository
|
||||
tokenRepository repositories.TokenRepository
|
||||
service services.AuthService
|
||||
tokenService services.TokenService
|
||||
controller controllers.AuthController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewAuthRouter(db *gorm.DB, router *gin.Engine) *authRouter {
|
||||
userRepository := repositories.NewUserRepository(db)
|
||||
tokenRepository := repositories.NewTokenRepository(db)
|
||||
service := services.NewAuthService(userRepository, tokenRepository)
|
||||
tokenService := services.NewTokenService(tokenRepository)
|
||||
controller := controllers.NewAuthController(service, tokenService)
|
||||
|
||||
return &authRouter{
|
||||
db: db,
|
||||
userRepository: userRepository,
|
||||
tokenRepository: tokenRepository,
|
||||
service: service,
|
||||
tokenService: tokenService,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *authRouter) SetAuthRouter() {
|
||||
group := r.router.Group("/auth")
|
||||
group.POST("login", r.controller.Login)
|
||||
group.POST("register", r.controller.Register)
|
||||
}
|
53
internal/routers/center.go
Normal file
53
internal/routers/center.go
Normal file
@ -0,0 +1,53 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/middleware"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitCenterRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewCenterRouter(db, router)
|
||||
r.SetCenterRouter()
|
||||
}
|
||||
|
||||
type CenterRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type centerRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.CenterRepository
|
||||
service services.CenterService
|
||||
controller controllers.CenterController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewCenterRouter(db *gorm.DB, router *gin.Engine) *centerRouter {
|
||||
repository := repositories.NewCenterRepository(db)
|
||||
tokenRepository := repositories.NewTokenRepository(db)
|
||||
service := services.NewCenterService(repository, tokenRepository)
|
||||
|
||||
tokenService := services.NewTokenService(tokenRepository)
|
||||
controller := controllers.NewCenterController(service, tokenService)
|
||||
|
||||
return ¢erRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
service: service,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *centerRouter) SetCenterRouter() {
|
||||
group := r.router.Group("/center")
|
||||
group.GET("", middleware.Auth("admin"), r.controller.List)
|
||||
group.GET("/:id", middleware.Auth("admin"), r.controller.Find)
|
||||
group.POST("", middleware.Auth("admin"), r.controller.Create)
|
||||
group.PUT("/:id", middleware.Auth("admin"), r.controller.Update)
|
||||
}
|
50
internal/routers/quiz.go
Normal file
50
internal/routers/quiz.go
Normal file
@ -0,0 +1,50 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/middleware"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitQuizRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewQuizRouter(db, router)
|
||||
r.SetQuizRouter()
|
||||
}
|
||||
|
||||
type QuizRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type quizRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.QuizRepository
|
||||
service services.QuizService
|
||||
controller controllers.QuizController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewQuizRouter(db *gorm.DB, router *gin.Engine) *quizRouter {
|
||||
repository := repositories.NewQuizRepository(db)
|
||||
service := services.NewQuizService(repository)
|
||||
controller := controllers.NewQuizController(service)
|
||||
|
||||
return &quizRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
service: service,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *quizRouter) SetQuizRouter() {
|
||||
group := r.router.Group("/quiz")
|
||||
group.GET("", middleware.Auth("admin"), r.controller.List)
|
||||
group.GET("/:id", middleware.Auth("admin"), r.controller.Find)
|
||||
group.POST("", middleware.Auth("admin"), r.controller.Create)
|
||||
group.PUT("/:id", middleware.Auth("admin"), r.controller.Update)
|
||||
}
|
57
internal/routers/quizpaper.go
Normal file
57
internal/routers/quizpaper.go
Normal file
@ -0,0 +1,57 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/middleware"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitQuizPaperRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewQuizPaperRouter(db, router)
|
||||
r.SetQuizPaperRouter()
|
||||
}
|
||||
|
||||
type QuizPaperRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type quizPaperRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.QuizPaperRepository
|
||||
quizRepository repositories.QuizRepository
|
||||
service services.QuizPaperService
|
||||
quizService services.QuizService
|
||||
controller controllers.QuizPaperController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewQuizPaperRouter(db *gorm.DB, router *gin.Engine) *quizPaperRouter {
|
||||
repository := repositories.NewQuizPaperRepository(db)
|
||||
quizRepository := repositories.NewQuizRepository(db)
|
||||
service := services.NewQuizPaperService(repository)
|
||||
quizService := services.NewQuizService(quizRepository)
|
||||
controller := controllers.NewQuizPaperController(service, quizService)
|
||||
|
||||
return &quizPaperRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
quizRepository: quizRepository,
|
||||
service: service,
|
||||
quizService: quizService,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *quizPaperRouter) SetQuizPaperRouter() {
|
||||
group := r.router.Group("/quizpaper")
|
||||
group.GET("", middleware.Auth("admin"), r.controller.List)
|
||||
group.GET("/:id", middleware.Auth("admin"), r.controller.Find)
|
||||
group.POST("", middleware.Auth("admin"), r.controller.Create)
|
||||
group.PUT("/:id", middleware.Auth("admin"), r.controller.Update)
|
||||
group.POST("/:id/copy", middleware.Auth("admin"), r.controller.Copy)
|
||||
}
|
33
internal/routers/router.go
Normal file
33
internal/routers/router.go
Normal file
@ -0,0 +1,33 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/database"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var Router *gin.Engine
|
||||
|
||||
func Init() {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
Router = gin.Default()
|
||||
config := cors.DefaultConfig()
|
||||
config.AllowOrigins = []string{"http://127.0.0.1:3000", "http://localhost:3000", "http://localhost:3030", "https://learnsteam-quiz.jongyeob.com"}
|
||||
config.AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "PATCH"}
|
||||
config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type"}
|
||||
Router.Use(cors.New(config))
|
||||
|
||||
maindb := database.GetDB()
|
||||
|
||||
InitAuthRouter(maindb, Router)
|
||||
InitCenterRouter(maindb, Router)
|
||||
InitQuizPaperRouter(maindb, Router)
|
||||
InitQuizRouter(maindb, Router)
|
||||
InitTokenRouter(maindb, Router)
|
||||
InitUserQuizPaperRouter(maindb, Router)
|
||||
InitUserQuizRouter(maindb, Router)
|
||||
InitUserRouter(maindb, Router)
|
||||
|
||||
InitSwaggerRouter(Router)
|
||||
}
|
37
internal/routers/swagger.go
Normal file
37
internal/routers/swagger.go
Normal file
@ -0,0 +1,37 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
)
|
||||
|
||||
func InitSwaggerRouter(router *gin.Engine) {
|
||||
r := NewSwaggerRouter(router)
|
||||
r.SetSwaggerRouter()
|
||||
}
|
||||
|
||||
type SwaggerRouter interface {
|
||||
SetRouter(router *gin.Engine)
|
||||
}
|
||||
|
||||
type swaggerRouter struct {
|
||||
router *gin.Engine
|
||||
controller controllers.SwaggerController
|
||||
}
|
||||
|
||||
func NewSwaggerRouter(router *gin.Engine) *swaggerRouter {
|
||||
controller := controllers.NewSwaggerController()
|
||||
return &swaggerRouter{
|
||||
router: router,
|
||||
controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *swaggerRouter) SetSwaggerRouter() {
|
||||
group := r.router.Group("/swagger")
|
||||
group.GET("*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
}
|
46
internal/routers/token.go
Normal file
46
internal/routers/token.go
Normal file
@ -0,0 +1,46 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitTokenRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewTokenRouter(db, router)
|
||||
r.SetTokenRouter()
|
||||
}
|
||||
|
||||
type TokenRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type tokenRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.TokenRepository
|
||||
service services.TokenService
|
||||
controller controllers.TokenController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewTokenRouter(db *gorm.DB, router *gin.Engine) *tokenRouter {
|
||||
repository := repositories.NewTokenRepository(db)
|
||||
service := services.NewTokenService(repository)
|
||||
controller := controllers.NewTokenController(service)
|
||||
|
||||
return &tokenRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
service: service,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *tokenRouter) SetTokenRouter() {
|
||||
group := r.router.Group("/token")
|
||||
group.POST("refresh", r.controller.Refresh)
|
||||
}
|
51
internal/routers/user.go
Normal file
51
internal/routers/user.go
Normal file
@ -0,0 +1,51 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/middleware"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitUserRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewUserRouter(db, router)
|
||||
r.SetUserRouter()
|
||||
}
|
||||
|
||||
type UserRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type userRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.UserRepository
|
||||
service services.UserService
|
||||
controller controllers.UserController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewUserRouter(db *gorm.DB, router *gin.Engine) *userRouter {
|
||||
repository := repositories.NewUserRepository(db)
|
||||
tokenRepository := repositories.NewTokenRepository(db)
|
||||
service := services.NewUserService(repository, tokenRepository)
|
||||
|
||||
tokenService := services.NewTokenService(tokenRepository)
|
||||
controller := controllers.NewUserController(service, tokenService)
|
||||
|
||||
return &userRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
service: service,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *userRouter) SetUserRouter() {
|
||||
group := r.router.Group("/user")
|
||||
group.GET("", middleware.Auth("admin"), r.controller.List)
|
||||
group.GET("/:id", middleware.Auth("admin"), r.controller.Find)
|
||||
}
|
53
internal/routers/userquiz.go
Normal file
53
internal/routers/userquiz.go
Normal file
@ -0,0 +1,53 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/middleware"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitUserQuizRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewUserQuizRouter(db, router)
|
||||
r.SetUserQuizRouter()
|
||||
}
|
||||
|
||||
type UserQuizRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type userQuizRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.UserQuizRepository
|
||||
quizRepository repositories.QuizRepository
|
||||
service services.UserQuizService
|
||||
controller controllers.UserQuizController
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewUserQuizRouter(db *gorm.DB, router *gin.Engine) *userQuizRouter {
|
||||
repository := repositories.NewUserQuizRepository(db)
|
||||
quizRepostory := repositories.NewQuizRepository(db)
|
||||
service := services.NewUserQuizService(repository, quizRepostory)
|
||||
controller := controllers.NewUserQuizController(service)
|
||||
|
||||
return &userQuizRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
quizRepository: quizRepostory,
|
||||
service: service,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *userQuizRouter) SetUserQuizRouter() {
|
||||
group := r.router.Group("/userquiz")
|
||||
group.GET("", middleware.Auth("admin"), r.controller.List)
|
||||
group.GET("/:id", middleware.Auth("admin"), r.controller.Find)
|
||||
group.POST("", middleware.Auth("admin"), r.controller.Create)
|
||||
group.PUT("/:id", middleware.Auth("admin"), r.controller.Update)
|
||||
}
|
67
internal/routers/userquizpaper.go
Normal file
67
internal/routers/userquizpaper.go
Normal file
@ -0,0 +1,67 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/controllers"
|
||||
"learnsteam/cslms-api/internal/middleware"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"learnsteam/cslms-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitUserQuizPaperRouter(db *gorm.DB, router *gin.Engine) {
|
||||
r := NewUserQuizPaperRouter(db, router)
|
||||
r.SetUserQuizPaperRouter()
|
||||
}
|
||||
|
||||
type UserQuizPaperRouter interface {
|
||||
SetRouter(db *gorm.DB, router *gin.Engine)
|
||||
}
|
||||
|
||||
type userQuizPaperRouter struct {
|
||||
db *gorm.DB
|
||||
repository repositories.UserQuizPaperRepository
|
||||
service services.UserQuizPaperService
|
||||
controller controllers.UserQuizPaperController
|
||||
// quizPaperRepository repositories.QuizPaperRepository
|
||||
// userRepository repositories.UserRepository
|
||||
|
||||
// quizPaperService services.QuizPaperService
|
||||
// userService services.UserService
|
||||
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func NewUserQuizPaperRouter(db *gorm.DB, router *gin.Engine) *userQuizPaperRouter {
|
||||
repository := repositories.NewUserQuizPaperRepository(db)
|
||||
quizRepository := repositories.NewQuizRepository(db)
|
||||
quizPaperRepository := repositories.NewQuizPaperRepository(db)
|
||||
tokenRepository := repositories.NewTokenRepository(db)
|
||||
userRepository := repositories.NewUserRepository(db)
|
||||
userQuizRepository := repositories.NewUserQuizRepository(db)
|
||||
|
||||
service := services.NewUserQuizPaperService(repository)
|
||||
quizPaperService := services.NewQuizPaperService(quizPaperRepository)
|
||||
userService := services.NewUserService(userRepository, tokenRepository)
|
||||
userQuizService := services.NewUserQuizService(userQuizRepository, quizRepository)
|
||||
|
||||
controller := controllers.NewUserQuizPaperController(service, userService, quizPaperService, userQuizService)
|
||||
|
||||
return &userQuizPaperRouter{
|
||||
db: db,
|
||||
repository: repository,
|
||||
service: service,
|
||||
controller: controller,
|
||||
router: router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *userQuizPaperRouter) SetUserQuizPaperRouter() {
|
||||
group := r.router.Group("/userquizpaper")
|
||||
group.GET("", middleware.Auth("admin"), r.controller.List)
|
||||
group.GET("/:id", middleware.Auth("admin"), r.controller.Find)
|
||||
group.POST("", middleware.Auth("admin"), r.controller.Create)
|
||||
group.PUT("/:id", middleware.Auth("admin"), r.controller.Update)
|
||||
group.PATCH("/:id", middleware.Auth("admin"), r.controller.Patch)
|
||||
}
|
72
internal/services/auth.go
Normal file
72
internal/services/auth.go
Normal file
@ -0,0 +1,72 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type authService struct {
|
||||
userRepository repositories.UserRepository
|
||||
tokenRepository repositories.TokenRepository
|
||||
}
|
||||
|
||||
type AuthService interface {
|
||||
Register(*models.RegisterRequest) (*models.User, error)
|
||||
Login(*models.LoginRequest) (*models.User, error)
|
||||
}
|
||||
|
||||
func NewAuthService(userRepository repositories.UserRepository, tokenRepository repositories.TokenRepository) AuthService {
|
||||
return &authService{
|
||||
userRepository: userRepository,
|
||||
tokenRepository: tokenRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *authService) Register(request *models.RegisterRequest) (*models.User, error) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(request.Password), 10)
|
||||
if err != nil {
|
||||
return nil, errors.New("fail to hash password")
|
||||
}
|
||||
|
||||
// Create the user
|
||||
newUser := models.User{
|
||||
GUID: uuid.NewString(),
|
||||
FirstName: request.FirstName,
|
||||
LastName: request.LastName,
|
||||
Username: request.Username,
|
||||
Password: string(hash),
|
||||
Gender: request.Gender,
|
||||
Phone: request.Phone,
|
||||
UserRole: request.UserRole,
|
||||
Image: request.Image,
|
||||
RegisterAt: time.Now(),
|
||||
}
|
||||
|
||||
fmt.Println(newUser)
|
||||
|
||||
user, err := s.userRepository.Create(&newUser)
|
||||
if err != nil {
|
||||
return nil, errors.New("fail to create user")
|
||||
}
|
||||
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (s *authService) Login(request *models.LoginRequest) (*models.User, error) {
|
||||
user, err := s.userRepository.FindByUsername(request.Username)
|
||||
if err != nil || user == nil {
|
||||
return nil, errors.New("invalid user or password")
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(request.Password))
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid user or password")
|
||||
}
|
||||
return user, nil
|
||||
}
|
64
internal/services/center.go
Normal file
64
internal/services/center.go
Normal file
@ -0,0 +1,64 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
)
|
||||
|
||||
type centerService struct {
|
||||
repository repositories.CenterRepository
|
||||
tokenRepository repositories.TokenRepository
|
||||
}
|
||||
|
||||
type CenterService interface {
|
||||
List(string, int, int) (*[]models.Center, error)
|
||||
Total(string) (int64, error)
|
||||
|
||||
Find(int64) (*models.Center, error)
|
||||
FindByTitle(string) (*models.Center, error)
|
||||
|
||||
Create(*models.Center) (*models.Center, error)
|
||||
Update(*models.Center) (*models.Center, error)
|
||||
Delete(int64) error
|
||||
}
|
||||
|
||||
func NewCenterService(repository repositories.CenterRepository, tokenRepository repositories.TokenRepository) CenterService {
|
||||
return ¢erService{
|
||||
repository: repository,
|
||||
tokenRepository: tokenRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *centerService) List(q string, page int, limit int) (*[]models.Center, error) {
|
||||
return s.repository.List(q, page, limit)
|
||||
}
|
||||
|
||||
func (s *centerService) Total(q string) (int64, error) {
|
||||
return s.repository.Total(q)
|
||||
}
|
||||
|
||||
func (s *centerService) Find(id int64) (*models.Center, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *centerService) FindByTitle(centername string) (*models.Center, error) {
|
||||
return s.repository.FindByTitle(centername)
|
||||
}
|
||||
|
||||
func (s *centerService) Create(center *models.Center) (*models.Center, error) {
|
||||
result, err := s.repository.Create(center)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *centerService) Update(center *models.Center) (*models.Center, error) {
|
||||
result, err := s.repository.Update(center)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *centerService) Delete(id int64) error {
|
||||
err := s.repository.Delete(id)
|
||||
|
||||
return err
|
||||
}
|
85
internal/services/quiz.go
Normal file
85
internal/services/quiz.go
Normal file
@ -0,0 +1,85 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type quizService struct {
|
||||
repository repositories.QuizRepository
|
||||
}
|
||||
|
||||
type QuizService interface {
|
||||
List(int64, int, int) (*[]models.Quiz, error)
|
||||
Total(int64) (int64, error)
|
||||
|
||||
Find(int64) (*models.Quiz, error)
|
||||
Create(*models.Quiz) (*models.Quiz, error)
|
||||
Update(*models.Quiz) (*models.Quiz, error)
|
||||
Delete(int64) error
|
||||
}
|
||||
|
||||
func NewQuizService(repository repositories.QuizRepository) QuizService {
|
||||
return &quizService{
|
||||
repository: repository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *quizService) List(quiz_paper_id int64, page int, limit int) (*[]models.Quiz, error) {
|
||||
return s.repository.List(quiz_paper_id, page, limit)
|
||||
}
|
||||
|
||||
func (s *quizService) Total(quiz_paper_id int64) (int64, error) {
|
||||
return s.repository.Total(quiz_paper_id)
|
||||
}
|
||||
|
||||
func (s *quizService) Find(id int64) (*models.Quiz, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *quizService) Create(quiz *models.Quiz) (*models.Quiz, error) {
|
||||
result, err := s.repository.Create(quiz)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *quizService) Update(quiz *models.Quiz) (*models.Quiz, error) {
|
||||
result, err := s.repository.Update(quiz)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *quizService) Delete(id int64) error {
|
||||
err := s.repository.Delete(id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *quizService) Generate(quizpaper *models.QuizPaper) ([]models.Quiz, error) {
|
||||
templates, err := s.repository.List(quizpaper.ID, 1, 1000)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var quizzes []models.Quiz
|
||||
for _, q := range *templates {
|
||||
quiz := models.Quiz{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: quizpaper.CenterID,
|
||||
QuizPaperID: quizpaper.ID,
|
||||
No: q.No,
|
||||
QuestionType: q.QuestionType,
|
||||
Question: q.Question,
|
||||
Content: q.Content,
|
||||
Answer: q.Answer,
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
quizzes = append(quizzes, quiz)
|
||||
}
|
||||
|
||||
return quizzes, nil
|
||||
}
|
56
internal/services/quizpaper.go
Normal file
56
internal/services/quizpaper.go
Normal file
@ -0,0 +1,56 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
)
|
||||
|
||||
type quizPaperService struct {
|
||||
repository repositories.QuizPaperRepository
|
||||
}
|
||||
|
||||
type QuizPaperService interface {
|
||||
List(string, string, int, int) (*[]models.QuizPaper, error)
|
||||
Total(string, string) (int64, error)
|
||||
|
||||
Find(int64) (*models.QuizPaper, error)
|
||||
Create(*models.QuizPaper) (*models.QuizPaper, error)
|
||||
Update(*models.QuizPaper) (*models.QuizPaper, error)
|
||||
Delete(string) error
|
||||
}
|
||||
|
||||
func NewQuizPaperService(repository repositories.QuizPaperRepository) QuizPaperService {
|
||||
return &quizPaperService{
|
||||
repository: repository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *quizPaperService) List(q string, tag string, page int, limit int) (*[]models.QuizPaper, error) {
|
||||
return s.repository.List(q, tag, page, limit)
|
||||
}
|
||||
|
||||
func (s *quizPaperService) Total(q string, tag string) (int64, error) {
|
||||
return s.repository.Total(q, tag)
|
||||
}
|
||||
|
||||
func (s *quizPaperService) Find(id int64) (*models.QuizPaper, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *quizPaperService) Create(quizPaper *models.QuizPaper) (*models.QuizPaper, error) {
|
||||
result, err := s.repository.Create(quizPaper)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *quizPaperService) Update(quizPaper *models.QuizPaper) (*models.QuizPaper, error) {
|
||||
result, err := s.repository.Update(quizPaper)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *quizPaperService) Delete(id string) error {
|
||||
err := s.repository.Delete(id)
|
||||
|
||||
return err
|
||||
}
|
200
internal/services/token.go
Normal file
200
internal/services/token.go
Normal file
@ -0,0 +1,200 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
config "learnsteam/cslms-api/configs"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type tokenService struct {
|
||||
repository repositories.TokenRepository
|
||||
}
|
||||
|
||||
type TokenService interface {
|
||||
Find(int64) (*models.Token, error)
|
||||
Create(int64, string) (*models.Token, error)
|
||||
Update(*models.Token) (*models.Token, error)
|
||||
Delete(string) error
|
||||
|
||||
Refresh(string) (*models.Token, error)
|
||||
|
||||
Generate(string, int64, string) (string, error)
|
||||
Verify(tokenString string) (*jwt.Token, error)
|
||||
|
||||
GetJwtToken(string) (*jwt.Token, error)
|
||||
ExtractTokenString(string) string
|
||||
VerifyTokenString(string) (*jwt.Token, error)
|
||||
ValidToken(*jwt.Token) (bool, error)
|
||||
}
|
||||
|
||||
func NewTokenService(repository repositories.TokenRepository) TokenService {
|
||||
return &tokenService{
|
||||
repository: repository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *tokenService) Find(id int64) (*models.Token, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *tokenService) Create(user_id int64, role string) (*models.Token, error) {
|
||||
expiredAt := time.Now().Add(time.Hour * 24 * 30)
|
||||
accessToken, err := s.repository.Generate(user_id, expiredAt.Unix(), role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refreshExpiredAt := time.Now().Add(time.Hour * 24 * 90)
|
||||
refreshToken, err := s.repository.Generate(user_id, refreshExpiredAt.Unix(), role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newToken := &models.Token{
|
||||
UserID: user_id,
|
||||
Token: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
Status: "on",
|
||||
EndingAt: expiredAt,
|
||||
RegisterAt: time.Now(),
|
||||
}
|
||||
|
||||
token, err := s.repository.Create(newToken)
|
||||
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (s *tokenService) Update(token *models.Token) (*models.Token, error) {
|
||||
return s.repository.Update(token)
|
||||
}
|
||||
|
||||
func (s *tokenService) Delete(id string) error {
|
||||
return s.repository.Delete(id)
|
||||
}
|
||||
|
||||
func (s *tokenService) Verify(tokenString string) (*jwt.Token, error) {
|
||||
jwtToken, err := jwt.Parse(tokenString, func(jwtToken *jwt.Token) (interface{}, error) {
|
||||
if _, ok := jwtToken.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", jwtToken.Header["alg"])
|
||||
}
|
||||
return []byte(config.SECRET_KEY), nil
|
||||
})
|
||||
|
||||
return jwtToken, err
|
||||
}
|
||||
|
||||
func (s *tokenService) Generate(user_id string, expire_at int64, role string) (string, error) {
|
||||
claims := jwt.MapClaims{}
|
||||
claims["authorized"] = true
|
||||
claims["sub"] = user_id
|
||||
claims["exp"] = expire_at
|
||||
claims["role"] = role
|
||||
at := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
token, err := at.SignedString([]byte(config.SECRET_KEY))
|
||||
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (s *tokenService) GetJwtToken(tokenString string) (*jwt.Token, error) {
|
||||
jwtToken, err := jwt.Parse(tokenString, func(jwtToken *jwt.Token) (interface{}, error) {
|
||||
if _, ok := jwtToken.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", jwtToken.Header["alg"])
|
||||
}
|
||||
return []byte(config.SECRET_KEY), nil
|
||||
})
|
||||
return jwtToken, err
|
||||
}
|
||||
|
||||
func (s *tokenService) ExtractTokenString(authorization string) string {
|
||||
strArr := strings.Split(authorization, " ")
|
||||
if len(strArr) == 2 {
|
||||
return strArr[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *tokenService) VerifyTokenString(tokenString string) (*jwt.Token, error) {
|
||||
jwtToken, err := jwt.Parse(tokenString, func(jwtToken *jwt.Token) (interface{}, error) {
|
||||
if _, ok := jwtToken.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", jwtToken.Header["alg"])
|
||||
}
|
||||
return []byte(config.SECRET_KEY), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return jwtToken, nil
|
||||
}
|
||||
|
||||
func (s *tokenService) ValidToken(jwtToken *jwt.Token) (bool, error) {
|
||||
if jwtToken == nil {
|
||||
return false, fmt.Errorf("no token")
|
||||
}
|
||||
return jwtToken.Valid, nil
|
||||
}
|
||||
|
||||
func (s *tokenService) Refresh(refreshToken string) (*models.Token, error) {
|
||||
fmt.Println("refresh_token", refreshToken)
|
||||
|
||||
jwtToken, err := jwt.Parse(refreshToken, func(jwtToken *jwt.Token) (interface{}, error) {
|
||||
if _, ok := jwtToken.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", jwtToken.Header["alg"])
|
||||
}
|
||||
return []byte(config.SECRET_KEY), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("refresh token is not valid")
|
||||
} else {
|
||||
|
||||
fmt.Println("refresh token is valid")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims, ok := jwtToken.Claims.(jwt.MapClaims)
|
||||
if !ok || !jwtToken.Valid {
|
||||
return nil, errors.New("refresh token is invalid")
|
||||
}
|
||||
|
||||
sub := claims["sub"].(int64)
|
||||
if err != nil {
|
||||
return nil, errors.New("wrong user")
|
||||
}
|
||||
role := claims["role"].(string)
|
||||
|
||||
token, err := s.repository.FindByRefreshToken(sub, refreshToken)
|
||||
if err != nil {
|
||||
return nil, errors.New("wrong token")
|
||||
}
|
||||
|
||||
expiredAt := time.Now().Add(time.Hour * 24 * 30)
|
||||
accessToken, err := s.repository.Generate(sub, expiredAt.Unix(), role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refreshExpiredAt := time.Now().Add(time.Hour * 24 * 90)
|
||||
refreshToken, err = s.repository.Generate(sub, refreshExpiredAt.Unix(), role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token.Token = accessToken
|
||||
token.EndingAt = expiredAt
|
||||
token.RefreshToken = refreshToken
|
||||
|
||||
return s.repository.Update(token)
|
||||
}
|
48
internal/services/user.go
Normal file
48
internal/services/user.go
Normal file
@ -0,0 +1,48 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
)
|
||||
|
||||
type userService struct {
|
||||
repository repositories.UserRepository
|
||||
tokenRepository repositories.TokenRepository
|
||||
}
|
||||
|
||||
type UserService interface {
|
||||
List(string, int, int) (*[]models.User, error)
|
||||
Total(string) (int64, error)
|
||||
Find(int64) (*models.User, error)
|
||||
FindByUsername(string) (*models.User, error)
|
||||
Create(*models.User) (*models.User, error)
|
||||
}
|
||||
|
||||
func NewUserService(repository repositories.UserRepository, tokenRepository repositories.TokenRepository) UserService {
|
||||
return &userService{
|
||||
repository: repository,
|
||||
tokenRepository: tokenRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userService) List(q string, page int, limit int) (*[]models.User, error) {
|
||||
return s.repository.List(q, page, limit)
|
||||
}
|
||||
|
||||
func (s *userService) Total(q string) (int64, error) {
|
||||
return s.repository.Total(q)
|
||||
}
|
||||
|
||||
func (s *userService) Find(id int64) (*models.User, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *userService) FindByUsername(username string) (*models.User, error) {
|
||||
return s.repository.FindByUsername(username)
|
||||
}
|
||||
|
||||
func (s *userService) Create(user *models.User) (*models.User, error) {
|
||||
result, err := s.repository.Create(user)
|
||||
|
||||
return result, err
|
||||
}
|
94
internal/services/userquiz.go
Normal file
94
internal/services/userquiz.go
Normal file
@ -0,0 +1,94 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
)
|
||||
|
||||
type userQuizService struct {
|
||||
repository repositories.UserQuizRepository
|
||||
quizRepository repositories.QuizRepository
|
||||
}
|
||||
|
||||
type UserQuizService interface {
|
||||
List(int64, int, int) (*[]models.UserQuiz, error)
|
||||
Total(int64) (int64, error)
|
||||
|
||||
Find(int64) (*models.UserQuiz, error)
|
||||
Create(*models.UserQuiz) (*models.UserQuiz, error)
|
||||
Insert([]models.UserQuiz) ([]models.UserQuiz, error)
|
||||
Update(*models.UserQuiz) (*models.UserQuiz, error)
|
||||
Delete(int64) error
|
||||
Generate(int64, *models.UserQuizPaper) ([]models.UserQuiz, error)
|
||||
}
|
||||
|
||||
func NewUserQuizService(repository repositories.UserQuizRepository, quizRepository repositories.QuizRepository) UserQuizService {
|
||||
return &userQuizService{
|
||||
repository: repository,
|
||||
quizRepository: quizRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userQuizService) List(user_quiz_paper_id int64, page int, limit int) (*[]models.UserQuiz, error) {
|
||||
return s.repository.List(user_quiz_paper_id, page, limit)
|
||||
}
|
||||
|
||||
func (s *userQuizService) Total(user_quiz_paper_id int64) (int64, error) {
|
||||
return s.repository.Total(user_quiz_paper_id)
|
||||
}
|
||||
|
||||
func (s *userQuizService) Find(id int64) (*models.UserQuiz, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *userQuizService) Create(quiz *models.UserQuiz) (*models.UserQuiz, error) {
|
||||
result, err := s.repository.Create(quiz)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userQuizService) Insert(items []models.UserQuiz) ([]models.UserQuiz, error) {
|
||||
result, err := s.repository.Insert(items)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userQuizService) Update(quiz *models.UserQuiz) (*models.UserQuiz, error) {
|
||||
result, err := s.repository.Update(quiz)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userQuizService) Delete(id int64) error {
|
||||
err := s.repository.Delete(id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *userQuizService) Generate(quiz_paper_id int64, userQuizPaper *models.UserQuizPaper) ([]models.UserQuiz, error) {
|
||||
var userQuizzes []models.UserQuiz
|
||||
quizzes, err := s.quizRepository.List(quiz_paper_id, 1, 1000)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, quiz := range *quizzes {
|
||||
userQuiz := models.UserQuiz{
|
||||
GUID: quiz.GUID,
|
||||
CenterID: quiz.CenterID,
|
||||
UserQuizPaperID: userQuizPaper.ID,
|
||||
UserID: userQuizPaper.UserID,
|
||||
No: quiz.No,
|
||||
QuestionType: quiz.QuestionType,
|
||||
Question: quiz.Question,
|
||||
Content: quiz.Content,
|
||||
}
|
||||
|
||||
fmt.Println(userQuiz.Content)
|
||||
// fmt.Println(userQuiz.Answer)
|
||||
userQuizzes = append(userQuizzes, userQuiz)
|
||||
}
|
||||
|
||||
return userQuizzes, nil
|
||||
}
|
83
internal/services/userquizpaper.go
Normal file
83
internal/services/userquizpaper.go
Normal file
@ -0,0 +1,83 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"learnsteam/cslms-api/internal/models"
|
||||
"learnsteam/cslms-api/internal/repositories"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type userQuizPaperService struct {
|
||||
repository repositories.UserQuizPaperRepository
|
||||
}
|
||||
|
||||
type UserQuizPaperService interface {
|
||||
List(string, int, int) (*[]models.UserQuizPaper, error)
|
||||
Total(string) (int64, error)
|
||||
|
||||
Find(int64) (*models.UserQuizPaper, error)
|
||||
Create(*models.UserQuizPaper) (*models.UserQuizPaper, error)
|
||||
Insert([]models.UserQuizPaper) ([]models.UserQuizPaper, error)
|
||||
Update(*models.UserQuizPaper) (*models.UserQuizPaper, error)
|
||||
Delete(string) error
|
||||
Generate([]int64, *models.QuizPaper) []models.UserQuizPaper
|
||||
}
|
||||
|
||||
func NewUserQuizPaperService(repository repositories.UserQuizPaperRepository) UserQuizPaperService {
|
||||
return &userQuizPaperService{
|
||||
repository: repository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) List(q string, page int, limit int) (*[]models.UserQuizPaper, error) {
|
||||
return s.repository.List(q, page, limit)
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Total(q string) (int64, error) {
|
||||
return s.repository.Total(q)
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Find(id int64) (*models.UserQuizPaper, error) {
|
||||
return s.repository.Find(id)
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Create(userQuizPaper *models.UserQuizPaper) (*models.UserQuizPaper, error) {
|
||||
result, err := s.repository.Create(userQuizPaper)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Insert(items []models.UserQuizPaper) ([]models.UserQuizPaper, error) {
|
||||
result, err := s.repository.Insert(items)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Update(userQuizPaper *models.UserQuizPaper) (*models.UserQuizPaper, error) {
|
||||
result, err := s.repository.Update(userQuizPaper)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Delete(id string) error {
|
||||
err := s.repository.Delete(id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *userQuizPaperService) Generate(users []int64, quizPaper *models.QuizPaper) []models.UserQuizPaper {
|
||||
var userQuizPapers []models.UserQuizPaper
|
||||
|
||||
for _, user_id := range users {
|
||||
userQuizPaper := models.UserQuizPaper{
|
||||
GUID: uuid.NewString(),
|
||||
CenterID: quizPaper.CenterID,
|
||||
UserID: user_id,
|
||||
QuizPaperID: quizPaper.ID,
|
||||
}
|
||||
|
||||
userQuizPapers = append(userQuizPapers, userQuizPaper)
|
||||
}
|
||||
|
||||
return userQuizPapers
|
||||
}
|
Reference in New Issue
Block a user