diff --git a/cmd/app/main.go b/cmd/app/main.go index a0a020f..c30519a 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -18,9 +18,8 @@ import ( // @BasePath / // @schemes http -// @securitydefinitions.apikey Auth -// @in header -// @name Authorization +// @securitydefinitions.oauth2.password OAuth2Password +// @tokenUrl http://localhost:8080/api/v1/auth/login func main() { cfg, err := config.NewConfig() if err != nil { diff --git a/go.mod b/go.mod index db20ede..a79bbd7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module ssr -go 1.17 +go 1.19 require ( github.com/golang-jwt/jwt v3.2.2+incompatible diff --git a/internal/app/app.go b/internal/app/app.go index b916ad2..7af04f9 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -4,45 +4,44 @@ package app import ( "fmt" "github.com/labstack/echo/v4" - m "github.com/labstack/echo/v4/middleware" - echoSwagger "github.com/swaggo/echo-swagger" + "github.com/labstack/echo/v4/middleware" + "net/http" "ssr/config" - "ssr/internal/controller/http" - uc "ssr/internal/usecase" - repo "ssr/internal/usecase/repo_pg" + ctrl "ssr/internal/controller/http" + "ssr/internal/service" + "ssr/internal/service/repo_pg" "ssr/pkg/logger" - "ssr/pkg/misc" "ssr/pkg/postgres" - _ "ssr/swagger" - "strings" ) -func setupMiddlewares(server *echo.Echo, cfg *config.Config) { - server.Use(m.CORS()) - server.Use(m.Logger()) - server.Use(m.Recover()) - server.Use(m.JWTWithConfig(m.JWTConfig{ - Claims: &misc.AppJWTClaims{}, - SigningKey: []byte(cfg.SigningKey), - ContextKey: "ctx", - Skipper: func(c echo.Context) bool { - // Skip middleware if 'login' or 'swagger' - path := c.Request().URL.Path - split := strings.Split(path, "/") - return split[2] == "auth" || split[1] == "swagger" - }, - })) +func setupMiddlewares(server *echo.Echo) { + server.Use(middleware.CORS()) + server.Use(middleware.Logger()) + server.Use(middleware.Recover()) } -func setupUC(server *echo.Echo, pg *postgres.Postgres, l *logger.Logger, cfg *config.Config) { - authUC := uc.NewAuth(repo.NewAuthPgRepo(pg, l), l, cfg.Auth.TokenExp, []byte(cfg.Auth.SigningKey)) - profileUC := uc.NewProfile(repo.NewProfilePgRepo(pg, l), l) - bidUC := uc.NewBid(repo.NewSSRPgRepo(pg, l), l) - workUC := uc.NewWork(repo.NewWorkPgRepo(pg, l), repo.NewSSRPgRepo(pg, l), l) - ssrUC := uc.NewSSR(repo.NewSSRPgRepo(pg, l), l) - feedBackUC := uc.NewFeedback(repo.NewFeedback(pg, l), l) +func makeInjections(server *echo.Echo, pg *postgres.Postgres, l *logger.Logger, cfg *config.Config) { + relationRepo := repo_pg.NewRelation(pg, l) + workRepo := repo_pg.NewWork(pg, l) + waypointRepo := repo_pg.NewWaypointRepo(pg, l) + userRepo := repo_pg.NewUser(pg, l) + studentRepo := repo_pg.NewStudent(pg, l) + supervisorRepo := repo_pg.NewSupervisor(pg, l) - http.NewRouter(server, l, authUC, profileUC, bidUC, bidUC, workUC, workUC, ssrUC, feedBackUC) + authService := service.NewAuth(userRepo, l, cfg.Auth.TokenExp, []byte(cfg.Auth.SigningKey)) + profileService := service.NewProfile(studentRepo, supervisorRepo, l) + workService := service.NewWork(workRepo, relationRepo, studentRepo, supervisorRepo, waypointRepo, l) + relationService := service.NewRelation(relationRepo, l) + + ctrl.NewRouter( + server, + l, + cfg, + authService, + profileService, + workService, + relationService, + ) } func Run(cfg *config.Config) { @@ -56,9 +55,10 @@ func Run(cfg *config.Config) { defer pg.Close() server := echo.New() - setupMiddlewares(server, cfg) - setupUC(server, pg, loggerObject, cfg) + setupMiddlewares(server) + makeInjections(server, pg, loggerObject, cfg) - server.GET("/swagger*", echoSwagger.WrapHandler) - server.Logger.Fatal(server.Start(cfg.HTTP.Port)) + if err := server.Start(cfg.HTTP.Port); err != http.ErrServerClosed { + server.Logger.Fatal(err) + } } diff --git a/internal/controller/http/auth.go b/internal/controller/http/auth.go index d60a3f4..4373510 100644 --- a/internal/controller/http/auth.go +++ b/internal/controller/http/auth.go @@ -4,13 +4,12 @@ import ( "fmt" "github.com/labstack/echo/v4" "net/http" - "ssr/internal/usecase" "ssr/pkg/logger" ) -type authRoutes struct { - l logger.Interface - uc usecase.IUsecaseAuth +type auth struct { + l logger.Interface + service AuthService } // ShowAccount godoc @@ -18,19 +17,19 @@ type authRoutes struct { // @Tags auth // @Accept x-www-form-urlencoded // @Produce json -// @Param username formData string true "User email" -// @Param password formData string true "User password" +// @Param username formData string true "UserFull email" +// @Param password formData string true "UserFull password" // @Success 200 {object} dto.LoginResponse // @Failure 401 // @Failure 500 // @Router /api/auth/login [post] -func (r *authRoutes) login(ctx echo.Context) error { +func (ctrl *auth) login(ctx echo.Context) error { email := ctx.FormValue("username") password := ctx.FormValue("password") - r.l.Debug(fmt.Sprintf("Email %s; Password: %s", email, password)) + ctrl.l.Debug(fmt.Sprintf("Email %s; Password: %s", email, password)) - respDTO, err := r.uc.Login(email, password) + respDTO, err := ctrl.service.Login(email, password) if err != nil { return echo.ErrUnauthorized } @@ -38,13 +37,12 @@ func (r *authRoutes) login(ctx echo.Context) error { return ctx.JSON(http.StatusOK, respDTO) } -func NewAuthRoutes(router *echo.Group, l logger.Interface, uc usecase.IUsecaseAuth) { - ar := &authRoutes{l, uc} +func NewAuthRoutes(router *echo.Group, l logger.Interface, service AuthService) { + ctrl := &auth{l, service} g := router.Group("/auth") - { - g.POST("/login", ar.login) + g.POST("/login", ctrl.login) } } diff --git a/internal/controller/http/interfaces.go b/internal/controller/http/interfaces.go new file mode 100644 index 0000000..03bc4f4 --- /dev/null +++ b/internal/controller/http/interfaces.go @@ -0,0 +1,26 @@ +package http + +import ( + "ssr/internal/dto" +) + +type ( + AuthService interface { + Login(email, password string) (*dto.LoginResponse, error) + } + ProfileService interface { + GetStudentProfile(userID int) (*dto.Student, error) + GetSupervisorProfile(userID int) (*dto.Supervisor, error) + } + RelationsService interface { + GetPlenty(studentID, supervisorID int) (*dto.RelationPlenty, error) + Create(data *dto.RelationCreateReq) (*dto.RelationCreateResp, error) + Update(data *dto.RelationUpdateReq) (*dto.RelationResp, error) + Get(RelationID int) (*dto.RelationResp, error) + } + WorkService interface { + Get(workID int) (*dto.WorkFullResp, error) + GetStudentWorks(studentID int) (*dto.StudentViewWorkPlenty, error) + GetSupervisorWorks(supervisorID int) (*dto.SupervisorViewWorkPlenty, error) + } +) diff --git a/internal/controller/http/middlewares/auth.go b/internal/controller/http/middlewares/auth.go index a2d3c16..a0dc950 100644 --- a/internal/controller/http/middlewares/auth.go +++ b/internal/controller/http/middlewares/auth.go @@ -2,6 +2,8 @@ package middlewares import ( "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + "ssr/config" "ssr/pkg/misc" "strings" ) @@ -10,11 +12,17 @@ func CheckRole(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { split := strings.Split(c.Request().URL.Path, "/") - // /api//... -> ["", "api", "" , ...] - expRole := split[2] + // /api//... -> ["", "api", "vNo", "" , ...] + + if len(split) < 4 { + return echo.ErrForbidden + } + expRole := split[3] _, recRole := misc.ExtractCtx(c) - if recRole != expRole { + mapping := map[string]string{"st": "students", "sv": "supervisors"} + + if mapping[recRole] != expRole { return echo.ErrForbidden } @@ -25,3 +33,11 @@ func CheckRole(next echo.HandlerFunc) echo.HandlerFunc { return nil } } + +func MakeAuthMiddleware(config *config.Config) echo.MiddlewareFunc { + return middleware.JWTWithConfig(middleware.JWTConfig{ + Claims: &misc.AppJWTClaims{}, + SigningKey: []byte(config.SigningKey), + ContextKey: "ctx", + }) +} diff --git a/internal/controller/http/relation.go b/internal/controller/http/relation.go new file mode 100644 index 0000000..2efac99 --- /dev/null +++ b/internal/controller/http/relation.go @@ -0,0 +1,119 @@ +package http + +import ( + "github.com/labstack/echo/v4" + "net/http" + "ssr/config" + "ssr/internal/controller/http/middlewares" + "ssr/internal/dto" + "ssr/pkg/logger" + "strconv" +) + +type relation struct { + l logger.Interface + relationService RelationsService +} + +// ShowAccount godoc +// @Summary Create relation +// @Tags relation +// @Accept json +// @Param CreateRelation body dto.RelationCreateReq true "Relation data" +// @Produce json +// @Success 201 {object} dto.RelationCreateResp +// @Router /api/v1/relations/ [post] +// @Security OAuth2Password +func (ctrl *relation) create(ctx echo.Context) error { + reqDTO := &dto.RelationCreateReq{} + + if err := ctx.Bind(reqDTO); err != nil { + return echo.ErrBadRequest + } + + respDTO, err := ctrl.relationService.Create(reqDTO) + if err != nil { + return echo.ErrInternalServerError + } + + return ctx.JSON(http.StatusCreated, respDTO) +} + +// ShowAccount godoc +// @Summary Update relation +// @Tags relation +// @Accept json +// @Param CreateRelation body dto.RelationUpdateReq true "Relation data" +// @Produce json +// @Success 200 {object} dto.RelationResp +// @Router /api/v1/relations/ [patch] +// @Security OAuth2Password +func (ctrl *relation) update(ctx echo.Context) error { + reqDTO := &dto.RelationUpdateReq{} + + if err := ctx.Bind(reqDTO); err != nil { + return echo.ErrBadRequest + } + + respDTO, err := ctrl.relationService.Update(reqDTO) + if err != nil { + return echo.ErrInternalServerError + } + + return ctx.JSON(http.StatusCreated, respDTO) +} + +// ShowAccount godoc +// @Summary Get relations +// @Tags relation +// @Produce json +// @Param student_id query int false "Student ID" +// @Param supervisor_id query int false "Supervisor ID" +// @Success 200 {object} dto.RelationPlenty +// @Failure 404 +// @Router /api/v1/relations/ [get] +// @Security OAuth2Password +func (ctrl *relation) getPlenty(ctx echo.Context) error { + studentID, _ := strconv.Atoi(ctx.QueryParam("student_id")) + supervisorID, _ := strconv.Atoi(ctx.QueryParam("supervisor_id")) + + if studentID < 0 || supervisorID < 0 { + return echo.NewHTTPError(400, map[string]string{"err": "Bad request", "msg": "Parameter (student_id, supervisor_id) must be positive"}) + } + + if studentID == 0 && supervisorID == 0 { + return echo.NewHTTPError(400, map[string]string{"err": "Bad request", "msg": "Must be passed at least one parameter (student_id, supervisor_id)"}) + } + + if studentID != 0 && supervisorID != 0 { + return echo.NewHTTPError(400, map[string]string{"err": "Bad request", "msg": "Must be passed only on parameter (student_id, supervisor_id)"}) + } + + respDTO, err := ctrl.relationService.GetPlenty(studentID, supervisorID) + if err != nil { + return err + } + + return ctx.JSON(http.StatusOK, respDTO) +} + +func NewRelationRoutes( + router *echo.Group, + l logger.Interface, + config *config.Config, + relationsService RelationsService, +) { + ctrl := &relation{ + l, + relationsService, + } + + relations := router.Group("/relations", middlewares.MakeAuthMiddleware(config)) + + { + relations.GET("/", ctrl.getPlenty) + relations.POST("/", ctrl.create) + relations.PATCH("/", ctrl.update) + } + +} diff --git a/internal/controller/http/router.go b/internal/controller/http/router.go index fa7484d..cbe18d4 100644 --- a/internal/controller/http/router.go +++ b/internal/controller/http/router.go @@ -2,27 +2,29 @@ package http import ( "github.com/labstack/echo/v4" - "ssr/internal/usecase" + echoSwagger "github.com/swaggo/echo-swagger" + "ssr/config" "ssr/pkg/logger" + _ "ssr/swagger" ) func NewRouter( - echo *echo.Echo, + server *echo.Echo, l logger.Interface, - auth usecase.IUsecaseAuth, - profile usecase.IUsecaseProfile, - studentBids usecase.IUsecaseStudentBid, - supervisorBids usecase.IUseCaseSupervisorBid, - studentWorks usecase.IStudentWorkUC, - supervisorWorks usecase.ISupervisorWorkUC, - studentRelations usecase.IUseCaseStudentRelation, - feedback usecase.IUsecaseFeedback, + config *config.Config, + auth AuthService, + profiles ProfileService, + works WorkService, + relations RelationsService, ) { - g := echo.Group("/api") + g := server.Group("/api/v1") + g.GET("/swagger/*", echoSwagger.WrapHandler) { NewAuthRoutes(g, l, auth) - NewStudentRoutes(g, l, profile, studentBids, studentWorks, studentRelations, feedback) - NewSupervisorRoutes(g, l, profile, supervisorBids, supervisorWorks) + NewStudentRoutes(g, l, config, profiles, works, relations) + NewSupervisorRoutes(g, l, config, profiles, works) + NewWorksRoutes(g, l, config, works) + NewRelationRoutes(g, l, config, relations) } } diff --git a/internal/controller/http/student.go b/internal/controller/http/student.go index e2aa220..f5003a0 100644 --- a/internal/controller/http/student.go +++ b/internal/controller/http/student.go @@ -1,105 +1,53 @@ package http import ( - "fmt" "github.com/labstack/echo/v4" "net/http" + "ssr/config" "ssr/internal/controller/http/middlewares" - "ssr/internal/dto" - "ssr/internal/usecase" "ssr/pkg/logger" - "ssr/pkg/misc" "strconv" ) -type studentRoutes struct { - l logger.Interface - profileUC usecase.IUsecaseProfile - bidsUC usecase.IUsecaseStudentBid - worksUC usecase.IStudentWorkUC - ssrUC usecase.IUseCaseStudentRelation - feedbackUC usecase.IUsecaseFeedback +type student struct { + l logger.Interface + profileService ProfileService + workService WorkService + relationsService RelationsService } // ShowAccount godoc -// @Summary GetUserInfo student's profile +// @Summary Get student's profile // @Tags student // @Produce json -// @Success 200 {object} dto.StudentProfile +// @Param student_id path int true "Student ID" +// @Success 200 {object} dto.Student // @Failure 404 -// @Router /api/student/profile [get] -// @Security Auth -func (r *studentRoutes) getProfile(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) +// @Router /api/v1/students/{student_id}/profile [get] +// @Security OAuth2Password +func (ctrl *student) getProfile(ctx echo.Context) error { + studentID, _ := strconv.Atoi(ctx.Param("student_id")) - profileDto, err := r.profileUC.GetStudentProfile(email) + profileDTO, err := ctrl.profileService.GetStudentProfile(studentID) if err != nil { return echo.ErrNotFound } - return ctx.JSON(http.StatusOK, profileDto) + return ctx.JSON(http.StatusOK, profileDTO) } // ShowAccount godoc -// @Summary GetUserInfo student's bids +// @Summary Get student's works // @Tags student +// @Param student_id path int true "Student ID" // @Produce json -// @Param student_id query int true "Student ID" -// @Success 200 {object} dto.StudentBids -// @Failure 404 -// @Router /api/student/bid [get] -// @Security Auth -func (r *studentRoutes) getBids(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - studentID, _ := strconv.Atoi(ctx.QueryParam("student_id")) - - respDTO, err := r.bidsUC.GetStudentBids(studentID) - if err != nil { - return echo.ErrNotFound - } - - return ctx.JSON(http.StatusOK, respDTO) -} - -// ShowAccount godoc -// @Summary GetUserInfo student's works -// @Tags student -// @Param student_id query int true "Student ID" -// @Produce json -// @Success 200 {object} dto.StudentWorks -// @Router /api/student/work [get] -// @Security Auth -func (r *studentRoutes) getWorks(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - studentID, _ := strconv.Atoi(ctx.QueryParam("student_id")) - - respDTO, err := r.worksUC.GetStudentWorks(studentID) - if err != nil { - return echo.ErrNotFound - } +// @Success 200 {object} dto.StudentViewWorkPlenty +// @Router /api/v1/students/{student_id}/works [get] +// @Security OAuth2Password +func (ctrl *student) getWorks(ctx echo.Context) error { + studentID, _ := strconv.Atoi(ctx.Param("student_id")) - return ctx.JSON(http.StatusOK, respDTO) -} - -// ShowAccount godoc -// @Summary GetUserInfo supervisors of the work -// @Tags student -// @Param work_id query int true "Work ID" -// @Produce json -// @Success 200 {object} dto.WorkSupervisorPlenty -// @Router /api/student/work/supervisor [get] -// @Security Auth -func (r *studentRoutes) getSupervisorsOfWork(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - workID, _ := strconv.Atoi(ctx.QueryParam("work_id")) - - respDTO, err := r.worksUC.GetWorkSupervisors(workID) + respDTO, err := ctrl.workService.GetStudentWorks(studentID) if err != nil { return echo.ErrNotFound } @@ -107,129 +55,26 @@ func (r *studentRoutes) getSupervisorsOfWork(ctx echo.Context) error { return ctx.JSON(http.StatusOK, respDTO) } -// ShowAccount godoc -// @Summary Apply bid -// @Tags student -// @Accept json -// @Param ApplyBid body dto.ApplyBid true "bid info" -// @Produce json -// @Success 200 {object} dto.ApplyBidResponse -// @Router /api/student/bid [put] -// @Security Auth -func (r *studentRoutes) applyBid(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - reqDTO := &dto.ApplyBid{} - if err := ctx.Bind(reqDTO); err != nil { - return echo.ErrBadRequest - } - - respDTO, err := r.bidsUC.Apply(reqDTO) - if err != nil { - return echo.ErrInternalServerError - } - - return ctx.JSON(http.StatusCreated, respDTO) -} - -// ShowAccount godoc -// @Summary Start SSR -// @Tags student -// @Accept json -// @Param ApplyBid body dto.CreateSSR true "ssr info" -// @Produce json -// @Success 200 {object} dto.StudentViewSSR -// @Router /api/student/ssr [post] -// @Security Auth -func (r *studentRoutes) createSSR(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - reqDTO := &dto.CreateSSR{} - if err := ctx.Bind(reqDTO); err != nil { - return echo.ErrBadRequest - } - - respDTO, err := r.ssrUC.Create(reqDTO) - if err != nil { - return echo.ErrInternalServerError - } - - return ctx.JSON(http.StatusCreated, respDTO) -} - -// ShowAccount godoc -// @Summary Provide a feedback -// @Tags student -// @Accept json -// @Param Feedback body dto.FeedbackReq true "feedback info" -// @Produce json -// @Success 201 {object} dto.FeedbackAddResp -// @Failure 500 -// @Router /api/student/feedback [put] -// @Security Auth -func (r *studentRoutes) provideFeedback(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - reqDTO := &dto.FeedbackReq{} - if err := ctx.Bind(reqDTO); err != nil { - return echo.ErrBadRequest - } - - id, err := r.feedbackUC.Add(reqDTO) - if err != nil { - return echo.NewHTTPError(http.StatusConflict) - } - - return ctx.JSON(http.StatusCreated, dto.FeedbackAddResp{FeedbackID: id}) -} - -// ShowAccount godoc -// @Summary Get feedbacks on the supervisor. -// @Tags student -// @Param supervisor_id query int true "Supervisor ID" -// @Produce json -// @Success 200 {object} dto.FeedbackPlenty -// @Router /api/student/feedback [get] -// @Security Auth -func (r *studentRoutes) getFeedback(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - supervisorID, _ := strconv.Atoi(ctx.QueryParam("supervisor_id")) - - respDTO, err := r.feedbackUC.GetOnSupervisor(supervisorID) - if err != nil { - return echo.ErrInternalServerError - } - - return ctx.JSON(http.StatusOK, respDTO) -} - func NewStudentRoutes( router *echo.Group, l logger.Interface, - profileUC usecase.IUsecaseProfile, - bidsUC usecase.IUsecaseStudentBid, - worksUC usecase.IStudentWorkUC, - ssrUC usecase.IUseCaseStudentRelation, - feedbackUC usecase.IUsecaseFeedback, + config *config.Config, + profileService ProfileService, + worksService WorkService, + relationService RelationsService, ) { - r := &studentRoutes{l, profileUC, bidsUC, worksUC, ssrUC, feedbackUC} + ctrl := &student{ + l, + profileService, + worksService, + relationService, + } - g := router.Group("/student", middlewares.CheckRole) + student := router.Group("/students", middlewares.MakeAuthMiddleware(config), middlewares.CheckRole) { - g.GET("/profile", r.getProfile) - g.GET("/bid", r.getBids) - g.PUT("/bid", r.applyBid) - g.POST("/ssr", r.createSSR) - g.GET("/work", r.getWorks) - g.GET("/work/supervisor", r.getSupervisorsOfWork) - g.GET("/feedback", r.getFeedback) - g.PUT("/feedback", r.provideFeedback) + student.GET("/:student_id/profile", ctrl.getProfile) + student.GET("/:student_id/works", ctrl.getWorks) } } diff --git a/internal/controller/http/supervisor.go b/internal/controller/http/supervisor.go index 46f8a71..26273f7 100644 --- a/internal/controller/http/supervisor.go +++ b/internal/controller/http/supervisor.go @@ -1,61 +1,34 @@ package http import ( - "fmt" "github.com/labstack/echo/v4" "net/http" + "ssr/config" "ssr/internal/controller/http/middlewares" - "ssr/internal/dto" - "ssr/internal/usecase" "ssr/pkg/logger" - "ssr/pkg/misc" "strconv" ) -type supervisorRoutes struct { - l logger.Interface - profileUC usecase.IUsecaseProfile - bidUC usecase.IUseCaseSupervisorBid - workUC usecase.ISupervisorWorkUC +type supervisor struct { + l logger.Interface + profileService ProfileService + workService WorkService } // ShowAccount godoc -// @Summary GetUserInfo supervisor's profile +// @Summary Get supervisor's profile // @Tags supervisor // @Produce json -// @Success 200 {object} dto.SupervisorProfile -// @Router /api/supervisor/profile [get] -// @Security Auth -func (r *supervisorRoutes) getProfile(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - respDTO, err := r.profileUC.GetSupervisorProfile(email) - if err != nil { - r.l.Error(err) - return echo.NewHTTPError(http.StatusInternalServerError, "TODO") - } - - return ctx.JSON(http.StatusOK, respDTO) -} - -// ShowAccount godoc -// @Summary GetUserInfo supervisor's works -// @Tags supervisor -// @Param supervisor_id query int true "Supervisor ID" -// @Produce json -// @Success 200 {object} dto.SupervisorWorkPlenty -// @Router /api/supervisor/work [get] -// @Security Auth -func (r *supervisorRoutes) getWorks(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - supervisorID, _ := strconv.Atoi(ctx.QueryParam("supervisor_id")) - - respDTO, err := r.workUC.GetSupervisorWorks(supervisorID) +// @Param supervisor_id path int true "Supervisor ID" +// @Success 200 {object} dto.Supervisor +// @Router /api/v1/supervisors/{supervisor_id}/profile [get] +// @Security OAuth2Password +func (ctrl *supervisor) getProfile(ctx echo.Context) error { + supervisorID, _ := strconv.Atoi(ctx.Param("supervisor_id")) + + respDTO, err := ctrl.profileService.GetSupervisorProfile(supervisorID) if err != nil { - r.l.Error(err) + ctrl.l.Error(err) return echo.NewHTTPError(http.StatusInternalServerError, "TODO") } @@ -63,78 +36,39 @@ func (r *supervisorRoutes) getWorks(ctx echo.Context) error { } // ShowAccount godoc -// @Summary GetUserInfo supervisor's bids +// @Summary Get supervisor's works // @Tags supervisor -// @Param supervisor_id query int true "Supervisor ID" +// @Param supervisor_id path int true "Supervisor ID" // @Produce json -// @Success 200 {object} dto.SupervisorBids -// @Router /api/supervisor/bid [get] -// @Security Auth -func (r *supervisorRoutes) getBids(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - supervisorID, _ := strconv.Atoi(ctx.QueryParam("supervisor_id")) +// @Success 200 {object} dto.SupervisorViewWorkPlenty +// @Router /api/v1/supervisors/{supervisor_id}/works [get] +// @Security OAuth2Password +func (ctrl *supervisor) getWorks(ctx echo.Context) error { + supervisorID, _ := strconv.Atoi(ctx.Param("supervisor_id")) - respDTO, err := r.bidUC.GetSupervisorBids(supervisorID) + respDTO, err := ctrl.workService.GetSupervisorWorks(supervisorID) if err != nil { - r.l.Error(err) + ctrl.l.Error(err) return echo.NewHTTPError(http.StatusInternalServerError, "TODO") } return ctx.JSON(http.StatusOK, respDTO) } -// ShowAccount godoc -// @Summary Accept or Decline student's bid -// @Tags supervisor -// @Param ResolveBid body dto.ResolveBid true "bid info" -// @Produce json -// @Success 200 {object} dto.ResolveBidResp -// @Router /api/supervisor/bid/resolve [post] -// @Security Auth -func (r *supervisorRoutes) resolveBid(ctx echo.Context) error { - email, _ := misc.ExtractCtx(ctx) - r.l.Debug(fmt.Sprintf("Email: %s", email)) - - reqDTO := &dto.ResolveBid{} - if err := ctx.Bind(reqDTO); err != nil { - return echo.ErrBadRequest - } - - if err := r.bidUC.Resolve(reqDTO); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError) - } - - newStatus := "" - if reqDTO.Accept { - newStatus = "accepted" - } else { - newStatus = "rejected" - } - - resp := dto.ResolveBidResp{NewStatus: newStatus} - - return ctx.JSON(http.StatusOK, resp) -} - func NewSupervisorRoutes( router *echo.Group, l logger.Interface, - profileUC usecase.IUsecaseProfile, - bidUC usecase.IUseCaseSupervisorBid, - workUC usecase.ISupervisorWorkUC, + config *config.Config, + profileService ProfileService, + workService WorkService, ) { - r := &supervisorRoutes{l, profileUC, bidUC, workUC} + ctrl := &supervisor{l, profileService, workService} - g := router.Group("/supervisor", middlewares.CheckRole) + g := router.Group("/supervisors", middlewares.MakeAuthMiddleware(config), middlewares.CheckRole) { - g.GET("/profile", r.getProfile) - g.GET("/bid", r.getBids) - g.POST("/bid/resolve", r.resolveBid) - g.GET("/work", r.getWorks) - g.GET("/work", r.getWorks) + g.GET("/:supervisor_id/profile", ctrl.getProfile) + g.GET("/:supervisor_id/works", ctrl.getWorks) } } diff --git a/internal/controller/http/works.go b/internal/controller/http/works.go new file mode 100644 index 0000000..ac42a3d --- /dev/null +++ b/internal/controller/http/works.go @@ -0,0 +1,53 @@ +package http + +import ( + "github.com/labstack/echo/v4" + "net/http" + "ssr/config" + "ssr/internal/controller/http/middlewares" + "ssr/pkg/logger" + "strconv" +) + +type works struct { + l logger.Interface + workService WorkService +} + +// ShowAccount godoc +// @Summary Get supervisors of the work +// @Tags works +// @Param work_id path int true "Work ID" +// @Produce json +// @Success 200 {object} dto.WorkFullResp +// @Router /api/v1/works/{work_id} [get] +// @Security OAuth2Password +func (ctrl *works) get(ctx echo.Context) error { + workID, _ := strconv.Atoi(ctx.Param("work_id")) + + respDTO, err := ctrl.workService.Get(workID) + if err != nil { + return echo.ErrNotFound + } + + return ctx.JSON(http.StatusOK, respDTO) +} + +func NewWorksRoutes( + router *echo.Group, + l logger.Interface, + config *config.Config, + worksService WorkService, +) { + ctrl := &works{ + l, + worksService, + } + + works := router.Group("/works", middlewares.MakeAuthMiddleware(config)) + + { + works.GET("/:work_id", ctrl.get) + } + +} diff --git a/internal/dto/auth.go b/internal/dto/auth.go index 01a42d6..df6d6e7 100644 --- a/internal/dto/auth.go +++ b/internal/dto/auth.go @@ -1,7 +1,8 @@ package dto type LoginResponse struct { - Token string `json:"token"` - Email string `json:"email"` - Role string `json:"role"` + Token string `json:"access_token"` + TokenType string `json:"token_type"` + UserID int `json:"user_id"` + Role string `json:"role"` } diff --git a/internal/dto/bid.go b/internal/dto/bid.go deleted file mode 100644 index 06b5ccb..0000000 --- a/internal/dto/bid.go +++ /dev/null @@ -1,49 +0,0 @@ -package dto - -import ( - "time" -) - -type StudentBid struct { - BidID int `json:"id"` - Status string `json:"status"` - CreatedAt time.Time `json:"createdAt"` - Supervisor SupervisorProfile `json:"supervisor"` - Work Work `json:"work"` -} - -type StudentBids struct { - Bids []*StudentBid `json:"bids"` -} - -type SupervisorBid struct { - BidID int `json:"id"` - Status string `json:"status"` - CreatedAt time.Time `json:"createdAt"` - Student StudentProfile `json:"student"` - Work Work `json:"work"` -} - -type SupervisorBids struct { - Bids []*SupervisorBid `json:"bids"` -} - -type ApplyBid struct { - StudentID int `json:"studentID"` - SupervisorID int `json:"supervisorID"` - WorkID int `json:"workID"` -} - -type ApplyBidResponse struct { - BidID int `json:"bidID"` -} - -type ResolveBid struct { - SupervisorID int `json:"supervisorID"` - BidID int `json:"bidID"` - Accept bool `json:"accept"` -} - -type ResolveBidResp struct { - NewStatus string `json:"new_status"` -} diff --git a/internal/dto/feedback.go b/internal/dto/feedback.go deleted file mode 100644 index f6e49f0..0000000 --- a/internal/dto/feedback.go +++ /dev/null @@ -1,26 +0,0 @@ -package dto - -type FeedbackReq struct { - StudentID int `json:"studentID"` - SupervisorID int `json:"supervisorID"` - WorkID int `json:"workID"` - Content string `json:"content"` -} - -type FeedbackResp struct { - StudentID int `json:"studentID"` - StudentFullName string `json:"student_full_name"` - SupervisorID int `json:"supervisorID"` - WorkID int `json:"workID"` - WorkKind string `json:"work_kind"` - WorkSubject string `json:"work_subject"` - Content string `json:"content"` -} - -type FeedbackAddResp struct { - FeedbackID int `json:"feedback_id"` -} - -type FeedbackPlenty struct { - Feedbacks []*FeedbackResp `json:"feedbacks"` -} diff --git a/internal/dto/profile.go b/internal/dto/profile.go deleted file mode 100644 index d14a36b..0000000 --- a/internal/dto/profile.go +++ /dev/null @@ -1,34 +0,0 @@ -package dto - -import ( - "ssr/pkg/misc" -) - -type UserInfo struct { - Email string `json:"email"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - AvatarUrl misc.NullString `json:"avatarUrl"` -} - -type StudentProfile struct { - StudentID int `json:"studentID"` - Email string `json:"email"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - AvatarUrl misc.NullString `json:"avatarUrl" swaggertype:"string"` - Year int `json:"year"` - StudentCard string `json:"studentCard"` - Department string `json:"department"` -} - -type SupervisorProfile struct { - SupervisorID int `json:"supervisorID"` - Email string `json:"email"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - About string `json:"about"` - Birthdate misc.Date `json:"birthdate" swaggertype:"string"` - AvatarUrl misc.NullString `json:"avatarUrl" swaggertype:"string"` - Department string `json:"department"` -} diff --git a/internal/dto/relations.go b/internal/dto/relations.go new file mode 100644 index 0000000..a8c60f2 --- /dev/null +++ b/internal/dto/relations.go @@ -0,0 +1,40 @@ +package dto + +import ( + "ssr/internal/entity" +) + +type RelationCreateReq struct { + StudentID int `json:"student_id"` + SupervisorID int `json:"supervisor_id"` + WorkID int `json:"work_id"` +} + +type RelationResp struct { + RelationID int `json:"relation_id"` + Work WorkResp `json:"work"` + Status string `json:"status"` + Supervisor Supervisor `json:"supervisor"` + Student Student `json:"student"` +} + +type RelationShortResp struct { + RelationID int `json:"relation_id"` + Work WorkShortResp `json:"work"` + Status string `json:"status"` + Supervisor SupervisorShort `json:"supervisor"` + Student StudentShort `json:"student"` +} + +type RelationCreateResp struct { + RelationID int `json:"relation_id"` +} + +type RelationUpdateReq struct { + RelationID int `json:"relation_id"` + Status entity.StatusSSR `json:"status"` +} + +type RelationPlenty struct { + Relations []*RelationShortResp `json:"relations"` +} diff --git a/internal/dto/ssr.go b/internal/dto/ssr.go deleted file mode 100644 index 2672f85..0000000 --- a/internal/dto/ssr.go +++ /dev/null @@ -1,16 +0,0 @@ -package dto - -import "time" - -type CreateSSR struct { - StudentID int `json:"studentID"` - BidID int `json:"bidID"` -} - -type StudentViewSSR struct { - RelID int `json:"id"` - Status string `json:"status"` - CreatedAt time.Time `json:"createdAt"` - Supervisor SupervisorProfile `json:"supervisor"` - Work Work `json:"work"` -} diff --git a/internal/dto/students.go b/internal/dto/students.go new file mode 100644 index 0000000..82afa16 --- /dev/null +++ b/internal/dto/students.go @@ -0,0 +1,18 @@ +package dto + +type Student struct { + UserID int `json:"user_id"` + Email string `json:"email"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + PhotoUrl string `json:"photo_url"` + Year int `json:"year"` + StudentCard string `json:"student_card"` + Department string `json:"department"` +} + +type StudentShort struct { + UserID int `json:"user_id"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` +} diff --git a/internal/dto/subject.go b/internal/dto/subjects.go similarity index 74% rename from internal/dto/subject.go rename to internal/dto/subjects.go index d3aa69d..258b5fe 100644 --- a/internal/dto/subject.go +++ b/internal/dto/subjects.go @@ -1,7 +1,7 @@ package dto type SubjectResp struct { - SubjectID int `json:"subjectID"` + ID int `json:"id"` Name string `json:"name"` Department string `json:"department"` } diff --git a/internal/dto/supervisors.go b/internal/dto/supervisors.go new file mode 100644 index 0000000..b1b7c1a --- /dev/null +++ b/internal/dto/supervisors.go @@ -0,0 +1,26 @@ +package dto + +import "ssr/pkg/misc" + +type Supervisor struct { + UserID int `json:"user_id"` + Email string `json:"email"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + About string `json:"about"` + Birthdate misc.Date `json:"birthdate" swaggertype:"string"` + PhotoUrl string `json:"photo_url"` + Department string `json:"department"` +} + +type SupervisorShort struct { + UserID int `json:"user_id"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` +} + +type WorkSupervisorShort struct { + SupervisorShort + IsHead bool `json:"head"` + IsFull bool `json:"full"` +} diff --git a/internal/dto/waypoints.go b/internal/dto/waypoints.go new file mode 100644 index 0000000..3eb1de4 --- /dev/null +++ b/internal/dto/waypoints.go @@ -0,0 +1,13 @@ +package dto + +import "ssr/pkg/misc" + +type WaypointResp struct { + Title string `json:"title"` + Description string `json:"description"` + Deadline misc.Date `json:"deadline" swaggertype:"string"` +} + +type WaypointPlenty struct { + Waypoints []*WaypointResp `json:"waypoints"` +} diff --git a/internal/dto/work.go b/internal/dto/work.go deleted file mode 100644 index 6f56097..0000000 --- a/internal/dto/work.go +++ /dev/null @@ -1,46 +0,0 @@ -package dto - -type Work struct { - WorkID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Semester int8 `json:"semester"` - Subject SubjectResp `json:"subject"` -} - -type StudentWork struct { - WorkID int `json:"id"` - Kind string `json:"kind"` - Description string `json:"description"` - Subject string `json:"subject"` - IsStarted bool `json:"is_started"` -} - -type StudentWorks struct { - StudentID int `json:"studentID"` - Works []*StudentWork `json:"works"` -} - -type SupervisorWork struct { - WorkID int `json:"id"` - Kind string `json:"kind"` - Description string `json:"description"` - Subject string `json:"subject"` - Head bool `json:"head"` -} - -type SupervisorWorkPlenty struct { - SupervisorID int `json:"supervisorID"` - Works []*SupervisorWork `json:"works"` -} - -type WorkSupervisor struct { - SupervisorProfile - Head bool `json:"head"` - Full bool `json:"full"` -} - -type WorkSupervisorPlenty struct { - WorkID int `json:"workID"` - Supervisors []*WorkSupervisor `json:"supervisors"` -} diff --git a/internal/dto/work_kinds.go b/internal/dto/work_kinds.go new file mode 100644 index 0000000..5a2f9b1 --- /dev/null +++ b/internal/dto/work_kinds.go @@ -0,0 +1,6 @@ +package dto + +type WorkKindResp struct { + ID int `json:"id"` + Name string `json:"name"` +} diff --git a/internal/dto/works_common.go b/internal/dto/works_common.go new file mode 100644 index 0000000..4b9f077 --- /dev/null +++ b/internal/dto/works_common.go @@ -0,0 +1,29 @@ +package dto + +type WorkResp struct { + WorkID int `json:"id"` + Description string `json:"description"` + Semester int8 `json:"semester"` + Subject SubjectResp `json:"subject"` + Kind WorkKindResp `json:"kind"` +} + +type WorkFullResp struct { + WorkID int `json:"id"` + Description string `json:"description"` + Semester int8 `json:"semester"` + Subject SubjectResp `json:"subject"` + Kind WorkKindResp `json:"kind"` + Waypoints []*WaypointResp `json:"waypoints"` + Supervisors []*WorkSupervisorShort `json:"supervisors"` +} + +type WorkShortResp struct { + WorkID int `json:"id"` + Subject SubjectResp `json:"subject"` + Kind WorkKindResp `json:"kind"` +} + +type WorkPlenty struct { + Works []*WorkShortResp `json:"works"` +} diff --git a/internal/dto/works_student_view.go b/internal/dto/works_student_view.go new file mode 100644 index 0000000..d7a004a --- /dev/null +++ b/internal/dto/works_student_view.go @@ -0,0 +1,14 @@ +package dto + +type StudentViewWorkResp struct { + Work WorkResp `json:"work"` + IsStarted bool `json:"is_started"` // TODO +} + +type StudentViewWorkShortResp struct { + Work WorkShortResp `json:"work"` +} + +type StudentViewWorkPlenty struct { + Works []*StudentViewWorkShortResp `json:"works"` +} diff --git a/internal/dto/works_supervisor_view.go b/internal/dto/works_supervisor_view.go new file mode 100644 index 0000000..98a5e92 --- /dev/null +++ b/internal/dto/works_supervisor_view.go @@ -0,0 +1,17 @@ +package dto + +type SupervisorViewWorkResp struct { + Work WorkResp `json:"work"` + IsHead bool `json:"is_head"` + IsFull bool `json:"is_full"` +} + +type SupervisorViewWorkShortResp struct { + Work WorkShortResp `json:"work"` + IsHead bool `json:"is_head"` + IsFull bool `json:"is_full"` +} + +type SupervisorViewWorkPlenty struct { + Works []*SupervisorViewWorkShortResp `json:"works"` +} diff --git a/internal/entity/auth.go b/internal/entity/auth.go deleted file mode 100644 index 22e1d9d..0000000 --- a/internal/entity/auth.go +++ /dev/null @@ -1,14 +0,0 @@ -package entity - -type UserRole string - -const ( - student UserRole = "student" - supervisor = "supervisor" -) - -type Auth struct { - Email string `db:"email"` - Password string `db:"password"` - Role UserRole `db:"role"` -} diff --git a/internal/entity/feedback.go b/internal/entity/feedback.go deleted file mode 100644 index 34ee542..0000000 --- a/internal/entity/feedback.go +++ /dev/null @@ -1,15 +0,0 @@ -package entity - -import "time" - -type Feedback struct { - FeedbackID int `db:"feedback_id"` - WorkID int `db:"work_id"` - WorkKind string `db:"work_kind"` - WorkSubject string `db:"work_subject"` - StudentID int `db:"student_id"` - StudentFullName string `db:"student_full_name"` - SupervisorID int `db:"supervisor_id"` - CreatedAt time.Time `db:"created_at"` - Content string `db:"content"` -} diff --git a/internal/entity/profile.go b/internal/entity/profile.go index 7f11a4a..cdbb7c6 100644 --- a/internal/entity/profile.go +++ b/internal/entity/profile.go @@ -2,7 +2,7 @@ package entity import "time" -type StudentProfile struct { +type StProfile struct { *User StudentID int `db:"student_id"` StudentCard string `db:"student_card"` @@ -10,7 +10,7 @@ type StudentProfile struct { DepartmentID string `db:"department_id"` } -type SupervisorProfile struct { +type SvProfile struct { *User SupervisorID int `db:"supervisor_id"` Birthdate time.Time `db:"birthdate"` diff --git a/internal/entity/relation.go b/internal/entity/relation.go new file mode 100644 index 0000000..eb47391 --- /dev/null +++ b/internal/entity/relation.go @@ -0,0 +1,37 @@ +package entity + +import "time" + +type StatusSSR string + +const ( + Pending StatusSSR = "pending" + Rejected = "rejected" + Cancelled = "cancelled" + Accepted = "accepted" + Wip = "wip" + Completed = "done" +) + +type WaypointRelation struct { + *Waypoint + Status string `db:"waypoint_status"` + SsrID int `db:"ssr_id"` +} + +type Relation struct { + RelationID int `db:"ssr_id"` + CreatedAt time.Time `db:"created_at"` + Status string `db:"status"` + Supervisor `db:"sv"` + Student `db:"st"` + Work `db:"work"` +} + +type RelationShort struct { + RelationID int `db:"ssr_id"` + Status string `db:"status"` + SupervisorShort `db:"sv"` + StudentShort `db:"st"` + Work `db:"work"` +} diff --git a/internal/entity/ssr.go b/internal/entity/ssr.go deleted file mode 100644 index 790680f..0000000 --- a/internal/entity/ssr.go +++ /dev/null @@ -1,36 +0,0 @@ -package entity - -import "time" - -type StatusSSR string - -const ( - bidPending StatusSSR = "pending" - bidDeclined = "rejected" - bidCancelled = "cancelled" - bidAccepted = "accepted" - inProgress = "wip" - completed = "done" -) - -type WaypointSsr struct { - *Waypoint - Status string `db:"waypoint_status"` - SsrID int `db:"ssr_id"` -} - -type StudentSsr struct { - BidID int `db:"ssr_id"` - CreatedAt time.Time `db:"created_at"` - Status string `db:"ssr_status"` - *SupervisorProfile - *Work -} - -type SupervisorSsr struct { - BidID int `db:"ssr_id"` - CreatedAt time.Time `db:"created_at"` - Status string `db:"ssr_status"` - *StudentProfile - *Work -} diff --git a/internal/entity/student.go b/internal/entity/student.go new file mode 100644 index 0000000..48e15a8 --- /dev/null +++ b/internal/entity/student.go @@ -0,0 +1,14 @@ +package entity + +type StudentShort struct { + User UserShort `db:"user"` + Year int + DepartmentID string `db:"department_id"` +} + +type Student struct { + User User + StudentCard string `db:"student_card"` + Year int + DepartmentID string `db:"department_id"` +} diff --git a/internal/entity/subject.go b/internal/entity/subject.go index 9f8242d..29944fe 100644 --- a/internal/entity/subject.go +++ b/internal/entity/subject.go @@ -1,7 +1,7 @@ package entity type Subject struct { - SubjectID int `db:"subject_id"` - SubjectName string `db:"subject_name"` - DepartmentID string `db:"subject_department_id"` + SubjectID int `db:"subject_id"` + Name string + DepartmentID string `db:"department_id"` } diff --git a/internal/entity/supervisor.go b/internal/entity/supervisor.go new file mode 100644 index 0000000..e45bbe3 --- /dev/null +++ b/internal/entity/supervisor.go @@ -0,0 +1,15 @@ +package entity + +import "time" + +type SupervisorShort struct { + User UserShort `db:"user"` + DepartmentID string `db:"department_id"` +} + +type Supervisor struct { + User User `db:"user"` + Birthdate time.Time + About string + DepartmentID string `db:"department_id"` +} diff --git a/internal/entity/user.go b/internal/entity/user.go index d3b304e..a8d54d1 100644 --- a/internal/entity/user.go +++ b/internal/entity/user.go @@ -1,11 +1,32 @@ package entity -import "database/sql" +type UserRole string + +const ( + student UserRole = "st" + supervisor = "sv" +) + +type UserFull struct { + ID int `db:"id"` + Email string `db:"email"` + FirstName string `db:"first_name"` + LastName string `db:"last_name"` + PhotoUrl string `db:"photo_url"` + Role UserRole `db:"role"` + Password string `db:"password"` +} type User struct { - UserID int `db:"user_id"` - Email string `db:"email"` - FirstName string `db:"first_name"` - LastName string `db:"last_name"` - Avatar sql.NullString `db:"avatar_url"` + ID int `db:"id"` + Email string `db:"email"` + FirstName string `db:"first_name"` + LastName string `db:"last_name"` + PhotoUrl string `db:"photo_url"` +} + +type UserShort struct { + ID int `db:"id"` + FirstName string `db:"first_name"` + LastName string `db:"last_name"` } diff --git a/internal/entity/waypoint.go b/internal/entity/waypoint.go index adaa0d8..851d3e2 100644 --- a/internal/entity/waypoint.go +++ b/internal/entity/waypoint.go @@ -5,7 +5,9 @@ import ( ) type Waypoint struct { - WorkID int + WaypointID int `db:"waypoint_id"` + WorkID int `db:"work_id"` Deadline time.Time + Title string Description string } diff --git a/internal/entity/work.go b/internal/entity/work.go index 674aedc..57e5d57 100644 --- a/internal/entity/work.go +++ b/internal/entity/work.go @@ -1,25 +1,26 @@ package entity type WorkKind struct { - WorkKindID int `db:"work_kind_id"` - WorkKindName string `db:"work_kind_name"` + WorkKindID int `db:"work_kind_id"` + Name string } type Work struct { - *WorkKind - *Subject + WorkKind `db:"work_kind"` + Subject `db:"subject"` WorkID int `db:"work_id"` Description string Semester int8 } -type WorkOfSupervisor struct { - *Work - Head bool `db:"head"` +type SupervisorViewWork struct { + Work + IsHead bool `db:"is_head"` + IsFull bool `db:"is_full"` } -type SupervisorOfWork struct { - *SupervisorProfile - Head bool `db:"head"` - Full bool `db:"full"` +type WorkSupervisor struct { + Supervisor `db:"sv"` + IsHead bool `db:"is_head"` + IsFull bool `db:"is_full"` } diff --git a/internal/usecase/auth.go b/internal/service/auth.go similarity index 54% rename from internal/usecase/auth.go rename to internal/service/auth.go index 9a56d96..f809b87 100644 --- a/internal/usecase/auth.go +++ b/internal/service/auth.go @@ -1,4 +1,4 @@ -package usecase +package service import ( "github.com/golang-jwt/jwt" @@ -11,12 +11,12 @@ import ( type Auth struct { *Base - repo IRepoAuth + repo UserRepo tokenExp time.Duration signingKey []byte } -func NewAuth(r IRepoAuth, l logger.Interface, tokenExpMinutes int, signingKey []byte) *Auth { +func NewAuth(r UserRepo, l logger.Interface, tokenExpMinutes int, signingKey []byte) *Auth { return &Auth{ Base: NewBase(l), repo: r, @@ -25,29 +25,30 @@ func NewAuth(r IRepoAuth, l logger.Interface, tokenExpMinutes int, signingKey [] } } -func (uc *Auth) Login(email, password string) (*dto.LoginResponse, error) { - dbData, err := uc.repo.GetUserInfo(email) +func (service *Auth) Login(email, password string) (*dto.LoginResponse, error) { + dbData, err := service.repo.GetUserByEmail(email) if err != nil { return nil, err } if err = bcrypt.CompareHashAndPassword([]byte(dbData.Password), []byte(password)); err != nil { - uc.l.Error(err) + service.l.Error(err) return nil, err } - tokenClaims := misc.NewAppJWTClaims(uc.tokenExp, dbData.Email, string(dbData.Role)) + tokenClaims := misc.NewAppJWTClaims(service.tokenExp, dbData.ID, string(dbData.Role)) token := jwt.NewWithClaims(jwt.SigningMethodHS256, tokenClaims) - tokenStr, err := token.SignedString(uc.signingKey) + tokenStr, err := token.SignedString(service.signingKey) if err != nil { - uc.l.Error(err) + service.l.Error(err) return nil, err } return &dto.LoginResponse{ - Token: tokenStr, - Email: dbData.Email, - Role: string(dbData.Role), + Token: tokenStr, + TokenType: "Bearer", + UserID: dbData.ID, + Role: string(dbData.Role), }, nil } diff --git a/internal/usecase/base.go b/internal/service/base.go similarity index 89% rename from internal/usecase/base.go rename to internal/service/base.go index 44996eb..968b4f6 100644 --- a/internal/usecase/base.go +++ b/internal/service/base.go @@ -1,4 +1,4 @@ -package usecase +package service import ( "ssr/pkg/logger" diff --git a/internal/service/interfaces.go b/internal/service/interfaces.go new file mode 100644 index 0000000..cf1a424 --- /dev/null +++ b/internal/service/interfaces.go @@ -0,0 +1,35 @@ +package service + +import ( + "ssr/internal/entity" +) + +type ( + UserRepo interface { + GetUserByEmail(email string) (*entity.UserFull, error) + } + StudentRepo interface { + GetStudent(userID int) (*entity.Student, error) + GetStudentShort(userID int) (*entity.StudentShort, error) + } + SupervisorRepo interface { + GetSupervisor(userID int) (*entity.Supervisor, error) + GetSupervisorsByWorkID(workID int) ([]*entity.WorkSupervisor, error) + } + RelationRepo interface { + Create(studentID, supervisorID, workID int) (int, error) + GetRelationsByStudentID(studentID int) ([]*entity.RelationShort, error) + GetRelationsBySupervisorID(supervisorID int) ([]*entity.RelationShort, error) + Get(id int) (*entity.Relation, error) + Update(id int, status entity.StatusSSR) (int, error) + GetRelationStatus(studentID, workID int) (entity.StatusSSR, error) + } + WorkRepo interface { + Get(workID int) (*entity.Work, error) + GetStudentWorks(departmentID string, semester int) ([]*entity.Work, error) + GetSupervisorWorks(supervisorID int) ([]*entity.SupervisorViewWork, error) + } + WaypointRepo interface { + GetPlenty(workID int) ([]*entity.Waypoint, error) + } +) diff --git a/internal/service/profile.go b/internal/service/profile.go new file mode 100644 index 0000000..66e4399 --- /dev/null +++ b/internal/service/profile.go @@ -0,0 +1,55 @@ +package service + +import ( + "ssr/internal/dto" + "ssr/pkg/logger" + "ssr/pkg/misc" +) + +type Profile struct { + *Base + stRepo StudentRepo + svRepo SupervisorRepo +} + +func NewProfile(stRepo StudentRepo, svRepo SupervisorRepo, l logger.Interface) *Profile { + return &Profile{ + Base: NewBase(l), + stRepo: stRepo, + svRepo: svRepo, + } +} + +func (service *Profile) GetStudentProfile(userID int) (*dto.Student, error) { + dbData, err := service.stRepo.GetStudent(userID) + if err != nil { + return nil, err + } + + return &dto.Student{ + Email: dbData.User.Email, + FirstName: dbData.User.FirstName, + LastName: dbData.User.LastName, + PhotoUrl: dbData.User.PhotoUrl, + Year: dbData.Year, + StudentCard: dbData.StudentCard, + Department: dbData.DepartmentID, + }, nil +} + +func (service *Profile) GetSupervisorProfile(userID int) (*dto.Supervisor, error) { + dbData, err := service.svRepo.GetSupervisor(userID) + if err != nil { + return nil, err + } + + return &dto.Supervisor{ + Email: dbData.User.Email, + FirstName: dbData.User.FirstName, + LastName: dbData.User.LastName, + PhotoUrl: dbData.User.PhotoUrl, + About: dbData.About, + Birthdate: misc.Date{Time: dbData.Birthdate}, + Department: dbData.DepartmentID, + }, nil +} diff --git a/internal/service/relation.go b/internal/service/relation.go new file mode 100644 index 0000000..5fac7b8 --- /dev/null +++ b/internal/service/relation.go @@ -0,0 +1,161 @@ +package service + +import ( + "ssr/internal/dto" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/misc" +) + +type Relation struct { + *Base + repo RelationRepo +} + +func NewRelation(r RelationRepo, l logger.Interface) *Relation { + return &Relation{ + Base: NewBase(l), + repo: r, + } +} + +func (service *Relation) GetPlenty(studentID, supervisorID int) (*dto.RelationPlenty, error) { + var relations []*entity.RelationShort + var err error + + if studentID != 0 { + relations, err = service.repo.GetRelationsByStudentID(studentID) + } else { + relations, err = service.repo.GetRelationsBySupervisorID(supervisorID) + } + + if err != nil { + return nil, err + } + + var resp []*dto.RelationShortResp + + for _, db := range relations { + resp = append(resp, &dto.RelationShortResp{ + RelationID: db.RelationID, + Status: db.Status, + Supervisor: dto.SupervisorShort{ + UserID: db.SupervisorShort.User.ID, + FirstName: db.SupervisorShort.User.FirstName, + LastName: db.SupervisorShort.User.LastName, + }, + Student: dto.StudentShort{ + UserID: db.StudentShort.User.ID, + FirstName: db.StudentShort.User.FirstName, + LastName: db.StudentShort.User.LastName, + }, + Work: dto.WorkShortResp{ + WorkID: db.WorkID, + Kind: dto.WorkKindResp{ + ID: db.WorkKind.WorkKindID, + Name: db.WorkKind.Name, + }, + Subject: dto.SubjectResp{ + ID: db.SubjectID, + Name: db.Subject.Name, + Department: db.Subject.DepartmentID, + }, + }, + }) + } + + return &dto.RelationPlenty{Relations: resp}, nil +} + +func (service *Relation) Get(id int) (*dto.RelationResp, error) { + rel, err := service.repo.Get(id) + if err != nil { + return nil, err + } + + return &dto.RelationResp{ + RelationID: rel.RelationID, + Status: rel.Status, + Supervisor: dto.Supervisor{ + UserID: rel.Supervisor.User.ID, + Email: rel.Supervisor.User.Email, + FirstName: rel.Supervisor.User.FirstName, + LastName: rel.Supervisor.User.LastName, + About: rel.Supervisor.About, + Birthdate: misc.Date{Time: rel.Supervisor.Birthdate}, + PhotoUrl: rel.Supervisor.User.PhotoUrl, + Department: rel.Supervisor.DepartmentID, + }, + Work: dto.WorkResp{ + WorkID: rel.WorkID, + Kind: dto.WorkKindResp{ + ID: rel.WorkKind.WorkKindID, + Name: rel.WorkKind.Name, + }, + Subject: dto.SubjectResp{ + ID: rel.SubjectID, + Name: rel.Subject.Name, + Department: rel.Subject.DepartmentID, + }, + Description: rel.Work.Description, + Semester: rel.Work.Semester, + }, + Student: dto.Student{ + UserID: rel.Student.User.ID, + Email: rel.Student.User.Email, + FirstName: rel.Student.User.FirstName, + LastName: rel.Student.User.LastName, + PhotoUrl: rel.Student.User.PhotoUrl, + Year: rel.Student.Year, + StudentCard: rel.Student.StudentCard, + Department: rel.Student.DepartmentID, + }, + }, nil +} + +func (service *Relation) Create(data *dto.RelationCreateReq) (*dto.RelationCreateResp, error) { + relationID, err := service.repo.Create(data.StudentID, data.SupervisorID, data.WorkID) + if err != nil { + return nil, err + } + + return &dto.RelationCreateResp{RelationID: relationID}, nil +} + +func (service *Relation) Update(data *dto.RelationUpdateReq) (*dto.RelationResp, error) { + relationID, err := service.repo.Update(data.RelationID, data.Status) + if err != nil { + return nil, err + } + + relation, err := service.repo.Get(relationID) + + return &dto.RelationResp{ + RelationID: relation.RelationID, + Work: dto.WorkResp{ + WorkID: relation.Work.WorkID, + Description: relation.Work.Description, + Semester: relation.Semester, + Subject: dto.SubjectResp{ + ID: relation.Subject.SubjectID, + Name: relation.Subject.Name, + Department: relation.Subject.DepartmentID, + }, + Kind: dto.WorkKindResp{ + ID: relation.WorkKind.WorkKindID, + Name: relation.WorkKind.Name, + }, + }, + Student: dto.Student{ + UserID: relation.Student.User.ID, + Email: relation.Student.User.Email, + FirstName: relation.Student.User.FirstName, + LastName: relation.Student.User.LastName, + PhotoUrl: relation.Student.User.PhotoUrl, + Year: relation.Student.Year, + StudentCard: relation.Student.StudentCard, + Department: relation.Student.DepartmentID, + }, + Status: relation.Status, + }, nil +} diff --git a/internal/usecase/repo_pg/base.go b/internal/service/repo_pg/base.go similarity index 100% rename from internal/usecase/repo_pg/base.go rename to internal/service/repo_pg/base.go diff --git a/internal/service/repo_pg/relation.go b/internal/service/repo_pg/relation.go new file mode 100644 index 0000000..87f5934 --- /dev/null +++ b/internal/service/repo_pg/relation.go @@ -0,0 +1,226 @@ +package repo_pg + +import ( + "fmt" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/postgres" +) + +type Relation struct { + *BasePgRepo +} + +func NewRelation(pg *postgres.Postgres, l logger.Interface) *Relation { + return &Relation{ + BasePgRepo: NewPgRepo(pg, l), + } +} + +func (repo *Relation) Get(id int) (*entity.Relation, error) { + query := ` + select + ssr.ssr_id, + ssr.status, + ssr.created_at, + + sv.department_id as "sv.department_id", + sv.birthdate as "sv.birthdate", + sv.about as "sv.about", + + svu.id as "sv.user.id", + svu.email as "sv.user.email", + svu.last_name as "sv.user.last_name", + svu.first_name as "sv.user.first_name", + + st.year as "st.year", + st.department_id as "st.department_id", + + stu.id as "st.user.id", + stu.email as "st.user.email", + stu.last_name as "st.user.last_name", + stu.first_name as "st.user.first_name", + + w.semester as "work.semester", + w.description as "work.description", + w.work_id as "work.work_id", + wk.name as "work.work_kind.name", + wk.work_kind_id as "work.work_kind.work_kind_id", + + subj.subject_id as "work.subject.subject_id", + subj.name as "work.subject.name", + subj.department_id as "work.subject.department_id" + from ssr + join supervisors sv on ssr.supervisor_id = sv.user_id + join students st on ssr.student_id = st.user_id + join users stu on st.user_id = stu.id + join users svu on sv.user_id = svu.id + join works w using (work_id) + join work_kinds wk using (work_kind_id) + join subjects subj using (subject_id) + where ssr.ssr_id = $1; + ` + + relation := entity.Relation{} + + err := repo.Conn.Get(&relation, query, id) + if err != nil { + err := fmt.Errorf("Relation->Get->repo.Conn.Get: %w", err) + repo.l.Error(err) + return nil, err + } + + return &relation, nil +} + +func (repo *Relation) GetRelationsBySupervisorID(supervisorID int) ([]*entity.RelationShort, error) { + query := ` + select + ssr.ssr_id, + ssr.status, + + sv.department_id as "sv.department_id", + svu.id as "sv.user.id", + svu.last_name as "sv.user.last_name", + svu.first_name as "sv.user.first_name", + + st.year as "st.year", + st.department_id as "st.department_id", + stu.id as "st.user.id", + stu.last_name as "st.user.last_name", + stu.first_name as "st.user.first_name", + + w.semester as "work.semester", + w.description as "work.description", + w.work_id as "work.work_id", + wk.name as "work.work_kind.name", + wk.work_kind_id as "work.work_kind.work_kind_id", + + subj.subject_id as "work.subject.subject_id", + subj.name as "work.subject.name", + subj.department_id as "work.subject.department_id" + from ssr + join supervisors sv on ssr.supervisor_id = sv.user_id + join students st on ssr.student_id = st.user_id + join users stu on st.user_id = stu.id + join users svu on sv.user_id = svu.id + join works w using (work_id) + join work_kinds wk using (work_kind_id) + join subjects subj using (subject_id) + where ssr.supervisor_id = $1; + ` + + var relations []*entity.RelationShort + + err := repo.Conn.Select(&relations, query, supervisorID) + if err != nil { + err := fmt.Errorf("Relation->GetRelations->repo.Conn.Select: %w", err) + repo.l.Error(err) + return nil, err + } + + return relations, nil +} + +func (repo *Relation) GetRelationsByStudentID(studentID int) ([]*entity.RelationShort, error) { + query := ` + select + ssr.ssr_id, + ssr.status, + + sv.department_id as "sv.department_id", + svu.id as "sv.user.id", + svu.last_name as "sv.user.last_name", + svu.first_name as "sv.user.first_name", + + st.year as "st.year", + st.department_id as "st.department_id", + stu.id as "st.user.id", + stu.last_name as "st.user.last_name", + stu.first_name as "st.user.first_name", + + w.semester as "work.semester", + w.description as "work.description", + w.work_id as "work.work_id", + wk.name as "work.work_kind.name", + wk.work_kind_id as "work.work_kind.work_kind_id", + + subj.subject_id as "work.subject.subject_id", + subj.name as "work.subject.name", + subj.department_id as "work.subject.department_id" + from ssr + join supervisors sv on ssr.supervisor_id = sv.user_id + join students st on ssr.student_id = st.user_id + join users stu on st.user_id = stu.id + join users svu on sv.user_id = svu.id + join works w using (work_id) + join work_kinds wk using (work_kind_id) + join subjects subj using (subject_id) + where ssr.student_id = $1; + ` + + var relations []*entity.RelationShort + + err := repo.Conn.Select(&relations, query, studentID) + if err != nil { + err := fmt.Errorf("Relation->GetRelations->repo.Conn.Select: %w", err) + repo.l.Error(err) + return nil, err + } + + return relations, nil +} + +func (repo *Relation) Create(studentID, supervisorID, workID int) (int, error) { + query := ` + insert into ssr (student_id, supervisor_id, work_id) + values ($1, $2, $3) + returning ssr_id; + ` + + var relationID int + err := repo.Conn.QueryRowx(query, studentID, supervisorID, workID).Scan(&relationID) + if err != nil { + err := fmt.Errorf("RelationRepo->Create->repo.Conn.QueryRowx: %w", err) + repo.l.Error(err) + return 0, err + } + + return relationID, nil +} + +func (repo *Relation) Update(id int, status entity.StatusSSR) (int, error) { + query := ` + update ssr set status = $1 + where ssr_id = $2 + returning ssr_id; + ` + + var relationID int + err := repo.Conn.QueryRowx(query, status, id).Scan(&relationID) + if err != nil { + err := fmt.Errorf("Relation->Update->repo.Conn.QueryRowx: %w", err) + repo.l.Error(err) + return 0, err + } + + return relationID, nil +} + +func (repo *Relation) GetRelationStatus(studentID, workID int) (entity.StatusSSR, error) { + const query = ` + select ssr.status + from ssr where ssr.student_id = $1 and ssr.work_id = $2; + ` + + var status entity.StatusSSR + + err := repo.Conn.Get(&status, query, studentID, workID) + if err != nil { + err := fmt.Errorf("Relation->GetRelationStatus->r.Conn.Select: %w", err) + repo.l.Error(err) + return "", err + } + + return status, nil +} diff --git a/internal/service/repo_pg/student.go b/internal/service/repo_pg/student.go new file mode 100644 index 0000000..5d4f8c8 --- /dev/null +++ b/internal/service/repo_pg/student.go @@ -0,0 +1,71 @@ +package repo_pg + +import ( + "fmt" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/postgres" +) + +type Student struct { + *BasePgRepo +} + +func NewStudent(pg *postgres.Postgres, l logger.Interface) *Student { + return &Student{ + BasePgRepo: NewPgRepo(pg, l), + } +} + +func (repo *Student) GetStudentShort(userID int) (*entity.StudentShort, error) { + const query = ` + select + s.year, + s.department_id, + u.last_name as "user.last_name", + u.first_name as "user.first_name", + u.id as "user.id" + from students s + join users u on s.user_id = u.id + where u.id = $1 + ` + + student := entity.StudentShort{} + + err := repo.Conn.Get(&student, query, userID) + if err != nil { + err := fmt.Errorf("Student->Get->repo.Conn.Get(): %w", err) + repo.l.Error(err) + return nil, err + } + + return &student, nil +} + +func (repo *Student) GetStudent(userID int) (*entity.Student, error) { + const query = ` + select + s.student_card, + s.department_id, + s.year, + u.email as "user.email", + u.first_name as "user.first_name", + u.last_name as "user.last_name", + u.photo_url as "user.photo_url", + u.id as "user.id" + from users u + join students s on s.user_id = u.id + where u.id = $1 + ` + + studentFull := entity.Student{} + + err := repo.Conn.Get(&studentFull, query, userID) + if err != nil { + err := fmt.Errorf("Student->GetFull->repo.Conn.Get(): %w", err) + repo.l.Error(err) + return nil, err + } + + return &studentFull, nil +} diff --git a/internal/service/repo_pg/supervisor.go b/internal/service/repo_pg/supervisor.go new file mode 100644 index 0000000..ee0803d --- /dev/null +++ b/internal/service/repo_pg/supervisor.go @@ -0,0 +1,95 @@ +package repo_pg + +import ( + "fmt" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/postgres" +) + +type Supervisor struct { + *BasePgRepo +} + +func NewSupervisor(pg *postgres.Postgres, l logger.Interface) *Supervisor { + return &Supervisor{ + BasePgRepo: NewPgRepo(pg, l), + } +} + +func (repo *Supervisor) GetSupervisorShort(userID int) (*entity.SupervisorShort, error) { + const query = ` + select * from supervisors where user_id = $1 + ` + + supervisorShort := entity.SupervisorShort{} + + err := repo.Conn.Get(&supervisorShort, query, userID) + if err != nil { + err := fmt.Errorf("SupervisorShort->Get->repo.Conn.Get(): %w", err) + repo.l.Error(err) + return nil, err + } + + return &supervisorShort, nil +} + +func (repo *Supervisor) GetSupervisor(userID int) (*entity.Supervisor, error) { + const query = ` + select + s.about, + s.department_id, + s.birthdate, + u.email as "user.email", + u.first_name as "user.first_name", + u.last_name as "user.last_name", + u.photo_url as "user.photo_url", + u.id as "user.id" + from users u + join supervisors s on s.user_id = u.id + where u.id = $1 + ` + + supervisor := entity.Supervisor{} + + err := repo.Conn.Get(&supervisor, query, userID) + if err != nil { + err := fmt.Errorf("SupervisorShort->GetFull->repo.Conn.Get(): %w", err) + repo.l.Error(err) + return nil, err + } + + return &supervisor, nil +} + +func (repo *Supervisor) GetSupervisorsByWorkID(workID int) ([]*entity.WorkSupervisor, error) { + const query = ` + select + sv.about as "sv.about", + sv.birthdate as "sv.birthdate", + sv.department_id as "sv.department_id", + + u.id as "sv.user.id", + u.email as "sv.user.email", + u.first_name as "sv.user.first_name", + u.last_name as "sv.user.last_name", + u.photo_url as "sv.user.photo_url", + sw.is_full as is_full, + sw.is_head as is_head + from supervisors sv + join supervisor_work sw on sv.user_id = sw.supervisor_id + join users u on sv.user_id = u.id + where sw.work_id = $1; + ` + + var supervisors []*entity.WorkSupervisor + + err := repo.Conn.Select(&supervisors, query, workID) + if err != nil { + err := fmt.Errorf("Work->GetSupervisorsByWorkID->repo.Conn.Select: %w", err) + repo.l.Error(err) + return nil, err + } + + return supervisors, nil +} diff --git a/internal/service/repo_pg/user.go b/internal/service/repo_pg/user.go new file mode 100644 index 0000000..b9641b5 --- /dev/null +++ b/internal/service/repo_pg/user.go @@ -0,0 +1,63 @@ +package repo_pg + +import ( + "fmt" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/postgres" +) + +type User struct { + *BasePgRepo +} + +func NewUser(pg *postgres.Postgres, l logger.Interface) *User { + return &User{ + BasePgRepo: NewPgRepo(pg, l), + } +} + +func (r *User) CreateUser(email, password, firstName, lastName, photoUrl string, role entity.UserRole) error { + query := ` + insert into users (email, password, first_name, last_name, photo_url, role) + values ($1, $2, $3, $4, $5) + ` + + res, err := r.Conn.Exec(query, email, password, firstName, lastName, photoUrl, role) + + fmt.Println(res) //TODO + + if err != nil { + err := fmt.Errorf("Auth->Accept->repo.Conn.Exec: %w", err) + r.l.Error(err) // TODO + return err + } + + return nil +} + +func (r *User) GetUserByEmail(email string) (*entity.UserFull, error) { + user := entity.UserFull{} + + err := r.Conn.Get(&user, "select * from users where email = $1", email) + if err != nil { + err := fmt.Errorf("UserFull->r.Conn.Get(): %w", err) + r.l.Error(err) + return nil, err + } + + return &user, nil +} + +func (r *User) GetUserByID(userID int) (*entity.UserFull, error) { + auth := entity.UserFull{} + + err := r.Conn.Get(&auth, "select * from user where id = $1", userID) + if err != nil { + err := fmt.Errorf("UserFull->r.Conn.Get(): %w", err) + r.l.Error(err) + return nil, err + } + + return &auth, nil +} diff --git a/internal/service/repo_pg/waypoint.go b/internal/service/repo_pg/waypoint.go new file mode 100644 index 0000000..365c479 --- /dev/null +++ b/internal/service/repo_pg/waypoint.go @@ -0,0 +1,36 @@ +package repo_pg + +import ( + "fmt" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/postgres" +) + +type Waypoint struct { + *BasePgRepo +} + +func NewWaypointRepo(pg *postgres.Postgres, l logger.Interface) *Waypoint { + return &Waypoint{ + BasePgRepo: NewPgRepo(pg, l), + } +} + +func (repo *Waypoint) GetPlenty(workID int) ([]*entity.Waypoint, error) { + query := ` + select * from waypoints w + where w.work_id = $1; + ` + + var waypoints []*entity.Waypoint + + err := repo.Conn.Select(&waypoints, query, workID) + if err != nil { + err := fmt.Errorf("Waypoint->getPlenty->repo.Conn.Select: %w", err) + repo.l.Error(err) + return nil, err + } + + return waypoints, nil +} diff --git a/internal/service/repo_pg/work.go b/internal/service/repo_pg/work.go new file mode 100644 index 0000000..2d194ee --- /dev/null +++ b/internal/service/repo_pg/work.go @@ -0,0 +1,99 @@ +package repo_pg + +import ( + "fmt" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/postgres" +) + +type Work struct { + *BasePgRepo +} + +func NewWork(pg *postgres.Postgres, l logger.Interface) *Work { + return &Work{ + BasePgRepo: NewPgRepo(pg, l), + } +} + +func (repo *Work) GetStudentWorks(departmentID string, semester int) ([]*entity.Work, error) { + const query = ` + select w.work_id, w.description, w.semester, + wk.name as "work_kind.name", + wk.work_kind_id as "work_kind.work_kind_id", + subj.subject_id as "subject.subject_id", + subj.name as "subject.name", + subj.department_id as "subject.department_id" + from works w + join work_kinds wk using (work_kind_id) + join subjects subj using (subject_id) + where subj.department_id = $1 and w.semester = $2; + ` + + var works []*entity.Work + + err := repo.Conn.Select(&works, query, departmentID, semester) + if err != nil { + err := fmt.Errorf("Work->GetStudentWorks->repo.Conn.Select: %w", err) + repo.l.Error(err) + return nil, err + } + + return works, nil +} + +func (repo *Work) GetSupervisorWorks(supervisorID int) ([]*entity.SupervisorViewWork, error) { + const query = ` + select w.work_id, w.description, w.semester, + wk.name as "work_kind.name", + wk.work_kind_id as "work_kind.work_kind_id", + subj.subject_id as "subject.subject_id", + subj.name as "subject.name", + subj.department_id as "subject.department_id", + sw.is_head, + sw.is_full + from works w + join supervisor_work sw using (work_id) + join subjects subj using (subject_id) + join work_kinds wk using (work_kind_id) + where sw.supervisor_id = $1; + ` + var works []*entity.SupervisorViewWork + + err := repo.Conn.Select(&works, query, supervisorID) + if err != nil { + err := fmt.Errorf("Work->GetSupervisorWorks->repo.Conn.Select: %w", err) + repo.l.Error(err) + return nil, err + } + + return works, nil +} + +func (repo *Work) Get(workID int) (*entity.Work, error) { + const query = ` + select + w.work_id, w.description, w.semester, + wk.work_kind_id as "work_kind.work_kind_id", + wk.name as "work_kind.name", + s.subject_id as "subject.subject_id", + s.name as "subject.name", + s.department_id as "subject.department_id" + from works w + join work_kinds wk using ("work_kind_id") + join subjects s using ("subject_id") + where work_id = $1 + ` + + work := entity.Work{} + + err := repo.Conn.Get(&work, query, workID) + if err != nil { + err := fmt.Errorf("Work->Get->repo.Conn.Get(): %w", err) + repo.l.Error(err) + return nil, err + } + + return &work, nil +} diff --git a/internal/service/work.go b/internal/service/work.go new file mode 100644 index 0000000..b4cbca2 --- /dev/null +++ b/internal/service/work.go @@ -0,0 +1,179 @@ +package service + +import ( + "ssr/internal/dto" + "ssr/internal/entity" + "ssr/pkg/logger" + "ssr/pkg/misc" + "time" +) + +type Work struct { + *Base + workRepo WorkRepo + relationRepo RelationRepo + stRepo StudentRepo + svRepo SupervisorRepo + waypointRepo WaypointRepo +} + +func NewWork( + workRepo WorkRepo, + ssrRepo RelationRepo, + stRepo StudentRepo, + svRepo SupervisorRepo, + waypointRepo WaypointRepo, + l logger.Interface, +) *Work { + return &Work{ + Base: NewBase(l), + workRepo: workRepo, + relationRepo: ssrRepo, + stRepo: stRepo, + svRepo: svRepo, + waypointRepo: waypointRepo, + } +} + +func (service *Work) checkIfBegin(relations []*entity.Relation, workID int) bool { + for _, rel := range relations { + if rel.Work.WorkID == workID { + return true + } + } + + return false +} + +func (service *Work) recognizeSemester(studentYear int) int { + month := time.Now().Month() + if time.February <= month && month <= time.August { + return studentYear * 2 + } else { + return studentYear*2 - 1 + } +} + +func (service *Work) GetStudentWorks(studentID int) (*dto.StudentViewWorkPlenty, error) { + studentData, err := service.stRepo.GetStudentShort(studentID) + if err != nil { + return nil, err + } + + semester := service.recognizeSemester(studentData.Year) + + worksData, err := service.workRepo.GetStudentWorks(studentData.DepartmentID, semester) + if err != nil { + return nil, err + } + + var resp []*dto.StudentViewWorkShortResp + + for _, work := range worksData { + resp = append(resp, &dto.StudentViewWorkShortResp{ + Work: dto.WorkShortResp{ + WorkID: work.WorkID, + Subject: dto.SubjectResp{ + ID: work.Subject.SubjectID, + Name: work.Subject.Name, + Department: work.Subject.DepartmentID, + }, + Kind: dto.WorkKindResp{ + ID: work.WorkKind.WorkKindID, + Name: work.WorkKind.Name, + }, + }, + }) + } + + return &dto.StudentViewWorkPlenty{ + Works: resp, + }, nil +} + +func (service *Work) GetSupervisorWorks(supervisorID int) (*dto.SupervisorViewWorkPlenty, error) { + worksData, err := service.workRepo.GetSupervisorWorks(supervisorID) + if err != nil { + return nil, err + } + + var resp []*dto.SupervisorViewWorkShortResp + + for _, db := range worksData { + resp = append(resp, &dto.SupervisorViewWorkShortResp{ + Work: dto.WorkShortResp{ + WorkID: db.WorkID, + Subject: dto.SubjectResp{ + ID: db.Subject.SubjectID, + Name: db.Subject.Name, + Department: db.Subject.DepartmentID, + }, + Kind: dto.WorkKindResp{ + ID: db.WorkKind.WorkKindID, + Name: db.WorkKind.Name, + }, + }, + IsHead: db.IsHead, + IsFull: db.IsFull, + }) + } + + return &dto.SupervisorViewWorkPlenty{ + Works: resp, + }, nil +} + +func (service *Work) Get(workID int) (*dto.WorkFullResp, error) { + workData, err := service.workRepo.Get(workID) + if err != nil { + return nil, err + } + + waypointsData, err := service.waypointRepo.GetPlenty(workID) + if err != nil { + return nil, err + } + + var waypoints []*dto.WaypointResp + for _, waypointData := range waypointsData { + waypoints = append(waypoints, &dto.WaypointResp{ + Title: waypointData.Title, + Description: waypointData.Description, + Deadline: misc.Date{Time: waypointData.Deadline}, + }) + } + + supervisorsData, err := service.svRepo.GetSupervisorsByWorkID(workID) + if err != nil { + return nil, err + } + var supervisors []*dto.WorkSupervisorShort + for _, db := range supervisorsData { + supervisors = append(supervisors, &dto.WorkSupervisorShort{ + SupervisorShort: dto.SupervisorShort{ + UserID: db.Supervisor.User.ID, + FirstName: db.User.FirstName, + LastName: db.User.LastName, + }, + IsHead: db.IsHead, + IsFull: db.IsFull, + }) + } + + return &dto.WorkFullResp{ + WorkID: workData.WorkID, + Description: workData.Description, + Semester: workData.Semester, + Subject: dto.SubjectResp{ + ID: workData.Subject.SubjectID, + Name: workData.Subject.Name, + Department: workData.Subject.DepartmentID, + }, + Kind: dto.WorkKindResp{ + ID: workData.WorkKind.WorkKindID, + Name: workData.WorkKind.Name, + }, + Waypoints: waypoints, + Supervisors: supervisors, + }, nil +} diff --git a/internal/usecase/bid.go b/internal/usecase/bid.go deleted file mode 100644 index 491dacf..0000000 --- a/internal/usecase/bid.go +++ /dev/null @@ -1,123 +0,0 @@ -package usecase - -import ( - "ssr/internal/dto" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/misc" -) - -type Bid struct { - *Base - repo IRepoSSR -} - -func NewBid(r IRepoSSR, l logger.Interface) *Bid { - return &Bid{ - Base: NewBase(l), - repo: r, - } -} - -func (uc *Bid) GetStudentBids(studentID int) (*dto.StudentBids, error) { - dbData, err := uc.repo.GetStudentBids(studentID) - if err != nil { - return nil, err - } - - var resp []*dto.StudentBid - - for _, db := range dbData { - resp = append(resp, &dto.StudentBid{ - BidID: db.BidID, - Status: db.Status, - CreatedAt: db.CreatedAt, - Supervisor: dto.SupervisorProfile{ - SupervisorID: db.SupervisorID, - Email: db.Email, - FirstName: db.FirstName, - LastName: db.LastName, - About: db.About, - Birthdate: misc.Date{ - Time: db.Birthdate, - }, - AvatarUrl: misc.NullString(db.Avatar), - Department: db.SupervisorProfile.DepartmentID, - }, - Work: dto.Work{ - WorkID: db.WorkID, - Name: db.WorkKind.WorkKindName, - Description: db.Work.Description, - Semester: db.Work.Semester, - Subject: dto.SubjectResp{ - SubjectID: db.SubjectID, - Name: db.Subject.SubjectName, - Department: db.Subject.DepartmentID, - }, - }, - }) - } - - return &dto.StudentBids{Bids: resp}, nil -} - -func (uc *Bid) GetSupervisorBids(supervisorID int) (*dto.SupervisorBids, error) { - dbData, err := uc.repo.GetSupervisorBids(supervisorID) - if err != nil { - return nil, err - } - - var resp []*dto.SupervisorBid - - for _, db := range dbData { - resp = append(resp, &dto.SupervisorBid{ - BidID: db.BidID, - Status: db.Status, - CreatedAt: db.CreatedAt, - Student: dto.StudentProfile{ - StudentID: db.StudentID, - Email: db.Email, - FirstName: db.FirstName, - LastName: db.LastName, - Year: db.Year, - AvatarUrl: misc.NullString(db.Avatar), - Department: db.StudentProfile.DepartmentID, - }, - Work: dto.Work{ - WorkID: db.WorkID, - Name: db.WorkKind.WorkKindName, - Description: db.Work.Description, - Semester: db.Work.Semester, - Subject: dto.SubjectResp{ - SubjectID: db.SubjectID, - Name: db.Subject.SubjectName, - Department: db.Subject.DepartmentID, - }, - }, - }) - } - - return &dto.SupervisorBids{Bids: resp}, nil -} - -func (uc *Bid) Apply(data *dto.ApplyBid) (*dto.ApplyBidResponse, error) { - bidID, err := uc.repo.Create(data.StudentID, data.SupervisorID, data.WorkID) - if err != nil { - return nil, err - } - - return &dto.ApplyBidResponse{BidID: bidID}, nil -} - -func (uc *Bid) Resolve(data *dto.ResolveBid) error { - var status entity.StatusSSR - - if data.Accept { - status = "accepted" - } else { - status = "rejected" - } - - _, err := uc.repo.UpdateStatus(data.BidID, status) - return err -} diff --git a/internal/usecase/bid_test.go b/internal/usecase/bid_test.go deleted file mode 100644 index e89378b..0000000 --- a/internal/usecase/bid_test.go +++ /dev/null @@ -1,303 +0,0 @@ -package usecase - -// -//import ( -// "database/sql" -// "github.com/golang/mock/gomock" -// "reflect" -// "ssr/internal/dto" -// "ssr/internal/entity" -// "ssr/internal/usecase/mocks" -// "ssr/pkg/misc" -// "testing" -// "time" -//) -// -//func TestBidUseCase_Apply(t *testing.T) { -// type args struct { -// bid *dto.ApplyBid -// } -// tests := []struct { -// name string -// repository func(ctrl *gomock.Controller) *mocks.MockIRelRepo -// args args -// want *dto.ApplyBidResponse -// wantErr bool -// }{ -// { -// name: "success apply", -// repository: func(ctrl *gomock.Controller) *mocks.MockIRelRepo { -// m := mocks.NewMockIRelRepo(ctrl) -// m.EXPECT().Create(1, 1, 1).Return(1, nil) -// -// return m -// }, -// args: args{ -// bid: &dto.ApplyBid{ -// StudentID: 1, -// SupervisorID: 1, -// WorkID: 1, -// }, -// }, -// want: &dto.ApplyBidResponse{BidID: 1}, -// wantErr: false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// ctrl := gomock.NewController(t) -// -// u := NewBid(tt.repository(ctrl)) -// -// received, err := u.Apply(tt.args.bid) -// -// if (err != nil) != tt.wantErr { -// t.Errorf("Bid() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// if !reflect.DeepEqual(received, tt.want) { -// t.Errorf("Bid() got = %v, want %v", received, tt.want) -// } -// }) -// } -//} -// -//func TestBidUseCase_Resolve(t *testing.T) { -// type args struct { -// bid *dto.ResolveBid -// } -// tests := []struct { -// name string -// repository func(ctrl *gomock.Controller) *mocks.MockIRelRepo -// args args -// wantErr bool -// }{ -// { -// name: "accept success", -// repository: func(ctrl *gomock.Controller) *mocks.MockIRelRepo { -// m := mocks.NewMockIRelRepo(ctrl) -// m.EXPECT().UpdateStatus(1, entity.StatusSSR("accepted")).Return(1, nil) -// -// return m -// }, -// args: args{ -// bid: &dto.ResolveBid{ -// SupervisorID: 1, -// BidID: 1, -// Accept: true, -// }, -// }, -// wantErr: false, -// }, -// { -// name: "reject success", -// repository: func(ctrl *gomock.Controller) *mocks.MockIRelRepo { -// m := mocks.NewMockIRelRepo(ctrl) -// m.EXPECT().UpdateStatus(1, entity.StatusSSR("rejected")).Return(1, nil) -// -// return m -// }, -// args: args{ -// bid: &dto.ResolveBid{ -// SupervisorID: 1, -// BidID: 1, -// Accept: false, -// }, -// }, -// wantErr: false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// ctrl := gomock.NewController(t) -// -// u := NewBid(tt.repository(ctrl)) -// -// err := u.Resolve(tt.args.bid) -// -// if (err != nil) != tt.wantErr { -// t.Errorf("Bid() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// }) -// } -//} -// -//func TestSSRUseCase_Create(t *testing.T) { -// type args struct { -// req *dto.CreateSSR -// } -// tests := []struct { -// name string -// repository func(ctrl *gomock.Controller) *mocks.MockIRelRepo -// args args -// want *dto.StudentViewSSR -// wantErr bool -// }{ -// { -// name: "success ssr create", -// repository: func(ctrl *gomock.Controller) *mocks.MockIRelRepo { -// m := mocks.NewMockIRelRepo(ctrl) -// m.EXPECT().UpdateStatus(1, entity.StatusSSR("wip")).Return(1, nil) -// m.EXPECT().GetStudentViewSSR(1, 1).Return(&entity.StudentSsr{ -// BidID: 1, -// CreatedAt: time.Time{}, -// Status: "wip", -// SupervisorProfile: &entity.SupervisorProfile{ -// User: &entity.User{ -// UserID: 2, -// Email: "kek@kek.com", -// FirstName: "Иван", -// LastName: "Иванов", -// Avatar: sql.NullString{}, -// }, -// SupervisorID: 1, -// Birthdate: time.Time{}, -// About: "Обо мне", -// DepartmentID: "ИУ7", -// }, -// Work: &entity.Work{ -// WorkKind: &entity.WorkKind{ -// WorkKindID: 1, -// WorkKindName: "Курсовая работа", -// }, -// Subject: &entity.Subject{ -// SubjectID: 1, -// SubjectName: "Операционные системы", -// DepartmentID: "ИУ7", -// }, -// WorkID: 1, -// Description: "Работа для профи!", -// Semester: 7, -// }, -// }, nil) -// -// return m -// }, -// args: args{ -// req: &dto.CreateSSR{ -// StudentID: 1, -// BidID: 1, -// }, -// }, -// want: &dto.StudentViewSSR{ -// RelID: 1, -// Status: "wip", -// CreatedAt: time.Time{}, -// Supervisor: dto.SupervisorProfile{ -// SupervisorID: 1, -// Email: "kek@kek.com", -// FirstName: "Иван", -// LastName: "Иванов", -// About: "Обо мне", -// Birthdate: misc.Date{}, -// AvatarUrl: misc.NullString{}, -// Department: "ИУ7", -// }, -// Work: dto.Work{ -// WorkID: 1, -// Name: "Курсовая работа", -// Description: "Работа для профи!", -// Semester: 7, -// Subject: dto.SubjectResp{ -// SubjectID: 1, -// Name: "Операционные системы", -// Department: "ИУ7", -// }, -// }, -// }, -// wantErr: false, -// }, -// { -// name: "success ssr create", -// repository: func(ctrl *gomock.Controller) *mocks.MockIRelRepo { -// m := mocks.NewMockIRelRepo(ctrl) -// m.EXPECT().UpdateStatus(1, entity.StatusSSR("wip")).Return(1, nil) -// m.EXPECT().GetStudentViewSSR(1, 1).Return(&entity.StudentSsr{ -// BidID: 1, -// CreatedAt: time.Time{}, -// Status: "wip", -// SupervisorProfile: &entity.SupervisorProfile{ -// User: &entity.User{ -// UserID: 2, -// Email: "kek@kek.com", -// FirstName: "Иван", -// LastName: "Иванов", -// Avatar: sql.NullString{}, -// }, -// SupervisorID: 1, -// Birthdate: time.Time{}, -// About: "Обо мне", -// DepartmentID: "ИУ7", -// }, -// Work: &entity.Work{ -// WorkKind: &entity.WorkKind{ -// WorkKindID: 1, -// WorkKindName: "Курсовая работа", -// }, -// Subject: &entity.Subject{ -// SubjectID: 1, -// SubjectName: "Операционные системы", -// DepartmentID: "ИУ7", -// }, -// WorkID: 1, -// Description: "Работа для профи!", -// Semester: 7, -// }, -// }, nil) -// -// return m -// }, -// args: args{ -// req: &dto.CreateSSR{ -// StudentID: 1, -// BidID: 1, -// }, -// }, -// want: &dto.StudentViewSSR{ -// RelID: 1, -// Status: "wip", -// CreatedAt: time.Time{}, -// Supervisor: dto.SupervisorProfile{ -// SupervisorID: 1, -// Email: "kek@kek.com", -// FirstName: "Иван", -// LastName: "Иванов", -// About: "Обо мне", -// Birthdate: misc.Date{}, -// AvatarUrl: misc.NullString{}, -// Department: "ИУ7", -// }, -// Work: dto.Work{ -// WorkID: 1, -// Name: "Курсовая работа", -// Description: "Работа для профи!", -// Semester: 7, -// Subject: dto.SubjectResp{ -// SubjectID: 1, -// Name: "Операционные системы", -// Department: "ИУ7", -// }, -// }, -// }, -// wantErr: false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// ctrl := gomock.NewController(t) -// -// u := NewSSR(tt.repository(ctrl)) -// -// received, err := u.Create(tt.args.req) -// -// if (err != nil) != tt.wantErr { -// t.Errorf("Bid() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// if !reflect.DeepEqual(received, tt.want) { -// t.Errorf("Bid() got = %v, want %v", received, tt.want) -// } -// }) -// } -//} diff --git a/internal/usecase/feedback.go b/internal/usecase/feedback.go deleted file mode 100644 index 0f85760..0000000 --- a/internal/usecase/feedback.go +++ /dev/null @@ -1,45 +0,0 @@ -package usecase - -import ( - "ssr/internal/dto" - "ssr/pkg/logger" -) - -type Feedback struct { - *Base - repo IRepoFeedback -} - -func NewFeedback(r IRepoFeedback, l logger.Interface) *Feedback { - return &Feedback{ - Base: NewBase(l), - repo: r, - } -} - -func (uc *Feedback) Add(data *dto.FeedbackReq) (int, error) { - return uc.repo.Create(data.StudentID, data.SupervisorID, data.WorkID, data.Content) -} - -func (uc *Feedback) GetOnSupervisor(supervisorID int) (*dto.FeedbackPlenty, error) { - dbData, err := uc.repo.GetBySupervisorID(supervisorID) - if err != nil { - return nil, err - } - - var resp []*dto.FeedbackResp - - for _, db := range dbData { - resp = append(resp, &dto.FeedbackResp{ - StudentID: db.StudentID, - StudentFullName: db.StudentFullName, - SupervisorID: db.SupervisorID, - WorkID: db.WorkID, - WorkKind: db.WorkKind, - WorkSubject: db.WorkSubject, - Content: db.Content, - }) - } - - return &dto.FeedbackPlenty{Feedbacks: resp}, nil -} diff --git a/internal/usecase/interfaces.go b/internal/usecase/interfaces.go deleted file mode 100644 index ab5d869..0000000 --- a/internal/usecase/interfaces.go +++ /dev/null @@ -1,68 +0,0 @@ -package usecase - -import ( - "ssr/internal/dto" - "ssr/internal/entity" -) - -type ( - IRepoAuth interface { - GetUserInfo(email string) (*entity.Auth, error) - } - IUsecaseAuth interface { - Login(email, password string) (*dto.LoginResponse, error) - } - - IRepoProfile interface { - GetStudentProfile(email string) (*entity.StudentProfile, error) - GetSupervisorProfile(email string) (*entity.SupervisorProfile, error) - } - IUsecaseProfile interface { - GetStudentProfile(email string) (*dto.StudentProfile, error) - GetSupervisorProfile(email string) (*dto.SupervisorProfile, error) - } - - IRepoSSR interface { - Create(studentID, supervisorID, workID int) (int, error) - GetStudentBids(studentID int) ([]*entity.StudentSsr, error) - GetSupervisorBids(studentID int) ([]*entity.SupervisorSsr, error) - GetStudentRelations(studentID int) ([]*entity.StudentSsr, error) - GetStudentRelation(studentID, ssrID int) (*entity.StudentSsr, error) - UpdateStatus(id int, newStatus entity.StatusSSR) (int, error) - } - - IUsecaseStudentBid interface { - GetStudentBids(studentID int) (*dto.StudentBids, error) - Apply(data *dto.ApplyBid) (*dto.ApplyBidResponse, error) - } - IUseCaseSupervisorBid interface { - GetSupervisorBids(supervisorID int) (*dto.SupervisorBids, error) - Resolve(data *dto.ResolveBid) error - } - - IUseCaseStudentRelation interface { - Create(data *dto.CreateSSR) (*dto.StudentViewSSR, error) - } - - IRepoWork interface { - GetWorksByStudentID(studentID int) ([]*entity.Work, error) - GetWorksBySupervisorID(supervisorID int) ([]*entity.WorkOfSupervisor, error) - GetSupervisorsByWorkID(workID int) ([]*entity.SupervisorOfWork, error) - } - IStudentWorkUC interface { - GetStudentWorks(studentID int) (*dto.StudentWorks, error) - GetWorkSupervisors(workID int) (*dto.WorkSupervisorPlenty, error) - } - ISupervisorWorkUC interface { - GetSupervisorWorks(supervisorID int) (*dto.SupervisorWorkPlenty, error) - } - - IUsecaseFeedback interface { - Add(data *dto.FeedbackReq) (int, error) - GetOnSupervisor(supervisorID int) (*dto.FeedbackPlenty, error) - } - IRepoFeedback interface { - Create(studentID, supervisorID, workID int, content string) (int, error) - GetBySupervisorID(supervisorID int) ([]*entity.Feedback, error) - } -) diff --git a/internal/usecase/mocks/bid.go b/internal/usecase/mocks/bid.go deleted file mode 100644 index 8096230..0000000 --- a/internal/usecase/mocks/bid.go +++ /dev/null @@ -1,595 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: internal/usecase/interfaces.go - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - dto "ssr/internal/dto" - entity "ssr/internal/entity" - - gomock "github.com/golang/mock/gomock" -) - -// MockIAuthRepo is a mock of IAuthRepo interface. -type MockIAuthRepo struct { - ctrl *gomock.Controller - recorder *MockIAuthRepoMockRecorder -} - -// MockIAuthRepoMockRecorder is the mock recorder for MockIAuthRepo. -type MockIAuthRepoMockRecorder struct { - mock *MockIAuthRepo -} - -// NewMockIAuthRepo creates a new mock instance. -func NewMockIAuthRepo(ctrl *gomock.Controller) *MockIAuthRepo { - mock := &MockIAuthRepo{ctrl: ctrl} - mock.recorder = &MockIAuthRepoMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIAuthRepo) EXPECT() *MockIAuthRepoMockRecorder { - return m.recorder -} - -// Get mocks base method. -func (m *MockIAuthRepo) GetUserInfo(email string) (*entity.Auth, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUserInfo", email) - ret0, _ := ret[0].(*entity.Auth) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockIAuthRepoMockRecorder) Get(email interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserInfo", reflect.TypeOf((*MockIAuthRepo)(nil).GetUserInfo), email) -} - -// MockIAuthUC is a mock of IAuthUC interface. -type MockIAuthUC struct { - ctrl *gomock.Controller - recorder *MockIAuthUCMockRecorder -} - -// MockIAuthUCMockRecorder is the mock recorder for MockIAuthUC. -type MockIAuthUCMockRecorder struct { - mock *MockIAuthUC -} - -// NewMockIAuthUC creates a new mock instance. -func NewMockIAuthUC(ctrl *gomock.Controller) *MockIAuthUC { - mock := &MockIAuthUC{ctrl: ctrl} - mock.recorder = &MockIAuthUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIAuthUC) EXPECT() *MockIAuthUCMockRecorder { - return m.recorder -} - -// Login mocks base method. -func (m *MockIAuthUC) Login(email, password string) (*dto.LoginResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Login", email, password) - ret0, _ := ret[0].(*dto.LoginResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Login indicates an expected call of Login. -func (mr *MockIAuthUCMockRecorder) Login(email, password interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Login", reflect.TypeOf((*MockIAuthUC)(nil).Login), email, password) -} - -// MockIProfileRepo is a mock of IProfileRepo interface. -type MockIProfileRepo struct { - ctrl *gomock.Controller - recorder *MockIProfileRepoMockRecorder -} - -// MockIProfileRepoMockRecorder is the mock recorder for MockIProfileRepo. -type MockIProfileRepoMockRecorder struct { - mock *MockIProfileRepo -} - -// NewMockIProfileRepo creates a new mock instance. -func NewMockIProfileRepo(ctrl *gomock.Controller) *MockIProfileRepo { - mock := &MockIProfileRepo{ctrl: ctrl} - mock.recorder = &MockIProfileRepoMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIProfileRepo) EXPECT() *MockIProfileRepoMockRecorder { - return m.recorder -} - -// GetStudentProfile mocks base method. -func (m *MockIProfileRepo) GetStudentProfile(email string) (*entity.StudentProfile, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStudentProfile", email) - ret0, _ := ret[0].(*entity.StudentProfile) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStudentProfile indicates an expected call of GetStudentProfile. -func (mr *MockIProfileRepoMockRecorder) GetStudentProfile(email interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStudentProfile", reflect.TypeOf((*MockIProfileRepo)(nil).GetStudentProfile), email) -} - -// GetSupervisorProfile mocks base method. -func (m *MockIProfileRepo) GetSupervisorProfile(email string) (*entity.SupervisorProfile, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSupervisorProfile", email) - ret0, _ := ret[0].(*entity.SupervisorProfile) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSupervisorProfile indicates an expected call of GetSupervisorProfile. -func (mr *MockIProfileRepoMockRecorder) GetSupervisorProfile(email interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupervisorProfile", reflect.TypeOf((*MockIProfileRepo)(nil).GetSupervisorProfile), email) -} - -// MockIProfileUC is a mock of IProfileUC interface. -type MockIProfileUC struct { - ctrl *gomock.Controller - recorder *MockIProfileUCMockRecorder -} - -// MockIProfileUCMockRecorder is the mock recorder for MockIProfileUC. -type MockIProfileUCMockRecorder struct { - mock *MockIProfileUC -} - -// NewMockIProfileUC creates a new mock instance. -func NewMockIProfileUC(ctrl *gomock.Controller) *MockIProfileUC { - mock := &MockIProfileUC{ctrl: ctrl} - mock.recorder = &MockIProfileUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIProfileUC) EXPECT() *MockIProfileUCMockRecorder { - return m.recorder -} - -// GetStudentProfile mocks base method. -func (m *MockIProfileUC) GetStudentProfile(email string) (*dto.StudentProfile, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStudentProfile", email) - ret0, _ := ret[0].(*dto.StudentProfile) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStudentProfile indicates an expected call of GetStudentProfile. -func (mr *MockIProfileUCMockRecorder) GetStudentProfile(email interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStudentProfile", reflect.TypeOf((*MockIProfileUC)(nil).GetStudentProfile), email) -} - -// GetSupervisorProfile mocks base method. -func (m *MockIProfileUC) GetSupervisorProfile(email string) (*dto.SupervisorProfile, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSupervisorProfile", email) - ret0, _ := ret[0].(*dto.SupervisorProfile) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSupervisorProfile indicates an expected call of GetSupervisorProfile. -func (mr *MockIProfileUCMockRecorder) GetSupervisorProfile(email interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupervisorProfile", reflect.TypeOf((*MockIProfileUC)(nil).GetSupervisorProfile), email) -} - -// MockIRelRepo is a mock of IRelRepo interface. -type MockIRelRepo struct { - ctrl *gomock.Controller - recorder *MockIRelRepoMockRecorder -} - -// MockIRelRepoMockRecorder is the mock recorder for MockIRelRepo. -type MockIRelRepoMockRecorder struct { - mock *MockIRelRepo -} - -// NewMockIRelRepo creates a new mock instance. -func NewMockIRelRepo(ctrl *gomock.Controller) *MockIRelRepo { - mock := &MockIRelRepo{ctrl: ctrl} - mock.recorder = &MockIRelRepoMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIRelRepo) EXPECT() *MockIRelRepoMockRecorder { - return m.recorder -} - -// Create mocks base method. -func (m *MockIRelRepo) Create(studentID, supervisorID, workID int) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Create", studentID, supervisorID, workID) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Create indicates an expected call of Create. -func (mr *MockIRelRepoMockRecorder) Create(studentID, supervisorID, workID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockIRelRepo)(nil).Create), studentID, supervisorID, workID) -} - -// GetStudentViewBidPlenty mocks base method. -func (m *MockIRelRepo) GetStudentViewBidPlenty(studentID int) ([]*entity.StudentSsr, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStudentBids", studentID) - ret0, _ := ret[0].([]*entity.StudentSsr) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStudentViewBidPlenty indicates an expected call of GetStudentViewBidPlenty. -func (mr *MockIRelRepoMockRecorder) GetStudentViewBidPlenty(studentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStudentBids", reflect.TypeOf((*MockIRelRepo)(nil).GetStudentViewBidPlenty), studentID) -} - -// GetStudentViewSSR mocks base method. -func (m *MockIRelRepo) GetStudentViewSSR(studentID, ssrID int) (*entity.StudentSsr, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStudentRelation", studentID, ssrID) - ret0, _ := ret[0].(*entity.StudentSsr) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStudentViewSSR indicates an expected call of GetStudentViewSSR. -func (mr *MockIRelRepoMockRecorder) GetStudentViewSSR(studentID, ssrID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStudentRelation", reflect.TypeOf((*MockIRelRepo)(nil).GetStudentViewSSR), studentID, ssrID) -} - -// GetSupervisorViewBidPlenty mocks base method. -func (m *MockIRelRepo) GetSupervisorViewBidPlenty(studentID int) ([]*entity.SupervisorSsr, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSupervisorBids", studentID) - ret0, _ := ret[0].([]*entity.SupervisorSsr) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSupervisorViewBidPlenty indicates an expected call of GetSupervisorViewBidPlenty. -func (mr *MockIRelRepoMockRecorder) GetSupervisorViewBidPlenty(studentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupervisorBids", reflect.TypeOf((*MockIRelRepo)(nil).GetSupervisorViewBidPlenty), studentID) -} - -// UpdateStatus mocks base method. -func (m *MockIRelRepo) UpdateStatus(id int, newStatus entity.StatusSSR) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateStatus", id, newStatus) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateStatus indicates an expected call of UpdateStatus. -func (mr *MockIRelRepoMockRecorder) UpdateStatus(id, newStatus interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockIRelRepo)(nil).UpdateStatus), id, newStatus) -} - -// MockIStudentBidUC is a mock of IStudentBidUC interface. -type MockIStudentBidUC struct { - ctrl *gomock.Controller - recorder *MockIStudentBidUCMockRecorder -} - -// MockIStudentBidUCMockRecorder is the mock recorder for MockIStudentBidUC. -type MockIStudentBidUCMockRecorder struct { - mock *MockIStudentBidUC -} - -// NewMockIStudentBidUC creates a new mock instance. -func NewMockIStudentBidUC(ctrl *gomock.Controller) *MockIStudentBidUC { - mock := &MockIStudentBidUC{ctrl: ctrl} - mock.recorder = &MockIStudentBidUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIStudentBidUC) EXPECT() *MockIStudentBidUCMockRecorder { - return m.recorder -} - -// Apply mocks base method. -func (m *MockIStudentBidUC) Apply(data *dto.ApplyBid) (*dto.ApplyBidResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Apply", data) - ret0, _ := ret[0].(*dto.ApplyBidResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Apply indicates an expected call of Apply. -func (mr *MockIStudentBidUCMockRecorder) Apply(data interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockIStudentBidUC)(nil).Apply), data) -} - -// GetStudentBids mocks base method. -func (m *MockIStudentBidUC) GetStudentBids(studentID int) (*dto.StudentBids, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStudentBids", studentID) - ret0, _ := ret[0].(*dto.StudentBids) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStudentBids indicates an expected call of GetStudentBids. -func (mr *MockIStudentBidUCMockRecorder) GetStudentBids(studentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStudentBids", reflect.TypeOf((*MockIStudentBidUC)(nil).GetStudentBids), studentID) -} - -// MockISupervisorBidUC is a mock of ISupervisorBidUC interface. -type MockISupervisorBidUC struct { - ctrl *gomock.Controller - recorder *MockISupervisorBidUCMockRecorder -} - -// MockISupervisorBidUCMockRecorder is the mock recorder for MockISupervisorBidUC. -type MockISupervisorBidUCMockRecorder struct { - mock *MockISupervisorBidUC -} - -// NewMockISupervisorBidUC creates a new mock instance. -func NewMockISupervisorBidUC(ctrl *gomock.Controller) *MockISupervisorBidUC { - mock := &MockISupervisorBidUC{ctrl: ctrl} - mock.recorder = &MockISupervisorBidUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockISupervisorBidUC) EXPECT() *MockISupervisorBidUCMockRecorder { - return m.recorder -} - -// GetSupervisorBids mocks base method. -func (m *MockISupervisorBidUC) GetSupervisorBids(supervisorID int) (*dto.SupervisorBids, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSupervisorBids", supervisorID) - ret0, _ := ret[0].(*dto.SupervisorBids) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSupervisorBids indicates an expected call of GetSupervisorBids. -func (mr *MockISupervisorBidUCMockRecorder) GetSupervisorBids(supervisorID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupervisorBids", reflect.TypeOf((*MockISupervisorBidUC)(nil).GetSupervisorBids), supervisorID) -} - -// Resolve mocks base method. -func (m *MockISupervisorBidUC) Resolve(data *dto.ResolveBid) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Resolve", data) - ret0, _ := ret[0].(error) - return ret0 -} - -// Resolve indicates an expected call of Resolve. -func (mr *MockISupervisorBidUCMockRecorder) Resolve(data interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Resolve", reflect.TypeOf((*MockISupervisorBidUC)(nil).Resolve), data) -} - -// MockIStudentRelUC is a mock of IStudentRelUC interface. -type MockIStudentRelUC struct { - ctrl *gomock.Controller - recorder *MockIStudentRelUCMockRecorder -} - -// MockIStudentRelUCMockRecorder is the mock recorder for MockIStudentRelUC. -type MockIStudentRelUCMockRecorder struct { - mock *MockIStudentRelUC -} - -// NewMockIStudentRelUC creates a new mock instance. -func NewMockIStudentRelUC(ctrl *gomock.Controller) *MockIStudentRelUC { - mock := &MockIStudentRelUC{ctrl: ctrl} - mock.recorder = &MockIStudentRelUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIStudentRelUC) EXPECT() *MockIStudentRelUCMockRecorder { - return m.recorder -} - -// Create mocks base method. -func (m *MockIStudentRelUC) Create(data *dto.CreateSSR) (*dto.StudentViewSSR, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Create", data) - ret0, _ := ret[0].(*dto.StudentViewSSR) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Create indicates an expected call of Create. -func (mr *MockIStudentRelUCMockRecorder) Create(data interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockIStudentRelUC)(nil).Create), data) -} - -// MockIWorkRepo is a mock of IWorkRepo interface. -type MockIWorkRepo struct { - ctrl *gomock.Controller - recorder *MockIWorkRepoMockRecorder -} - -// MockIWorkRepoMockRecorder is the mock recorder for MockIWorkRepo. -type MockIWorkRepoMockRecorder struct { - mock *MockIWorkRepo -} - -// NewMockIWorkRepo creates a new mock instance. -func NewMockIWorkRepo(ctrl *gomock.Controller) *MockIWorkRepo { - mock := &MockIWorkRepo{ctrl: ctrl} - mock.recorder = &MockIWorkRepoMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIWorkRepo) EXPECT() *MockIWorkRepoMockRecorder { - return m.recorder -} - -// GetSupervisorsByWorkID mocks base method. -func (m *MockIWorkRepo) GetSupervisorsByWorkID(workID int) ([]*entity.SupervisorOfWork, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSupervisorsByWorkID", workID) - ret0, _ := ret[0].([]*entity.SupervisorOfWork) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSupervisorsByWorkID indicates an expected call of GetSupervisorsByWorkID. -func (mr *MockIWorkRepoMockRecorder) GetSupervisorsByWorkID(workID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupervisorsByWorkID", reflect.TypeOf((*MockIWorkRepo)(nil).GetSupervisorsByWorkID), workID) -} - -// GetWorksByStudentID mocks base method. -func (m *MockIWorkRepo) GetWorksByStudentID(studentID int) ([]*entity.Work, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWorksByStudentID", studentID) - ret0, _ := ret[0].([]*entity.Work) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetWorksByStudentID indicates an expected call of GetWorksByStudentID. -func (mr *MockIWorkRepoMockRecorder) GetWorksByStudentID(studentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorksByStudentID", reflect.TypeOf((*MockIWorkRepo)(nil).GetWorksByStudentID), studentID) -} - -// GetWorksBySupervisorID mocks base method. -func (m *MockIWorkRepo) GetWorksBySupervisorID(supervisorID int) ([]*entity.WorkOfSupervisor, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWorksBySupervisorID", supervisorID) - ret0, _ := ret[0].([]*entity.WorkOfSupervisor) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetWorksBySupervisorID indicates an expected call of GetWorksBySupervisorID. -func (mr *MockIWorkRepoMockRecorder) GetWorksBySupervisorID(supervisorID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorksBySupervisorID", reflect.TypeOf((*MockIWorkRepo)(nil).GetWorksBySupervisorID), supervisorID) -} - -// MockIStudentWorkUC is a mock of IStudentWorkUC interface. -type MockIStudentWorkUC struct { - ctrl *gomock.Controller - recorder *MockIStudentWorkUCMockRecorder -} - -// MockIStudentWorkUCMockRecorder is the mock recorder for MockIStudentWorkUC. -type MockIStudentWorkUCMockRecorder struct { - mock *MockIStudentWorkUC -} - -// NewMockIStudentWorkUC creates a new mock instance. -func NewMockIStudentWorkUC(ctrl *gomock.Controller) *MockIStudentWorkUC { - mock := &MockIStudentWorkUC{ctrl: ctrl} - mock.recorder = &MockIStudentWorkUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIStudentWorkUC) EXPECT() *MockIStudentWorkUCMockRecorder { - return m.recorder -} - -// GetStudentWorks mocks base method. -func (m *MockIStudentWorkUC) GetStudentWorks(studentID int) (*dto.StudentWorks, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStudentWorks", studentID) - ret0, _ := ret[0].(*dto.StudentWorks) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStudentWorks indicates an expected call of GetStudentWorks. -func (mr *MockIStudentWorkUCMockRecorder) GetStudentWorks(studentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStudentWorks", reflect.TypeOf((*MockIStudentWorkUC)(nil).GetStudentWorks), studentID) -} - -// GetWorkSupervisors mocks base method. -func (m *MockIStudentWorkUC) GetWorkSupervisors(workID int) (*dto.WorkSupervisorPlenty, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWorkSupervisors", workID) - ret0, _ := ret[0].(*dto.WorkSupervisorPlenty) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetWorkSupervisors indicates an expected call of GetWorkSupervisors. -func (mr *MockIStudentWorkUCMockRecorder) GetWorkSupervisors(workID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkSupervisors", reflect.TypeOf((*MockIStudentWorkUC)(nil).GetWorkSupervisors), workID) -} - -// MockISupervisorWorkUC is a mock of ISupervisorWorkUC interface. -type MockISupervisorWorkUC struct { - ctrl *gomock.Controller - recorder *MockISupervisorWorkUCMockRecorder -} - -// MockISupervisorWorkUCMockRecorder is the mock recorder for MockISupervisorWorkUC. -type MockISupervisorWorkUCMockRecorder struct { - mock *MockISupervisorWorkUC -} - -// NewMockISupervisorWorkUC creates a new mock instance. -func NewMockISupervisorWorkUC(ctrl *gomock.Controller) *MockISupervisorWorkUC { - mock := &MockISupervisorWorkUC{ctrl: ctrl} - mock.recorder = &MockISupervisorWorkUCMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockISupervisorWorkUC) EXPECT() *MockISupervisorWorkUCMockRecorder { - return m.recorder -} - -// GetSupervisorWorks mocks base method. -func (m *MockISupervisorWorkUC) GetSupervisorWorks(supervisorID int) (*dto.SupervisorWorkPlenty, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSupervisorWorks", supervisorID) - ret0, _ := ret[0].(*dto.SupervisorWorkPlenty) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSupervisorWorks indicates an expected call of GetSupervisorWorks. -func (mr *MockISupervisorWorkUCMockRecorder) GetSupervisorWorks(supervisorID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupervisorWorks", reflect.TypeOf((*MockISupervisorWorkUC)(nil).GetSupervisorWorks), supervisorID) -} diff --git a/internal/usecase/profile.go b/internal/usecase/profile.go deleted file mode 100644 index b8e9b66..0000000 --- a/internal/usecase/profile.go +++ /dev/null @@ -1,55 +0,0 @@ -package usecase - -import ( - "ssr/internal/dto" - "ssr/pkg/logger" - "ssr/pkg/misc" -) - -type Profile struct { - *Base - repo IRepoProfile -} - -func NewProfile(r IRepoProfile, l logger.Interface) *Profile { - return &Profile{ - Base: NewBase(l), - repo: r, - } -} - -func (uc *Profile) GetStudentProfile(email string) (*dto.StudentProfile, error) { - dbData, err := uc.repo.GetStudentProfile(email) - if err != nil { - return nil, err - } - - return &dto.StudentProfile{ - StudentID: dbData.StudentID, - Email: dbData.Email, - FirstName: dbData.FirstName, - LastName: dbData.LastName, - AvatarUrl: misc.NullString(dbData.Avatar), - Year: dbData.Year, - StudentCard: dbData.StudentCard, - Department: dbData.DepartmentID, - }, nil -} - -func (uc *Profile) GetSupervisorProfile(email string) (*dto.SupervisorProfile, error) { - dbData, err := uc.repo.GetSupervisorProfile(email) - if err != nil { - return nil, err - } - - return &dto.SupervisorProfile{ - SupervisorID: dbData.SupervisorID, - Email: dbData.Email, - FirstName: dbData.FirstName, - LastName: dbData.LastName, - AvatarUrl: misc.NullString(dbData.Avatar), - About: dbData.About, - Birthdate: misc.Date{Time: dbData.Birthdate}, - Department: dbData.DepartmentID, - }, nil -} diff --git a/internal/usecase/repo_pg/auth.go b/internal/usecase/repo_pg/auth.go deleted file mode 100644 index 7ed6616..0000000 --- a/internal/usecase/repo_pg/auth.go +++ /dev/null @@ -1,31 +0,0 @@ -package repo_pg - -import ( - "fmt" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/postgres" -) - -type AuthPgRepo struct { - *BasePgRepo -} - -func NewAuthPgRepo(pg *postgres.Postgres, l logger.Interface) *AuthPgRepo { - return &AuthPgRepo{ - BasePgRepo: NewPgRepo(pg, l), - } -} - -func (r *AuthPgRepo) GetUserInfo(email string) (*entity.Auth, error) { - auth := entity.Auth{} - - err := r.Conn.Get(&auth, "select * from auth where email = $1", email) - if err != nil { - err := fmt.Errorf("AuthPgRepo->r.Conn.Get(): %w", err) - r.l.Error(err) - return nil, err - } - - return &auth, nil -} diff --git a/internal/usecase/repo_pg/feedback.go b/internal/usecase/repo_pg/feedback.go deleted file mode 100644 index 9bd41e1..0000000 --- a/internal/usecase/repo_pg/feedback.go +++ /dev/null @@ -1,63 +0,0 @@ -package repo_pg - -import ( - "fmt" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/postgres" -) - -type Feedback struct { - *BasePgRepo -} - -func NewFeedback(pg *postgres.Postgres, l logger.Interface) *Feedback { - return &Feedback{ - BasePgRepo: NewPgRepo(pg, l), - } -} - -func (f *Feedback) Create(studentID, supervisorID, workID int, content string) (int, error) { - query := ` - insert into feedbacks (student_id, supervisor_id, work_id, content) - values ($1, $2, $3, $4) - returning feedback_id; - ` - - var feedbackID int - err := f.Conn.QueryRowx(query, studentID, supervisorID, workID, content).Scan(&feedbackID) - if err != nil { - err := fmt.Errorf("repo_pg.Feedback->Create->r.Conn.QueryRowx: %w", err) - f.l.Error(err) - return 0, err - } - - return feedbackID, nil -} - -func (f *Feedback) GetBySupervisorID(supervisorID int) ([]*entity.Feedback, error) { - query := ` - select - f.*, - concat (u.first_name, ' ', u.last_name) AS student_full_name, - wk.name as work_kind, - subj.name as work_subject - from feedbacks f - join students s using (student_id) - join users u using (user_id) - join works w using (work_id) - join work_kinds wk using (work_kind_id) - join subjects subj using (subject_id) - where f.supervisor_id = $1 - ` - - var feedbacks []*entity.Feedback - - if err := f.Conn.Select(&feedbacks, query, supervisorID); err != nil { - err := fmt.Errorf("repo_pg.Feedback->GetBySupervisorID->r.Conn.Select: %w", err) - f.l.Error(err) - return nil, err - } - - return feedbacks, nil -} diff --git a/internal/usecase/repo_pg/profile.go b/internal/usecase/repo_pg/profile.go deleted file mode 100644 index fc35131..0000000 --- a/internal/usecase/repo_pg/profile.go +++ /dev/null @@ -1,58 +0,0 @@ -package repo_pg - -import ( - "fmt" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/postgres" -) - -type ProfilePgRepo struct { - *BasePgRepo -} - -func NewProfilePgRepo(pg *postgres.Postgres, l logger.Interface) *ProfilePgRepo { - return &ProfilePgRepo{ - BasePgRepo: NewPgRepo(pg, l), - } -} - -func (r *ProfilePgRepo) GetStudentProfile(email string) (*entity.StudentProfile, error) { - const query = ` - select * - from users u - join students s using (user_id) - where email = $1 - ` - - student := entity.StudentProfile{} - - err := r.Conn.Get(&student, query, email) - if err != nil { - err := fmt.Errorf("ProfilePgRepo->GetStudentProfile->r.Conn.Get(): %w", err) - r.l.Error(err) - return nil, err - } - - return &student, nil -} - -func (r *ProfilePgRepo) GetSupervisorProfile(email string) (*entity.SupervisorProfile, error) { - const query = ` - select * - from users u - join supervisors s using (user_id) - where email = $1 - ` - - supervisor := entity.SupervisorProfile{} - - err := r.Conn.Get(&supervisor, query, email) - if err != nil { - err := fmt.Errorf("ProfilePgRepo->GetSupervisorProfile->r.Conn.Get(): %w", err) - r.l.Error(err) - return nil, err - } - - return &supervisor, nil -} diff --git a/internal/usecase/repo_pg/ssr.go b/internal/usecase/repo_pg/ssr.go deleted file mode 100644 index c8b93f0..0000000 --- a/internal/usecase/repo_pg/ssr.go +++ /dev/null @@ -1,185 +0,0 @@ -package repo_pg - -import ( - "fmt" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/postgres" -) - -type SsrPgRepo struct { - *BasePgRepo -} - -func NewSSRPgRepo(pg *postgres.Postgres, l logger.Interface) *SsrPgRepo { - return &SsrPgRepo{ - BasePgRepo: NewPgRepo(pg, l), - } -} - -func (r *SsrPgRepo) GetStudentRelation(studentID, ssrID int) (*entity.StudentSsr, error) { - query := ` - select - ssr.ssr_id, - ssr.status as ssr_status, - ssr.created_at, - sv.*, - u.*, - w.*, - wk.name as work_kind_name, - subj.name as subject_name, - subj.department_id as subject_department_id - from ssr - join supervisors sv using (supervisor_id) - join users u using (user_id) - join works w using (work_id) - join work_kinds wk using (work_kind_id) - join subjects subj using (subject_id) - where ssr.ssr_id = $1 and ssr.student_id = $2; - ` - ssr := entity.StudentSsr{} - - err := r.Conn.Get(&ssr, query, ssrID, studentID) - if err != nil { - err := fmt.Errorf("SsrPgRepo->GetStudentRelation->r.Conn.Get: %w", err) - r.l.Error(err) - return nil, err - } - - return &ssr, nil -} - -func (r *SsrPgRepo) GetStudentBids(studentID int) ([]*entity.StudentSsr, error) { - query := ` - select - ssr.ssr_id, - ssr.status as ssr_status, - ssr.created_at, - sv.*, - u.*, - w.*, - wk.name as work_kind_name, - subj.name as subject_name, - subj.department_id as subject_department_id - from ssr - join supervisors sv using (supervisor_id) - join users u using (user_id) - join works w using (work_id) - join work_kinds wk using (work_kind_id) - join subjects subj using (subject_id) - where ssr.status in ('pending','rejected', 'cancelled','accepted') and ssr.student_id = $1; - ` - - var bids []*entity.StudentSsr - - err := r.Conn.Select(&bids, query, studentID) - if err != nil { - err := fmt.Errorf("SsrPgRepo->GetStudentBids->r.Conn.Select: %w", err) - r.l.Error(err) - return nil, err - } - - return bids, nil -} - -func (r *SsrPgRepo) GetStudentRelations(studentID int) ([]*entity.StudentSsr, error) { - query := ` - select - ssr.ssr_id, - ssr.status as ssr_status, - ssr.created_at, - sv.*, - u.*, - w.*, - wk.name as work_kind_name, - subj.name as subject_name, - subj.department_id as subject_department_id - from ssr - join supervisors sv using (supervisor_id) - join users u using (user_id) - join works w using (work_id) - join work_kinds wk using (work_kind_id) - join subjects subj using (subject_id) - where ssr.status in ('wip', 'done') and ssr.student_id = $1; - ` - - var bids []*entity.StudentSsr - - err := r.Conn.Select(&bids, query, studentID) - if err != nil { - err := fmt.Errorf("SsrPgRepo->GetStudentBids->r.Conn.Select: %w", err) - r.l.Error(err) - return nil, err - } - - return bids, nil -} - -func (r *SsrPgRepo) GetSupervisorBids(supervisorID int) ([]*entity.SupervisorSsr, error) { - query := ` - select - ssr.ssr_id, - ssr.status as ssr_status, - ssr.created_at, - st.*, - u.*, - w.*, - wk.name as work_kind_name, - subj.name as subject_name, - subj.department_id as subject_department_id - from ssr - join students st using (student_id) - join users u using (user_id) - join works w using (work_id) - join work_kinds wk using (work_kind_id) - join subjects subj using (subject_id) - where ssr.status in ('pending','rejected', 'cancelled','accepted') and ssr.supervisor_id = $1; - ` - - var bids []*entity.SupervisorSsr - - err := r.Conn.Select(&bids, query, supervisorID) - if err != nil { - err := fmt.Errorf("SsrPgRepo->GetSupervisorBids->r.Conn.Select: %w", err) - r.l.Error(err) - return nil, err - } - - return bids, nil -} - -func (r *SsrPgRepo) Create(studentID, supervisorID, workID int) (int, error) { - query := ` - insert into ssr (student_id, supervisor_id, work_id) - values ($1, $2, $3) - returning ssr_id; - ` - - var bidID int - err := r.Conn.QueryRowx(query, studentID, supervisorID, workID).Scan(&bidID) - if err != nil { - err := fmt.Errorf("SsrPgRepo->Create->r.Conn.QueryRowx: %w", err) - r.l.Error(err) - return 0, err - } - - return bidID, nil -} - -func (r *SsrPgRepo) UpdateStatus(id int, newStatus entity.StatusSSR) (int, error) { - query := ` - update ssr set status = $1 - where ssr_id = $2 - returning ssr_id; - ` - - var bidID int - err := r.Conn.QueryRowx(query, newStatus, id).Scan(&bidID) - if err != nil { - err := fmt.Errorf("SsrPgRepo->UpdateStatus->r.Conn.QueryRowx: %w", err) - r.l.Error(err) - return 0, err - } - - return bidID, nil -} diff --git a/internal/usecase/repo_pg/work.go b/internal/usecase/repo_pg/work.go deleted file mode 100644 index 8c5a94a..0000000 --- a/internal/usecase/repo_pg/work.go +++ /dev/null @@ -1,101 +0,0 @@ -package repo_pg - -import ( - "fmt" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/postgres" -) - -type WorkPgRepo struct { - *BasePgRepo -} - -func NewWorkPgRepo(pg *postgres.Postgres, l logger.Interface) *WorkPgRepo { - return &WorkPgRepo{ - BasePgRepo: NewPgRepo(pg, l), - } -} - -func (r *WorkPgRepo) GetWorksByStudentID(studentID int) ([]*entity.Work, error) { - const query = ` - with const (st_year, st_department_id, curr_month) as ( - select s.year, - s.department_id, - extract('month' from current_date) - from students s - where student_id = $1 - ) - select w.*, - wk.name as work_kind_name, - subj.name as subject_name - from works w - join work_kinds wk using (work_kind_id) - join subjects subj using (subject_id) - join const c on true - where (((curr_month between 2 and 8) and (semester = st_year * 2)) - or (semester = st_year * 2 - 1)) - and subj.department_id = c.st_department_id; - ` - - var works []*entity.Work - - err := r.Conn.Select(&works, query, studentID) - if err != nil { - err := fmt.Errorf("WorkPgRepo->GetWorksByStudentID->r.Conn.Select: %w", err) - r.l.Error(err) - return nil, err - } - - return works, nil -} - -func (r *WorkPgRepo) GetWorksBySupervisorID(supervisorID int) ([]*entity.WorkOfSupervisor, error) { - const query = ` - select w.*, - subj.name as subject_name, - wk.name as work_kind_name, - sw.is_head as head - from works w - join supervisor_work sw using (work_id) - join supervisors s using (supervisor_id) - join subjects subj using (subject_id) - join work_kinds wk using (work_kind_id) - where s.supervisor_id = $1; - ` - var works []*entity.WorkOfSupervisor - - err := r.Conn.Select(&works, query, supervisorID) - if err != nil { - err := fmt.Errorf("WorkPgRepo->GetWorksBySupervisorID->r.Conn.Select: %w", err) - r.l.Error(err) - return nil, err - } - - return works, nil -} - -func (r *WorkPgRepo) GetSupervisorsByWorkID(workID int) ([]*entity.SupervisorOfWork, error) { - const query = ` - select - u.*, - sv.*, - sw.is_full as "full", - sw.is_head as head - from supervisors sv - join supervisor_work sw using (supervisor_id) - join users u using (user_id) - where sw.work_id = $1; - ` - - var supervisors []*entity.SupervisorOfWork - - err := r.Conn.Select(&supervisors, query, workID) - if err != nil { - err := fmt.Errorf("WorkPgRepo->GetSupervisorsByWorkID->r.Conn.Select: %w", err) - r.l.Error(err) - return nil, err - } - - return supervisors, nil -} diff --git a/internal/usecase/ssr.go b/internal/usecase/ssr.go deleted file mode 100644 index e066e05..0000000 --- a/internal/usecase/ssr.go +++ /dev/null @@ -1,73 +0,0 @@ -package usecase - -import ( - "ssr/internal/dto" - "ssr/pkg/logger" - "ssr/pkg/misc" -) - -type SSR struct { - *Base - repo IRepoSSR -} - -func NewSSR(r IRepoSSR, l logger.Interface) *SSR { - return &SSR{ - Base: NewBase(l), - repo: r, - } -} - -func (uc *SSR) CheckIfStudentBeginWork(studentID, workID int) (bool, error) { - relations, err := uc.repo.GetStudentRelations(studentID) - if err != nil { - return false, err - } - - for _, rel := range relations { - if rel.Work.WorkID == workID { - return true, nil - } - } - - return false, nil -} - -func (uc *SSR) Create(data *dto.CreateSSR) (*dto.StudentViewSSR, error) { - ssrID, err := uc.repo.UpdateStatus(data.BidID, "wip") - if err != nil { - return nil, err - } - - ssr, err := uc.repo.GetStudentRelation(data.StudentID, ssrID) - if err != nil { - return nil, err - } - - return &dto.StudentViewSSR{ - RelID: ssr.BidID, - Status: ssr.Status, - CreatedAt: ssr.CreatedAt, - Supervisor: dto.SupervisorProfile{ - SupervisorID: ssr.SupervisorID, - Email: ssr.SupervisorProfile.Email, - FirstName: ssr.SupervisorProfile.FirstName, - LastName: ssr.SupervisorProfile.LastName, - About: ssr.SupervisorProfile.About, - Birthdate: misc.Date{Time: ssr.Birthdate}, - AvatarUrl: misc.NullString(ssr.Avatar), - Department: ssr.DepartmentID, - }, - Work: dto.Work{ - WorkID: ssr.WorkID, - Name: ssr.Work.WorkKindName, - Description: ssr.Work.Description, - Semester: ssr.Work.Semester, - Subject: dto.SubjectResp{ - SubjectID: ssr.SubjectID, - Name: ssr.SubjectName, - Department: ssr.DepartmentID, - }, - }, - }, nil -} diff --git a/internal/usecase/work.go b/internal/usecase/work.go deleted file mode 100644 index 6569f60..0000000 --- a/internal/usecase/work.go +++ /dev/null @@ -1,116 +0,0 @@ -package usecase - -import ( - "ssr/internal/dto" - "ssr/internal/entity" - "ssr/pkg/logger" - "ssr/pkg/misc" -) - -type Work struct { - *Base - repoWork IRepoWork - repoSsr IRepoSSR -} - -func NewWork(rWork IRepoWork, rSsr IRepoSSR, l logger.Interface) *Work { - return &Work{ - Base: NewBase(l), - repoWork: rWork, - repoSsr: rSsr, - } -} - -func checkIfBegin(relations []*entity.StudentSsr, workID int) bool { - for _, rel := range relations { - if rel.Work.WorkID == workID { - return true - } - } - - return false -} - -func (uc *Work) GetStudentWorks(studentID int) (*dto.StudentWorks, error) { - dbData, err := uc.repoWork.GetWorksByStudentID(studentID) - if err != nil { - return nil, err - } - - relations, err := uc.repoSsr.GetStudentRelations(studentID) - if err != nil { - return nil, err - } - - var resp []*dto.StudentWork - - for _, db := range dbData { - resp = append(resp, &dto.StudentWork{ - WorkID: db.WorkID, - Kind: db.WorkKindName, - Description: db.Description, - Subject: db.SubjectName, - IsStarted: checkIfBegin(relations, db.WorkID), - }) - } - - return &dto.StudentWorks{ - StudentID: studentID, - Works: resp, - }, nil -} - -func (uc *Work) GetSupervisorWorks(supervisorID int) (*dto.SupervisorWorkPlenty, error) { - dbData, err := uc.repoWork.GetWorksBySupervisorID(supervisorID) - if err != nil { - return nil, err - } - - var resp []*dto.SupervisorWork - - for _, db := range dbData { - resp = append(resp, &dto.SupervisorWork{ - WorkID: db.WorkID, - Kind: db.WorkKindName, - Description: db.Description, - Subject: db.SubjectName, - Head: db.Head, - }) - } - - return &dto.SupervisorWorkPlenty{ - SupervisorID: supervisorID, - Works: resp, - }, nil -} - -func (uc *Work) GetWorkSupervisors(workID int) (*dto.WorkSupervisorPlenty, error) { - dbData, err := uc.repoWork.GetSupervisorsByWorkID(workID) - if err != nil { - return nil, err - } - - var resp []*dto.WorkSupervisor - - for _, db := range dbData { - resp = append(resp, &dto.WorkSupervisor{ - SupervisorProfile: dto.SupervisorProfile{ - SupervisorID: db.SupervisorID, - Email: db.Email, - FirstName: db.FirstName, - LastName: db.LastName, - About: db.About, - Birthdate: misc.Date{Time: db.Birthdate}, - AvatarUrl: misc.NullString(db.Avatar), - Department: db.DepartmentID, - }, - Head: db.Head, - Full: db.Full, - }) - } - - return &dto.WorkSupervisorPlenty{ - WorkID: workID, - Supervisors: resp, - }, nil -} diff --git a/migrations/20220508102907_create_users.up.sql b/migrations/20220508102907_create_users.up.sql index 5ea92e5..c3589ab 100644 --- a/migrations/20220508102907_create_users.up.sql +++ b/migrations/20220508102907_create_users.up.sql @@ -1,39 +1,28 @@ CREATE TYPE "user_role" AS ENUM ( - 'student', - 'supervisor' + 'st', + 'sv', + 'su' ); CREATE TABLE "users" ( - "user_id" bigint generated always as identity unique, + "id" bigint generated always as identity unique, "email" varchar unique not null, + "is_active" bool not null default true, "first_name" varchar not null, "last_name" varchar not null, - "avatar_url" varchar + "photo_url" varchar not null, + "role" user_role not null, + "created_at" timestamp not null default now(), + "last_login" timestamp default now(), + "password" varchar not null ); -CREATE TABLE "auth" -( - "email" varchar PRIMARY KEY, - "password" varchar not null, - "role" user_role -); - -ALTER TABLE "users" - ADD FOREIGN KEY ("email") REFERENCES "auth" ("email"); - -insert into auth (email, password, role) -VALUES ('viktor1970@example.org', '$2b$12$kXlvD8/GSm/ZLEEjPFS0peiPEz.AEh5byuNIqZvFyu7bW6R5RxcJy', 'student'), - ('komarovmina@example.org', '$2b$12$xfWQ1aLcxliWgiNj8pKyOOTqOaUjQV5YMSb7whSNKb.Liejt3ae8u', 'supervisor'), - ('jakov2001@example.org', '$2b$12$qhTeWstBv035IIbUXYM8I.pGnvMS0spDQqUM/OdpIUsmt6cFU.4P2', 'supervisor'), - ('mina1988@example.org', '$2b$12$H7iWpTmqm.2OcsosP8CseOM/XCDP2.y0en.X..nZcbtvQ9EBZ0Pg2', 'supervisor'), - ('ipat1974@example.net', '$2b$12$Zq11QMZNcC/9IxquRrqMwuWh1ijHx.k83McMe6pM2Jtf8LXbZ.a66', 'student'), - ('kopilovfoka@example.org', '$2b$12$MjWCy0Ka0n9QLm12cCJVjuReCykhbBfXck.Jt.VPkYgKQZ/SPwlbK', 'student'); -insert into users (email, first_name, last_name, avatar_url) -VALUES ('viktor1970@example.org', 'Дмитрий', 'Ивахненко', NULL), - ('komarovmina@example.org', 'Наташа', 'Рязанова', NULL), - ('mina1988@example.org', 'Кирилл', 'Тассов', NULL), - ('jakov2001@example.org', 'Андрей', 'Куров', NULL), - ('ipat1974@example.net', 'Максим', 'Борисов', NULL), - ('kopilovfoka@example.org', 'Дмитрий', 'Варин', NULL); +insert into users (email, first_name, last_name, photo_url, role, password) +VALUES ('viktor1970@example.org', 'Дмитрий', 'Ивахненко', '', 'st', '$2b$12$kXlvD8/GSm/ZLEEjPFS0peiPEz.AEh5byuNIqZvFyu7bW6R5RxcJy'), + ('komarovmina@example.org', 'Наташа', 'Рязанова', '', 'sv', '$2b$12$xfWQ1aLcxliWgiNj8pKyOOTqOaUjQV5YMSb7whSNKb.Liejt3ae8u'), + ('mina1988@example.org', 'Кирилл', 'Тассов', '', 'sv', '$2b$12$qhTeWstBv035IIbUXYM8I.pGnvMS0spDQqUM/OdpIUsmt6cFU.4P2'), + ('jakov2001@example.org', 'Андрей', 'Куров', '', 'sv', '$2b$12$H7iWpTmqm.2OcsosP8CseOM/XCDP2.y0en.X..nZcbtvQ9EBZ0Pg2'), + ('ipat1974@example.net', 'Максим', 'Борисов', '', 'st', '$2b$12$Zq11QMZNcC/9IxquRrqMwuWh1ijHx.k83McMe6pM2Jtf8LXbZ.a66'), + ('kopilovfoka@example.org', 'Дмитрий', 'Варин', '', 'st', '$2b$12$MjWCy0Ka0n9QLm12cCJVjuReCykhbBfXck.Jt.VPkYgKQZ/SPwlbK'); diff --git a/migrations/20220509115124_create_students.up.sql b/migrations/20220509115124_create_students.up.sql index 88c4c92..374dabc 100644 --- a/migrations/20220509115124_create_students.up.sql +++ b/migrations/20220509115124_create_students.up.sql @@ -1,20 +1,17 @@ CREATE TABLE "students" ( - "student_id" bigint unique generated always as identity, + "user_id" bigint primary key unique not null, "student_card" varchar unique not null, "year" int not null, - "user_id" bigint not null, "department_id" varchar not null ); ALTER TABLE "students" - ADD FOREIGN KEY ("user_id") REFERENCES "users" ("user_id"); - -ALTER TABLE "students" + ADD FOREIGN KEY ("user_id") REFERENCES "users" ("id"), ADD FOREIGN KEY ("department_id") REFERENCES "departments" ("department_id"); -insert into "students" (student_card, year, user_id, department_id) -VALUES ('ida19u463', 3, 1, 'ИУ7'), - ('bma19u463', 3, 5, 'ИУ7'), - ('vdv19u463', 3, 6, 'ИУ7'); +insert into "students" (user_id, student_card, year, department_id) +VALUES (1, 'ida19u463', 4, 'ИУ7'), + (5, 'bma19u463', 4, 'ИУ7'), + (6, 'vdv19u463', 4, 'ИУ7'); diff --git a/migrations/20220509192451_create_supervisors.up.sql b/migrations/20220509192451_create_supervisors.up.sql index 2166aa8..ad44da7 100644 --- a/migrations/20220509192451_create_supervisors.up.sql +++ b/migrations/20220509192451_create_supervisors.up.sql @@ -1,21 +1,18 @@ CREATE TABLE "supervisors" ( - "supervisor_id" bigint unique generated always as identity, - "birthdate" date not null, - "about" varchar not null, - "user_id" bigint not null, - "department_id" varchar not null + "user_id" bigint primary key not null, + "birthdate" date not null, + "about" text not null, + "department_id" varchar not null ); ALTER TABLE "supervisors" - ADD FOREIGN KEY ("user_id") REFERENCES "users" ("user_id"); - -ALTER TABLE "supervisors" + ADD FOREIGN KEY ("user_id") REFERENCES "users" ("id"), ADD FOREIGN KEY ("department_id") REFERENCES "departments" ("department_id"); -insert into "supervisors" (birthdate, about, user_id, department_id) -VALUES ('01-01-1956', 'Заслуженный программист СССР. Профессионал.', 2, 'ИУ7'), - ('01-01-1998', 'Лучшие анекдоты тут!', 3, 'ИУ7'), - ('01-01-1801', 'Нуууииитоживашщши слаувваа', 4 , 'ИУ7'); +insert into "supervisors" (user_id, birthdate, about, department_id) +VALUES (2, '01-01-1956', 'Заслуженный программист СССР. Профессионал.', 'ИУ7'), + (3, '01-01-1998', 'Лучшие анекдоты тут!', 'ИУ7'), + (4, '01-01-1801', 'Нуууииитоживашщши слаувваа' , 'ИУ7'); diff --git a/migrations/20220509193416_create_subjects.up.sql b/migrations/20220509193416_create_subjects.up.sql index a3dbb92..e682483 100644 --- a/migrations/20220509193416_create_subjects.up.sql +++ b/migrations/20220509193416_create_subjects.up.sql @@ -11,5 +11,5 @@ ALTER TABLE "subjects" insert into subjects (name, department_id) VALUES ('Операционные системы', 'ИУ7'), - ('Компьютерная графика', 'ИУ7'); + ('НИР', 'ИУ7'); diff --git a/migrations/20220509194216_create_works.up.sql b/migrations/20220509194216_create_works.up.sql index 5914c0d..718ffba 100644 --- a/migrations/20220509194216_create_works.up.sql +++ b/migrations/20220509194216_create_works.up.sql @@ -14,9 +14,7 @@ CREATE TABLE "works" ); ALTER TABLE "works" - ADD FOREIGN KEY ("subject_id") REFERENCES "subjects" ("subject_id"); - -ALTER TABLE "works" + ADD FOREIGN KEY ("subject_id") REFERENCES "subjects" ("subject_id"), ADD FOREIGN KEY ("work_kind_id") REFERENCES "work_kinds" ("work_kind_id"); @@ -25,5 +23,5 @@ VALUES ('Курсовая работа'), ('Научно-исследовательская работа'); insert into "works" (work_kind_id, description, semester, subject_id) -VALUES (1, 'Только для истинных профессионалов', 6, 1), - (2, 'Брезенхем за 20 минту', 6, 2); \ No newline at end of file +VALUES (1, 'Только для истинных профессионалов', 7, 1), + (2, 'Готовься к ВКР', 7, 2); \ No newline at end of file diff --git a/migrations/20220509195738_create_sv_work.up.sql b/migrations/20220509195738_create_sv_work.up.sql index 5976649..5647f45 100644 --- a/migrations/20220509195738_create_sv_work.up.sql +++ b/migrations/20220509195738_create_sv_work.up.sql @@ -1,5 +1,6 @@ CREATE TABLE "supervisor_work" ( + "id" bigint generated always as identity unique, "work_id" bigint not null, "supervisor_id" bigint not null, "is_head" bool, @@ -8,16 +9,15 @@ CREATE TABLE "supervisor_work" ALTER TABLE "supervisor_work" - ADD FOREIGN KEY ("work_id") REFERENCES "works" ("work_id"); - -ALTER TABLE "supervisor_work" - ADD FOREIGN KEY ("supervisor_id") REFERENCES "supervisors" ("supervisor_id"); + ADD FOREIGN KEY ("work_id") REFERENCES "works" ("work_id"), + ADD FOREIGN KEY ("supervisor_id") REFERENCES "supervisors" ("user_id"); +CREATE UNIQUE INDEX ON supervisor_work (work_id, supervisor_id); insert into "supervisor_work" (work_id, supervisor_id, is_head) -VALUES (1, 1, true), - (1, 2, false), +VALUES (1, 2, true), (1, 3, false), - (2, 1, false), + (1, 4, false), (2, 2, false), - (2, 3, true); \ No newline at end of file + (2, 3, false), + (2, 4, true); \ No newline at end of file diff --git a/migrations/20220509200350_create_ssr.up.sql b/migrations/20220509200350_create_ssr.up.sql index 2375d46..95de616 100644 --- a/migrations/20220509200350_create_ssr.up.sql +++ b/migrations/20220509200350_create_ssr.up.sql @@ -20,17 +20,15 @@ CREATE TABLE "ssr" ALTER TABLE "ssr" - ADD FOREIGN KEY ("work_id") REFERENCES "works" ("work_id"); - -ALTER TABLE "ssr" - ADD FOREIGN KEY ("supervisor_id") REFERENCES "supervisors" ("supervisor_id"); - -ALTER TABLE "ssr" - ADD FOREIGN KEY ("student_id") REFERENCES "students" ("student_id"); - -ALTER TABLE ssr + ADD FOREIGN KEY ("work_id") REFERENCES "works" ("work_id"), + ADD FOREIGN KEY ("supervisor_id") REFERENCES "supervisors" ("user_id"), + ADD FOREIGN KEY ("student_id") REFERENCES "students" ("user_id"), ADD CONSTRAINT ssr_unique_members_constraint UNIQUE (work_id, supervisor_id, student_id); CREATE INDEX ON "ssr" (status, supervisor_id); CREATE INDEX ON "ssr" (status, student_id); CREATE INDEX ON "ssr" (status, work_id); + + +insert into ssr(status, created_at, supervisor_id, work_id, student_id) + VALUES ('pending', '2022-09-01', 2, 1, 1) diff --git a/migrations/20220606071757_create_feedbacks.down.sql b/migrations/20220606071757_create_feedbacks.down.sql deleted file mode 100644 index 37e8098..0000000 --- a/migrations/20220606071757_create_feedbacks.down.sql +++ /dev/null @@ -1 +0,0 @@ -drop table "feedbacks" cascade; \ No newline at end of file diff --git a/migrations/20220606071757_create_feedbacks.up.sql b/migrations/20220606071757_create_feedbacks.up.sql deleted file mode 100644 index bffbc15..0000000 --- a/migrations/20220606071757_create_feedbacks.up.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE "feedbacks" -( - "feedback_id" bigint unique generated always as identity, - "work_id" bigint not null, - "created_at" timestamp default now(), - "supervisor_id" bigint not null, - "student_id" bigint not null, - "content" text not null -); - - -ALTER TABLE "feedbacks" - ADD FOREIGN KEY ("work_id") REFERENCES "works" ("work_id"); - -ALTER TABLE "feedbacks" - ADD FOREIGN KEY ("supervisor_id") REFERENCES "supervisors" ("supervisor_id"); - -ALTER TABLE "feedbacks" - ADD FOREIGN KEY ("student_id") REFERENCES "students" ("student_id"); - -ALTER TABLE "feedbacks" - ADD CONSTRAINT feedbacks_unique_members_constraint UNIQUE (work_id, student_id); - -CREATE INDEX ON "feedbacks" (supervisor_id); -CREATE INDEX ON "feedbacks" (student_id, work_id); -CREATE INDEX ON "feedbacks" (supervisor_id, work_id); - - diff --git a/migrations/20221003080212_create_waypoints.down.sql b/migrations/20221003080212_create_waypoints.down.sql new file mode 100644 index 0000000..82ded23 --- /dev/null +++ b/migrations/20221003080212_create_waypoints.down.sql @@ -0,0 +1 @@ +drop table "waypoints" cascade; \ No newline at end of file diff --git a/migrations/20221003080212_create_waypoints.up.sql b/migrations/20221003080212_create_waypoints.up.sql new file mode 100644 index 0000000..b33a28c --- /dev/null +++ b/migrations/20221003080212_create_waypoints.up.sql @@ -0,0 +1,15 @@ +CREATE TABLE "waypoints" +( + "waypoint_id" bigint unique generated always as identity, + "work_id" bigint not null, + "deadline" date not null, + "title" text not null, + "description" text not null +); + + +ALTER TABLE "waypoints" + ADD FOREIGN KEY ("work_id") REFERENCES "works" ("work_id"); + +insert into waypoints(work_id, deadline, title, description) + values (1, '2022-11-01', 'Выбрать тему', 'Необходимо определиться с темой курсовой работы и предоставить ее руководителю.') diff --git a/pkg/misc/auth.go b/pkg/misc/auth.go index 0af3a40..83ab487 100644 --- a/pkg/misc/auth.go +++ b/pkg/misc/auth.go @@ -3,6 +3,7 @@ package misc import ( "github.com/golang-jwt/jwt" "github.com/labstack/echo/v4" + "strconv" "time" ) @@ -11,11 +12,11 @@ type AppJWTClaims struct { Role string } -func NewAppJWTClaims(exp time.Duration, sub, role string) *AppJWTClaims { +func NewAppJWTClaims(exp time.Duration, sub int, role string) *AppJWTClaims { return &AppJWTClaims{ StandardClaims: jwt.StandardClaims{ ExpiresAt: time.Now().Add(exp).Unix(), - Subject: sub, + Subject: strconv.Itoa(sub), }, Role: role, } diff --git a/swagger/docs.go b/swagger/docs.go index 873ba34..ae5ced9 100644 --- a/swagger/docs.go +++ b/swagger/docs.go @@ -35,14 +35,14 @@ const docTemplate = `{ "parameters": [ { "type": "string", - "description": "User email", + "description": "UserFull email", "name": "username", "in": "formData", "required": true }, { "type": "string", - "description": "User password", + "description": "UserFull password", "name": "password", "in": "formData", "required": true @@ -56,122 +56,58 @@ const docTemplate = `{ } }, "401": { - "description": "" + "description": "Unauthorized" }, "500": { - "description": "" + "description": "Internal Server Error" } } } }, - "/api/student/bid": { + "/api/v1/relations/": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ "application/json" ], "tags": [ - "student" + "relation" ], - "summary": "GetUserInfo student's bids", + "summary": "Get relations", "parameters": [ { "type": "integer", "description": "Student ID", "name": "student_id", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.StudentBids" - } + "in": "query" }, - "404": { - "description": "" - } - } - }, - "put": { - "security": [ - { - "Auth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "student" - ], - "summary": "Apply bid", - "parameters": [ - { - "description": "bid info", - "name": "ApplyBid", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ApplyBid" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ApplyBidResponse" - } - } - } - } - }, - "/api/student/feedback": { - "get": { - "security": [ - { - "Auth": [] - } - ], - "produces": [ - "application/json" - ], - "tags": [ - "student" - ], - "summary": "Get feedbacks on the supervisor.", - "parameters": [ { "type": "integer", "description": "Supervisor ID", "name": "supervisor_id", - "in": "query", - "required": true + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.FeedbackPlenty" + "$ref": "#/definitions/dto.RelationPlenty" } + }, + "404": { + "description": "Not Found" } } }, - "put": { + "post": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "consumes": [ @@ -181,17 +117,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "student" + "relation" ], - "summary": "Provide a feedback", + "summary": "Create relation", "parameters": [ { - "description": "feedback info", - "name": "Feedback", + "description": "Relation data", + "name": "CreateRelation", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.FeedbackReq" + "$ref": "#/definitions/dto.RelationCreateReq" } } ], @@ -199,47 +135,15 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/dto.FeedbackAddResp" + "$ref": "#/definitions/dto.RelationCreateResp" } - }, - "500": { - "description": "" } } - } - }, - "/api/student/profile": { - "get": { - "security": [ - { - "Auth": [] - } - ], - "produces": [ - "application/json" - ], - "tags": [ - "student" - ], - "summary": "GetUserInfo student's profile", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.StudentProfile" - } - }, - "404": { - "description": "" - } - } - } - }, - "/api/student/ssr": { - "post": { + }, + "patch": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "consumes": [ @@ -249,17 +153,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "student" + "relation" ], - "summary": "Start SSR", + "summary": "Update relation", "parameters": [ { - "description": "ssr info", - "name": "ApplyBid", + "description": "Relation data", + "name": "CreateRelation", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateSSR" + "$ref": "#/definitions/dto.RelationUpdateReq" } } ], @@ -267,17 +171,17 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.StudentViewSSR" + "$ref": "#/definitions/dto.RelationResp" } } } } }, - "/api/student/work": { + "/api/v1/students/{student_id}/profile": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -286,13 +190,13 @@ const docTemplate = `{ "tags": [ "student" ], - "summary": "GetUserInfo student's works", + "summary": "Get student's profile", "parameters": [ { "type": "integer", "description": "Student ID", "name": "student_id", - "in": "query", + "in": "path", "required": true } ], @@ -300,17 +204,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.StudentWorks" + "$ref": "#/definitions/dto.Student" } + }, + "404": { + "description": "Not Found" } } } }, - "/api/student/work/supervisor": { + "/api/v1/students/{student_id}/works": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -319,13 +226,13 @@ const docTemplate = `{ "tags": [ "student" ], - "summary": "GetUserInfo supervisors of the work", + "summary": "Get student's works", "parameters": [ { "type": "integer", - "description": "Work ID", - "name": "work_id", - "in": "query", + "description": "Student ID", + "name": "student_id", + "in": "path", "required": true } ], @@ -333,17 +240,17 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.WorkSupervisorPlenty" + "$ref": "#/definitions/dto.StudentViewWorkPlenty" } } } } }, - "/api/supervisor/bid": { + "/api/v1/supervisors/{supervisor_id}/profile": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -352,13 +259,13 @@ const docTemplate = `{ "tags": [ "supervisor" ], - "summary": "GetUserInfo supervisor's bids", + "summary": "Get supervisor's profile", "parameters": [ { "type": "integer", "description": "Supervisor ID", "name": "supervisor_id", - "in": "query", + "in": "path", "required": true } ], @@ -366,17 +273,17 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.SupervisorBids" + "$ref": "#/definitions/dto.Supervisor" } } } } }, - "/api/supervisor/bid/resolve": { - "post": { + "/api/v1/supervisors/{supervisor_id}/works": { + "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -385,72 +292,46 @@ const docTemplate = `{ "tags": [ "supervisor" ], - "summary": "Accept or Decline student's bid", + "summary": "Get supervisor's works", "parameters": [ { - "description": "bid info", - "name": "ResolveBid", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ResolveBid" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ResolveBidResp" - } - } - } - } - }, - "/api/supervisor/profile": { - "get": { - "security": [ - { - "Auth": [] + "type": "integer", + "description": "Supervisor ID", + "name": "supervisor_id", + "in": "path", + "required": true } ], - "produces": [ - "application/json" - ], - "tags": [ - "supervisor" - ], - "summary": "GetUserInfo supervisor's profile", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.SupervisorProfile" + "$ref": "#/definitions/dto.SupervisorViewWorkPlenty" } } } } }, - "/api/supervisor/work": { + "/api/v1/works/{work_id}": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ "application/json" ], "tags": [ - "supervisor" + "works" ], - "summary": "GetUserInfo supervisor's works", + "summary": "Get supervisors of the work", "parameters": [ { "type": "integer", - "description": "Supervisor ID", - "name": "supervisor_id", - "in": "query", + "description": "Work ID", + "name": "work_id", + "in": "path", "required": true } ], @@ -458,7 +339,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.SupervisorWorkPlenty" + "$ref": "#/definitions/dto.WorkFullResp" } } } @@ -466,360 +347,309 @@ const docTemplate = `{ } }, "definitions": { - "dto.ApplyBid": { + "dto.LoginResponse": { "type": "object", "properties": { - "studentID": { - "type": "integer" + "access_token": { + "type": "string" }, - "supervisorID": { - "type": "integer" + "role": { + "type": "string" }, - "workID": { + "token_type": { + "type": "string" + }, + "user_id": { "type": "integer" } } }, - "dto.ApplyBidResponse": { + "dto.RelationCreateReq": { "type": "object", "properties": { - "bidID": { + "student_id": { "type": "integer" - } - } - }, - "dto.CreateSSR": { - "type": "object", - "properties": { - "bidID": { + }, + "supervisor_id": { "type": "integer" }, - "studentID": { + "work_id": { "type": "integer" } } }, - "dto.FeedbackAddResp": { + "dto.RelationCreateResp": { "type": "object", "properties": { - "feedback_id": { + "relation_id": { "type": "integer" } } }, - "dto.FeedbackPlenty": { + "dto.RelationPlenty": { "type": "object", "properties": { - "feedbacks": { + "relations": { "type": "array", "items": { - "$ref": "#/definitions/dto.FeedbackResp" + "$ref": "#/definitions/dto.RelationShortResp" } } } }, - "dto.FeedbackReq": { + "dto.RelationResp": { "type": "object", "properties": { - "content": { + "relation_id": { + "type": "integer" + }, + "status": { "type": "string" }, - "studentID": { - "type": "integer" + "student": { + "$ref": "#/definitions/dto.Student" }, - "supervisorID": { - "type": "integer" + "supervisor": { + "$ref": "#/definitions/dto.Supervisor" }, - "workID": { - "type": "integer" + "work": { + "$ref": "#/definitions/dto.WorkResp" } } }, - "dto.FeedbackResp": { + "dto.RelationShortResp": { "type": "object", "properties": { - "content": { - "type": "string" - }, - "studentID": { + "relation_id": { "type": "integer" }, - "student_full_name": { + "status": { "type": "string" }, - "supervisorID": { - "type": "integer" + "student": { + "$ref": "#/definitions/dto.StudentShort" }, - "workID": { - "type": "integer" + "supervisor": { + "$ref": "#/definitions/dto.SupervisorShort" }, - "work_kind": { - "type": "string" + "work": { + "$ref": "#/definitions/dto.WorkShortResp" + } + } + }, + "dto.RelationUpdateReq": { + "type": "object", + "properties": { + "relation_id": { + "type": "integer" }, - "work_subject": { + "status": { "type": "string" } } }, - "dto.LoginResponse": { + "dto.Student": { "type": "object", "properties": { + "department": { + "type": "string" + }, "email": { "type": "string" }, - "role": { + "first_name": { "type": "string" }, - "token": { + "last_name": { "type": "string" - } - } - }, - "dto.ResolveBid": { - "type": "object", - "properties": { - "accept": { - "type": "boolean" }, - "bidID": { + "photo_url": { + "type": "string" + }, + "student_card": { + "type": "string" + }, + "user_id": { "type": "integer" }, - "supervisorID": { + "year": { "type": "integer" } } }, - "dto.ResolveBidResp": { + "dto.StudentShort": { "type": "object", "properties": { - "new_status": { - "type": "string" - } - } - }, - "dto.StudentBid": { - "type": "object", - "properties": { - "createdAt": { + "first_name": { "type": "string" }, - "id": { - "type": "integer" - }, - "status": { + "last_name": { "type": "string" }, - "supervisor": { - "$ref": "#/definitions/dto.SupervisorProfile" - }, - "work": { - "$ref": "#/definitions/dto.Work" + "user_id": { + "type": "integer" } } }, - "dto.StudentBids": { + "dto.StudentViewWorkPlenty": { "type": "object", "properties": { - "bids": { + "works": { "type": "array", "items": { - "$ref": "#/definitions/dto.StudentBid" + "$ref": "#/definitions/dto.StudentViewWorkShortResp" } } } }, - "dto.StudentProfile": { + "dto.StudentViewWorkShortResp": { "type": "object", "properties": { - "avatarUrl": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "studentCard": { - "type": "string" - }, - "studentID": { - "type": "integer" - }, - "year": { - "type": "integer" + "work": { + "$ref": "#/definitions/dto.WorkShortResp" } } }, - "dto.StudentViewSSR": { + "dto.SubjectResp": { "type": "object", "properties": { - "createdAt": { + "department": { "type": "string" }, "id": { "type": "integer" }, - "status": { + "name": { "type": "string" - }, - "supervisor": { - "$ref": "#/definitions/dto.SupervisorProfile" - }, - "work": { - "$ref": "#/definitions/dto.Work" } } }, - "dto.StudentWork": { + "dto.Supervisor": { "type": "object", "properties": { - "description": { + "about": { "type": "string" }, - "id": { - "type": "integer" + "birthdate": { + "type": "string" }, - "is_started": { - "type": "boolean" + "department": { + "type": "string" }, - "kind": { + "email": { "type": "string" }, - "subject": { + "first_name": { "type": "string" - } - } - }, - "dto.StudentWorks": { - "type": "object", - "properties": { - "studentID": { - "type": "integer" }, - "works": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.StudentWork" - } - } - } - }, - "dto.SubjectResp": { - "type": "object", - "properties": { - "department": { + "last_name": { "type": "string" }, - "name": { + "photo_url": { "type": "string" }, - "subjectID": { + "user_id": { "type": "integer" } } }, - "dto.SupervisorBid": { + "dto.SupervisorShort": { "type": "object", "properties": { - "createdAt": { + "first_name": { "type": "string" }, - "id": { - "type": "integer" - }, - "status": { + "last_name": { "type": "string" }, - "student": { - "$ref": "#/definitions/dto.StudentProfile" - }, - "work": { - "$ref": "#/definitions/dto.Work" + "user_id": { + "type": "integer" } } }, - "dto.SupervisorBids": { + "dto.SupervisorViewWorkPlenty": { "type": "object", "properties": { - "bids": { + "works": { "type": "array", "items": { - "$ref": "#/definitions/dto.SupervisorBid" + "$ref": "#/definitions/dto.SupervisorViewWorkShortResp" } } } }, - "dto.SupervisorProfile": { + "dto.SupervisorViewWorkShortResp": { "type": "object", "properties": { - "about": { - "type": "string" - }, - "avatarUrl": { - "type": "string" - }, - "birthdate": { - "type": "string" + "is_full": { + "type": "boolean" }, - "department": { - "type": "string" + "is_head": { + "type": "boolean" }, - "email": { + "work": { + "$ref": "#/definitions/dto.WorkShortResp" + } + } + }, + "dto.WaypointResp": { + "type": "object", + "properties": { + "deadline": { "type": "string" }, - "firstName": { + "description": { "type": "string" }, - "lastName": { + "title": { "type": "string" - }, - "supervisorID": { - "type": "integer" } } }, - "dto.SupervisorWork": { + "dto.WorkFullResp": { "type": "object", "properties": { "description": { "type": "string" }, - "head": { - "type": "boolean" - }, "id": { "type": "integer" }, "kind": { - "type": "string" + "$ref": "#/definitions/dto.WorkKindResp" + }, + "semester": { + "type": "integer" }, "subject": { - "type": "string" + "$ref": "#/definitions/dto.SubjectResp" + }, + "supervisors": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.WorkSupervisorShort" + } + }, + "waypoints": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.WaypointResp" + } } } }, - "dto.SupervisorWorkPlenty": { + "dto.WorkKindResp": { "type": "object", "properties": { - "supervisorID": { + "id": { "type": "integer" }, - "works": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SupervisorWork" - } + "name": { + "type": "string" } } }, - "dto.Work": { + "dto.WorkResp": { "type": "object", "properties": { "description": { @@ -828,8 +658,8 @@ const docTemplate = `{ "id": { "type": "integer" }, - "name": { - "type": "string" + "kind": { + "$ref": "#/definitions/dto.WorkKindResp" }, "semester": { "type": "integer" @@ -839,25 +669,24 @@ const docTemplate = `{ } } }, - "dto.WorkSupervisor": { + "dto.WorkShortResp": { "type": "object", "properties": { - "about": { - "type": "string" - }, - "avatarUrl": { - "type": "string" - }, - "birthdate": { - "type": "string" - }, - "department": { - "type": "string" + "id": { + "type": "integer" }, - "email": { - "type": "string" + "kind": { + "$ref": "#/definitions/dto.WorkKindResp" }, - "firstName": { + "subject": { + "$ref": "#/definitions/dto.SubjectResp" + } + } + }, + "dto.WorkSupervisorShort": { + "type": "object", + "properties": { + "first_name": { "type": "string" }, "full": { @@ -866,34 +695,20 @@ const docTemplate = `{ "head": { "type": "boolean" }, - "lastName": { + "last_name": { "type": "string" }, - "supervisorID": { - "type": "integer" - } - } - }, - "dto.WorkSupervisorPlenty": { - "type": "object", - "properties": { - "supervisors": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.WorkSupervisor" - } - }, - "workID": { + "user_id": { "type": "integer" } } } }, "securityDefinitions": { - "Auth": { - "type": "apiKey", - "name": "Authorization", - "in": "header" + "OAuth2Password": { + "type": "oauth2", + "flow": "password", + "tokenUrl": "http://localhost:8080/api/v1/auth/login" } } }` diff --git a/swagger/swagger.json b/swagger/swagger.json index 5085ee6..fe2bb23 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -31,14 +31,14 @@ "parameters": [ { "type": "string", - "description": "User email", + "description": "UserFull email", "name": "username", "in": "formData", "required": true }, { "type": "string", - "description": "User password", + "description": "UserFull password", "name": "password", "in": "formData", "required": true @@ -52,122 +52,58 @@ } }, "401": { - "description": "" + "description": "Unauthorized" }, "500": { - "description": "" + "description": "Internal Server Error" } } } }, - "/api/student/bid": { + "/api/v1/relations/": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ "application/json" ], "tags": [ - "student" + "relation" ], - "summary": "GetUserInfo student's bids", + "summary": "Get relations", "parameters": [ { "type": "integer", "description": "Student ID", "name": "student_id", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.StudentBids" - } + "in": "query" }, - "404": { - "description": "" - } - } - }, - "put": { - "security": [ - { - "Auth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "student" - ], - "summary": "Apply bid", - "parameters": [ - { - "description": "bid info", - "name": "ApplyBid", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ApplyBid" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ApplyBidResponse" - } - } - } - } - }, - "/api/student/feedback": { - "get": { - "security": [ - { - "Auth": [] - } - ], - "produces": [ - "application/json" - ], - "tags": [ - "student" - ], - "summary": "Get feedbacks on the supervisor.", - "parameters": [ { "type": "integer", "description": "Supervisor ID", "name": "supervisor_id", - "in": "query", - "required": true + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.FeedbackPlenty" + "$ref": "#/definitions/dto.RelationPlenty" } + }, + "404": { + "description": "Not Found" } } }, - "put": { + "post": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "consumes": [ @@ -177,17 +113,17 @@ "application/json" ], "tags": [ - "student" + "relation" ], - "summary": "Provide a feedback", + "summary": "Create relation", "parameters": [ { - "description": "feedback info", - "name": "Feedback", + "description": "Relation data", + "name": "CreateRelation", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.FeedbackReq" + "$ref": "#/definitions/dto.RelationCreateReq" } } ], @@ -195,47 +131,15 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/dto.FeedbackAddResp" + "$ref": "#/definitions/dto.RelationCreateResp" } - }, - "500": { - "description": "" } } - } - }, - "/api/student/profile": { - "get": { - "security": [ - { - "Auth": [] - } - ], - "produces": [ - "application/json" - ], - "tags": [ - "student" - ], - "summary": "GetUserInfo student's profile", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.StudentProfile" - } - }, - "404": { - "description": "" - } - } - } - }, - "/api/student/ssr": { - "post": { + }, + "patch": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "consumes": [ @@ -245,17 +149,17 @@ "application/json" ], "tags": [ - "student" + "relation" ], - "summary": "Start SSR", + "summary": "Update relation", "parameters": [ { - "description": "ssr info", - "name": "ApplyBid", + "description": "Relation data", + "name": "CreateRelation", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateSSR" + "$ref": "#/definitions/dto.RelationUpdateReq" } } ], @@ -263,17 +167,17 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.StudentViewSSR" + "$ref": "#/definitions/dto.RelationResp" } } } } }, - "/api/student/work": { + "/api/v1/students/{student_id}/profile": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -282,13 +186,13 @@ "tags": [ "student" ], - "summary": "GetUserInfo student's works", + "summary": "Get student's profile", "parameters": [ { "type": "integer", "description": "Student ID", "name": "student_id", - "in": "query", + "in": "path", "required": true } ], @@ -296,17 +200,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.StudentWorks" + "$ref": "#/definitions/dto.Student" } + }, + "404": { + "description": "Not Found" } } } }, - "/api/student/work/supervisor": { + "/api/v1/students/{student_id}/works": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -315,13 +222,13 @@ "tags": [ "student" ], - "summary": "GetUserInfo supervisors of the work", + "summary": "Get student's works", "parameters": [ { "type": "integer", - "description": "Work ID", - "name": "work_id", - "in": "query", + "description": "Student ID", + "name": "student_id", + "in": "path", "required": true } ], @@ -329,17 +236,17 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.WorkSupervisorPlenty" + "$ref": "#/definitions/dto.StudentViewWorkPlenty" } } } } }, - "/api/supervisor/bid": { + "/api/v1/supervisors/{supervisor_id}/profile": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -348,13 +255,13 @@ "tags": [ "supervisor" ], - "summary": "GetUserInfo supervisor's bids", + "summary": "Get supervisor's profile", "parameters": [ { "type": "integer", "description": "Supervisor ID", "name": "supervisor_id", - "in": "query", + "in": "path", "required": true } ], @@ -362,17 +269,17 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.SupervisorBids" + "$ref": "#/definitions/dto.Supervisor" } } } } }, - "/api/supervisor/bid/resolve": { - "post": { + "/api/v1/supervisors/{supervisor_id}/works": { + "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ @@ -381,72 +288,46 @@ "tags": [ "supervisor" ], - "summary": "Accept or Decline student's bid", + "summary": "Get supervisor's works", "parameters": [ { - "description": "bid info", - "name": "ResolveBid", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ResolveBid" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ResolveBidResp" - } - } - } - } - }, - "/api/supervisor/profile": { - "get": { - "security": [ - { - "Auth": [] + "type": "integer", + "description": "Supervisor ID", + "name": "supervisor_id", + "in": "path", + "required": true } ], - "produces": [ - "application/json" - ], - "tags": [ - "supervisor" - ], - "summary": "GetUserInfo supervisor's profile", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.SupervisorProfile" + "$ref": "#/definitions/dto.SupervisorViewWorkPlenty" } } } } }, - "/api/supervisor/work": { + "/api/v1/works/{work_id}": { "get": { "security": [ { - "Auth": [] + "OAuth2Password": [] } ], "produces": [ "application/json" ], "tags": [ - "supervisor" + "works" ], - "summary": "GetUserInfo supervisor's works", + "summary": "Get supervisors of the work", "parameters": [ { "type": "integer", - "description": "Supervisor ID", - "name": "supervisor_id", - "in": "query", + "description": "Work ID", + "name": "work_id", + "in": "path", "required": true } ], @@ -454,7 +335,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.SupervisorWorkPlenty" + "$ref": "#/definitions/dto.WorkFullResp" } } } @@ -462,360 +343,309 @@ } }, "definitions": { - "dto.ApplyBid": { + "dto.LoginResponse": { "type": "object", "properties": { - "studentID": { - "type": "integer" + "access_token": { + "type": "string" }, - "supervisorID": { - "type": "integer" + "role": { + "type": "string" }, - "workID": { + "token_type": { + "type": "string" + }, + "user_id": { "type": "integer" } } }, - "dto.ApplyBidResponse": { + "dto.RelationCreateReq": { "type": "object", "properties": { - "bidID": { + "student_id": { "type": "integer" - } - } - }, - "dto.CreateSSR": { - "type": "object", - "properties": { - "bidID": { + }, + "supervisor_id": { "type": "integer" }, - "studentID": { + "work_id": { "type": "integer" } } }, - "dto.FeedbackAddResp": { + "dto.RelationCreateResp": { "type": "object", "properties": { - "feedback_id": { + "relation_id": { "type": "integer" } } }, - "dto.FeedbackPlenty": { + "dto.RelationPlenty": { "type": "object", "properties": { - "feedbacks": { + "relations": { "type": "array", "items": { - "$ref": "#/definitions/dto.FeedbackResp" + "$ref": "#/definitions/dto.RelationShortResp" } } } }, - "dto.FeedbackReq": { + "dto.RelationResp": { "type": "object", "properties": { - "content": { + "relation_id": { + "type": "integer" + }, + "status": { "type": "string" }, - "studentID": { - "type": "integer" + "student": { + "$ref": "#/definitions/dto.Student" }, - "supervisorID": { - "type": "integer" + "supervisor": { + "$ref": "#/definitions/dto.Supervisor" }, - "workID": { - "type": "integer" + "work": { + "$ref": "#/definitions/dto.WorkResp" } } }, - "dto.FeedbackResp": { + "dto.RelationShortResp": { "type": "object", "properties": { - "content": { - "type": "string" - }, - "studentID": { + "relation_id": { "type": "integer" }, - "student_full_name": { + "status": { "type": "string" }, - "supervisorID": { - "type": "integer" + "student": { + "$ref": "#/definitions/dto.StudentShort" }, - "workID": { - "type": "integer" + "supervisor": { + "$ref": "#/definitions/dto.SupervisorShort" }, - "work_kind": { - "type": "string" + "work": { + "$ref": "#/definitions/dto.WorkShortResp" + } + } + }, + "dto.RelationUpdateReq": { + "type": "object", + "properties": { + "relation_id": { + "type": "integer" }, - "work_subject": { + "status": { "type": "string" } } }, - "dto.LoginResponse": { + "dto.Student": { "type": "object", "properties": { + "department": { + "type": "string" + }, "email": { "type": "string" }, - "role": { + "first_name": { "type": "string" }, - "token": { + "last_name": { "type": "string" - } - } - }, - "dto.ResolveBid": { - "type": "object", - "properties": { - "accept": { - "type": "boolean" }, - "bidID": { + "photo_url": { + "type": "string" + }, + "student_card": { + "type": "string" + }, + "user_id": { "type": "integer" }, - "supervisorID": { + "year": { "type": "integer" } } }, - "dto.ResolveBidResp": { + "dto.StudentShort": { "type": "object", "properties": { - "new_status": { - "type": "string" - } - } - }, - "dto.StudentBid": { - "type": "object", - "properties": { - "createdAt": { + "first_name": { "type": "string" }, - "id": { - "type": "integer" - }, - "status": { + "last_name": { "type": "string" }, - "supervisor": { - "$ref": "#/definitions/dto.SupervisorProfile" - }, - "work": { - "$ref": "#/definitions/dto.Work" + "user_id": { + "type": "integer" } } }, - "dto.StudentBids": { + "dto.StudentViewWorkPlenty": { "type": "object", "properties": { - "bids": { + "works": { "type": "array", "items": { - "$ref": "#/definitions/dto.StudentBid" + "$ref": "#/definitions/dto.StudentViewWorkShortResp" } } } }, - "dto.StudentProfile": { + "dto.StudentViewWorkShortResp": { "type": "object", "properties": { - "avatarUrl": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "studentCard": { - "type": "string" - }, - "studentID": { - "type": "integer" - }, - "year": { - "type": "integer" + "work": { + "$ref": "#/definitions/dto.WorkShortResp" } } }, - "dto.StudentViewSSR": { + "dto.SubjectResp": { "type": "object", "properties": { - "createdAt": { + "department": { "type": "string" }, "id": { "type": "integer" }, - "status": { + "name": { "type": "string" - }, - "supervisor": { - "$ref": "#/definitions/dto.SupervisorProfile" - }, - "work": { - "$ref": "#/definitions/dto.Work" } } }, - "dto.StudentWork": { + "dto.Supervisor": { "type": "object", "properties": { - "description": { + "about": { "type": "string" }, - "id": { - "type": "integer" + "birthdate": { + "type": "string" }, - "is_started": { - "type": "boolean" + "department": { + "type": "string" }, - "kind": { + "email": { "type": "string" }, - "subject": { + "first_name": { "type": "string" - } - } - }, - "dto.StudentWorks": { - "type": "object", - "properties": { - "studentID": { - "type": "integer" }, - "works": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.StudentWork" - } - } - } - }, - "dto.SubjectResp": { - "type": "object", - "properties": { - "department": { + "last_name": { "type": "string" }, - "name": { + "photo_url": { "type": "string" }, - "subjectID": { + "user_id": { "type": "integer" } } }, - "dto.SupervisorBid": { + "dto.SupervisorShort": { "type": "object", "properties": { - "createdAt": { + "first_name": { "type": "string" }, - "id": { - "type": "integer" - }, - "status": { + "last_name": { "type": "string" }, - "student": { - "$ref": "#/definitions/dto.StudentProfile" - }, - "work": { - "$ref": "#/definitions/dto.Work" + "user_id": { + "type": "integer" } } }, - "dto.SupervisorBids": { + "dto.SupervisorViewWorkPlenty": { "type": "object", "properties": { - "bids": { + "works": { "type": "array", "items": { - "$ref": "#/definitions/dto.SupervisorBid" + "$ref": "#/definitions/dto.SupervisorViewWorkShortResp" } } } }, - "dto.SupervisorProfile": { + "dto.SupervisorViewWorkShortResp": { "type": "object", "properties": { - "about": { - "type": "string" - }, - "avatarUrl": { - "type": "string" - }, - "birthdate": { - "type": "string" + "is_full": { + "type": "boolean" }, - "department": { - "type": "string" + "is_head": { + "type": "boolean" }, - "email": { + "work": { + "$ref": "#/definitions/dto.WorkShortResp" + } + } + }, + "dto.WaypointResp": { + "type": "object", + "properties": { + "deadline": { "type": "string" }, - "firstName": { + "description": { "type": "string" }, - "lastName": { + "title": { "type": "string" - }, - "supervisorID": { - "type": "integer" } } }, - "dto.SupervisorWork": { + "dto.WorkFullResp": { "type": "object", "properties": { "description": { "type": "string" }, - "head": { - "type": "boolean" - }, "id": { "type": "integer" }, "kind": { - "type": "string" + "$ref": "#/definitions/dto.WorkKindResp" + }, + "semester": { + "type": "integer" }, "subject": { - "type": "string" + "$ref": "#/definitions/dto.SubjectResp" + }, + "supervisors": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.WorkSupervisorShort" + } + }, + "waypoints": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.WaypointResp" + } } } }, - "dto.SupervisorWorkPlenty": { + "dto.WorkKindResp": { "type": "object", "properties": { - "supervisorID": { + "id": { "type": "integer" }, - "works": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SupervisorWork" - } + "name": { + "type": "string" } } }, - "dto.Work": { + "dto.WorkResp": { "type": "object", "properties": { "description": { @@ -824,8 +654,8 @@ "id": { "type": "integer" }, - "name": { - "type": "string" + "kind": { + "$ref": "#/definitions/dto.WorkKindResp" }, "semester": { "type": "integer" @@ -835,25 +665,24 @@ } } }, - "dto.WorkSupervisor": { + "dto.WorkShortResp": { "type": "object", "properties": { - "about": { - "type": "string" - }, - "avatarUrl": { - "type": "string" - }, - "birthdate": { - "type": "string" - }, - "department": { - "type": "string" + "id": { + "type": "integer" }, - "email": { - "type": "string" + "kind": { + "$ref": "#/definitions/dto.WorkKindResp" }, - "firstName": { + "subject": { + "$ref": "#/definitions/dto.SubjectResp" + } + } + }, + "dto.WorkSupervisorShort": { + "type": "object", + "properties": { + "first_name": { "type": "string" }, "full": { @@ -862,34 +691,20 @@ "head": { "type": "boolean" }, - "lastName": { + "last_name": { "type": "string" }, - "supervisorID": { - "type": "integer" - } - } - }, - "dto.WorkSupervisorPlenty": { - "type": "object", - "properties": { - "supervisors": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.WorkSupervisor" - } - }, - "workID": { + "user_id": { "type": "integer" } } } }, "securityDefinitions": { - "Auth": { - "type": "apiKey", - "name": "Authorization", - "in": "header" + "OAuth2Password": { + "type": "oauth2", + "flow": "password", + "tokenUrl": "http://localhost:8080/api/v1/auth/login" } } } \ No newline at end of file diff --git a/swagger/swagger.yaml b/swagger/swagger.yaml index 1e91fe9..b2bbd54 100644 --- a/swagger/swagger.yaml +++ b/swagger/swagger.yaml @@ -1,276 +1,233 @@ basePath: / definitions: - dto.ApplyBid: + dto.LoginResponse: properties: - studentID: - type: integer - supervisorID: - type: integer - workID: + access_token: + type: string + role: + type: string + token_type: + type: string + user_id: type: integer type: object - dto.ApplyBidResponse: + dto.RelationCreateReq: properties: - bidID: + student_id: type: integer - type: object - dto.CreateSSR: - properties: - bidID: + supervisor_id: type: integer - studentID: + work_id: type: integer type: object - dto.FeedbackAddResp: + dto.RelationCreateResp: properties: - feedback_id: + relation_id: type: integer type: object - dto.FeedbackPlenty: + dto.RelationPlenty: properties: - feedbacks: + relations: items: - $ref: '#/definitions/dto.FeedbackResp' + $ref: '#/definitions/dto.RelationShortResp' type: array type: object - dto.FeedbackReq: - properties: - content: - type: string - studentID: - type: integer - supervisorID: - type: integer - workID: - type: integer - type: object - dto.FeedbackResp: - properties: - content: - type: string - student_full_name: - type: string - studentID: - type: integer - supervisorID: - type: integer - work_kind: - type: string - work_subject: - type: string - workID: - type: integer - type: object - dto.LoginResponse: - properties: - email: - type: string - role: - type: string - token: - type: string - type: object - dto.ResolveBid: + dto.RelationResp: properties: - accept: - type: boolean - bidID: + relation_id: type: integer - supervisorID: - type: integer - type: object - dto.ResolveBidResp: - properties: - new_status: + status: type: string + student: + $ref: '#/definitions/dto.Student' + supervisor: + $ref: '#/definitions/dto.Supervisor' + work: + $ref: '#/definitions/dto.WorkResp' type: object - dto.StudentBid: + dto.RelationShortResp: properties: - createdAt: - type: string - id: + relation_id: type: integer status: type: string + student: + $ref: '#/definitions/dto.StudentShort' supervisor: - $ref: '#/definitions/dto.SupervisorProfile' + $ref: '#/definitions/dto.SupervisorShort' work: - $ref: '#/definitions/dto.Work' + $ref: '#/definitions/dto.WorkShortResp' type: object - dto.StudentBids: + dto.RelationUpdateReq: properties: - bids: - items: - $ref: '#/definitions/dto.StudentBid' - type: array + relation_id: + type: integer + status: + type: string type: object - dto.StudentProfile: + dto.Student: properties: - avatarUrl: - type: string department: type: string email: type: string - firstName: + first_name: + type: string + last_name: type: string - lastName: + photo_url: type: string - studentCard: + student_card: type: string - studentID: + user_id: type: integer year: type: integer type: object - dto.StudentViewSSR: + dto.StudentShort: properties: - createdAt: + first_name: type: string - id: - type: integer - status: + last_name: type: string - supervisor: - $ref: '#/definitions/dto.SupervisorProfile' - work: - $ref: '#/definitions/dto.Work' - type: object - dto.StudentWork: - properties: - description: - type: string - id: + user_id: type: integer - is_started: - type: boolean - kind: - type: string - subject: - type: string type: object - dto.StudentWorks: + dto.StudentViewWorkPlenty: properties: - studentID: - type: integer works: items: - $ref: '#/definitions/dto.StudentWork' + $ref: '#/definitions/dto.StudentViewWorkShortResp' type: array type: object - dto.SubjectResp: + dto.StudentViewWorkShortResp: properties: - department: - type: string - name: - type: string - subjectID: - type: integer + work: + $ref: '#/definitions/dto.WorkShortResp' type: object - dto.SupervisorBid: + dto.SubjectResp: properties: - createdAt: + department: type: string id: type: integer - status: + name: type: string - student: - $ref: '#/definitions/dto.StudentProfile' - work: - $ref: '#/definitions/dto.Work' - type: object - dto.SupervisorBids: - properties: - bids: - items: - $ref: '#/definitions/dto.SupervisorBid' - type: array type: object - dto.SupervisorProfile: + dto.Supervisor: properties: about: type: string - avatarUrl: - type: string birthdate: type: string department: type: string email: type: string - firstName: + first_name: type: string - lastName: + last_name: type: string - supervisorID: + photo_url: + type: string + user_id: type: integer type: object - dto.SupervisorWork: + dto.SupervisorShort: properties: - description: + first_name: type: string - head: - type: boolean - id: - type: integer - kind: - type: string - subject: + last_name: type: string + user_id: + type: integer type: object - dto.SupervisorWorkPlenty: + dto.SupervisorViewWorkPlenty: properties: - supervisorID: - type: integer works: items: - $ref: '#/definitions/dto.SupervisorWork' + $ref: '#/definitions/dto.SupervisorViewWorkShortResp' type: array type: object - dto.Work: + dto.SupervisorViewWorkShortResp: + properties: + is_full: + type: boolean + is_head: + type: boolean + work: + $ref: '#/definitions/dto.WorkShortResp' + type: object + dto.WaypointResp: + properties: + deadline: + type: string + description: + type: string + title: + type: string + type: object + dto.WorkFullResp: properties: description: type: string id: type: integer - name: - type: string + kind: + $ref: '#/definitions/dto.WorkKindResp' semester: type: integer subject: $ref: '#/definitions/dto.SubjectResp' + supervisors: + items: + $ref: '#/definitions/dto.WorkSupervisorShort' + type: array + waypoints: + items: + $ref: '#/definitions/dto.WaypointResp' + type: array type: object - dto.WorkSupervisor: + dto.WorkKindResp: properties: - about: - type: string - avatarUrl: - type: string - birthdate: - type: string - department: + id: + type: integer + name: type: string - email: + type: object + dto.WorkResp: + properties: + description: type: string - firstName: + id: + type: integer + kind: + $ref: '#/definitions/dto.WorkKindResp' + semester: + type: integer + subject: + $ref: '#/definitions/dto.SubjectResp' + type: object + dto.WorkShortResp: + properties: + id: + type: integer + kind: + $ref: '#/definitions/dto.WorkKindResp' + subject: + $ref: '#/definitions/dto.SubjectResp' + type: object + dto.WorkSupervisorShort: + properties: + first_name: type: string full: type: boolean head: type: boolean - lastName: + last_name: type: string - supervisorID: - type: integer - type: object - dto.WorkSupervisorPlenty: - properties: - supervisors: - items: - $ref: '#/definitions/dto.WorkSupervisor' - type: array - workID: + user_id: type: integer type: object host: localhost:8080 @@ -288,12 +245,12 @@ paths: consumes: - application/x-www-form-urlencoded parameters: - - description: User email + - description: UserFull email in: formData name: username required: true type: string - - description: User password + - description: UserFull password in: formData name: password required: true @@ -306,63 +263,22 @@ paths: schema: $ref: '#/definitions/dto.LoginResponse' "401": - description: "" + description: Unauthorized "500": - description: "" + description: Internal Server Error summary: Login into account tags: - auth - /api/student/bid: + /api/v1/relations/: get: parameters: - description: Student ID in: query name: student_id - required: true type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.StudentBids' - "404": - description: "" - security: - - Auth: [] - summary: GetUserInfo student's bids - tags: - - student - put: - consumes: - - application/json - parameters: - - description: bid info - in: body - name: ApplyBid - required: true - schema: - $ref: '#/definitions/dto.ApplyBid' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ApplyBidResponse' - security: - - Auth: [] - summary: Apply bid - tags: - - student - /api/student/feedback: - get: - parameters: - description: Supervisor ID in: query name: supervisor_id - required: true type: integer produces: - application/json @@ -370,80 +286,63 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.FeedbackPlenty' + $ref: '#/definitions/dto.RelationPlenty' + "404": + description: Not Found security: - - Auth: [] - summary: Get feedbacks on the supervisor. + - OAuth2Password: [] + summary: Get relations tags: - - student - put: + - relation + patch: consumes: - application/json parameters: - - description: feedback info + - description: Relation data in: body - name: Feedback + name: CreateRelation required: true schema: - $ref: '#/definitions/dto.FeedbackReq' - produces: - - application/json - responses: - "201": - description: Created - schema: - $ref: '#/definitions/dto.FeedbackAddResp' - "500": - description: "" - security: - - Auth: [] - summary: Provide a feedback - tags: - - student - /api/student/profile: - get: + $ref: '#/definitions/dto.RelationUpdateReq' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/dto.StudentProfile' - "404": - description: "" + $ref: '#/definitions/dto.RelationResp' security: - - Auth: [] - summary: GetUserInfo student's profile + - OAuth2Password: [] + summary: Update relation tags: - - student - /api/student/ssr: + - relation post: consumes: - application/json parameters: - - description: ssr info + - description: Relation data in: body - name: ApplyBid + name: CreateRelation required: true schema: - $ref: '#/definitions/dto.CreateSSR' + $ref: '#/definitions/dto.RelationCreateReq' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/dto.StudentViewSSR' + $ref: '#/definitions/dto.RelationCreateResp' security: - - Auth: [] - summary: Start SSR + - OAuth2Password: [] + summary: Create relation tags: - - student - /api/student/work: + - relation + /api/v1/students/{student_id}/profile: get: parameters: - description: Student ID - in: query + in: path name: student_id required: true type: integer @@ -453,18 +352,20 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.StudentWorks' + $ref: '#/definitions/dto.Student' + "404": + description: Not Found security: - - Auth: [] - summary: GetUserInfo student's works + - OAuth2Password: [] + summary: Get student's profile tags: - student - /api/student/work/supervisor: + /api/v1/students/{student_id}/works: get: parameters: - - description: Work ID - in: query - name: work_id + - description: Student ID + in: path + name: student_id required: true type: integer produces: @@ -473,17 +374,17 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.WorkSupervisorPlenty' + $ref: '#/definitions/dto.StudentViewWorkPlenty' security: - - Auth: [] - summary: GetUserInfo supervisors of the work + - OAuth2Password: [] + summary: Get student's works tags: - student - /api/supervisor/bid: + /api/v1/supervisors/{supervisor_id}/profile: get: parameters: - description: Supervisor ID - in: query + in: path name: supervisor_id required: true type: integer @@ -493,53 +394,38 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.SupervisorBids' + $ref: '#/definitions/dto.Supervisor' security: - - Auth: [] - summary: GetUserInfo supervisor's bids + - OAuth2Password: [] + summary: Get supervisor's profile tags: - supervisor - /api/supervisor/bid/resolve: - post: + /api/v1/supervisors/{supervisor_id}/works: + get: parameters: - - description: bid info - in: body - name: ResolveBid + - description: Supervisor ID + in: path + name: supervisor_id required: true - schema: - $ref: '#/definitions/dto.ResolveBid' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ResolveBidResp' - security: - - Auth: [] - summary: Accept or Decline student's bid - tags: - - supervisor - /api/supervisor/profile: - get: + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/dto.SupervisorProfile' + $ref: '#/definitions/dto.SupervisorViewWorkPlenty' security: - - Auth: [] - summary: GetUserInfo supervisor's profile + - OAuth2Password: [] + summary: Get supervisor's works tags: - supervisor - /api/supervisor/work: + /api/v1/works/{work_id}: get: parameters: - - description: Supervisor ID - in: query - name: supervisor_id + - description: Work ID + in: path + name: work_id required: true type: integer produces: @@ -548,17 +434,17 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.SupervisorWorkPlenty' + $ref: '#/definitions/dto.WorkFullResp' security: - - Auth: [] - summary: GetUserInfo supervisor's works + - OAuth2Password: [] + summary: Get supervisors of the work tags: - - supervisor + - works schemes: - http securityDefinitions: - Auth: - in: header - name: Authorization - type: apiKey + OAuth2Password: + flow: password + tokenUrl: http://localhost:8080/api/v1/auth/login + type: oauth2 swagger: "2.0"