Added authorization
This commit is contained in:
parent
c3c3d65d32
commit
b96dd39795
50 changed files with 685 additions and 410 deletions
|
|
@ -1,43 +1,155 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/commands"
|
||||
"58team_blog/internal/application/errors"
|
||||
"58team_blog/internal/application/services"
|
||||
"58team_blog/internal/interfaces/api/mapper"
|
||||
"58team_blog/internal/interfaces/api/responses"
|
||||
"58team_blog/internal/utils"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ImagesController struct {
|
||||
service *services.ImagesService
|
||||
images_path string
|
||||
service *services.ImagesService
|
||||
}
|
||||
|
||||
func CreateImagesController(service *services.ImagesService) ImagesController {
|
||||
func CreateImagesController(images_path string, service *services.ImagesService) ImagesController {
|
||||
return ImagesController{
|
||||
service: service,
|
||||
images_path: images_path,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// get /images/{path}
|
||||
// post /images
|
||||
// delete /images/{id}
|
||||
// @Summary Upload new image
|
||||
// @Description Upload new image and returns uploaded image json object
|
||||
// @Tags images
|
||||
// @Produce json
|
||||
// @Param file formData file true "image file"
|
||||
// @Success 200 {object} responses.ImageResponse
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /images/ [post]
|
||||
func (r *ImagesController) PostImage(c *gin.Context) {
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
resp := utils.HandleError(errors.NewNotFoundError("File not found"))
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
uploadedFile, err := file.Open()
|
||||
if err != nil {
|
||||
resp := utils.HandleError(errors.NewReadFileError(err.Error()))
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
// Read first 512 bytes for detect MIME-type
|
||||
buffer := make([]byte, 512)
|
||||
_, err = uploadedFile.Read(buffer)
|
||||
if err != nil {
|
||||
resp := utils.HandleError(errors.NewReadFileError(err.Error()))
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
uploadedFile.Close()
|
||||
|
||||
mimeType := http.DetectContentType(buffer)
|
||||
|
||||
if !utils.IsImageMime(mimeType) {
|
||||
resp := utils.HandleError(errors.NewValidationError("Unexpected file type. Expected: jpeg, png, gif, webp, bmp."))
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
cmd := commands.CreateImageCommand{
|
||||
Path: uuid.NewString(),
|
||||
}
|
||||
|
||||
image, err := r.service.Create(cmd)
|
||||
if err != nil {
|
||||
resp := utils.HandleError(errors.NewValidationError(err.Error()))
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
c.SaveUploadedFile(file, r.images_path+"/"+image.Path)
|
||||
|
||||
resp := mapper.ResponseFromImageResult(image)
|
||||
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// @Summary Get an image by path
|
||||
// @Description get image by path
|
||||
// @Param path query string true "Path to image"
|
||||
// @Tags images
|
||||
// @Param path path string true "Path to image"
|
||||
// @Produce octet-stream
|
||||
// @Produce json
|
||||
// @Success 200 {file} blob
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Failure 404 {object} responses.ErrorResponse
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /images/{path} [get]
|
||||
func (r *ImagesController) GetImage(c *gin.Context) {
|
||||
filename := c.Param("path")
|
||||
|
||||
filePath := filepath.Join(r.images_path, filename)
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusNotFound, "Image not found")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Cannot load image file from server")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
mimeData := make([]byte, 512)
|
||||
if _, err := file.Read(mimeData); err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Cannot load image from server")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
mimeType, err := utils.GetImageMimeType(mimeData)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, err.Error())
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Type", mimeType)
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
// @Summary Delete image by path
|
||||
// @Description Delete image from server by given path
|
||||
// @Tags images
|
||||
// @Param filename path string true "Path to image"
|
||||
// @Produce image/png
|
||||
// @Produce image/jpeg
|
||||
// @Success 200
|
||||
// @Router /images/{path} [get]
|
||||
func (r *ImagesController) GetImage(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (r *ImagesController) PostImage(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Failure 404 {object} responses.ErrorResponse
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /images/{path} [delete]
|
||||
func (r *ImagesController) DeleteImage(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@ import (
|
|||
)
|
||||
|
||||
type PostController struct {
|
||||
service *services.PostService
|
||||
service *services.PostService
|
||||
userService *services.UserService
|
||||
}
|
||||
|
||||
func CreatePostController(service *services.PostService) PostController {
|
||||
func CreatePostController(service *services.PostService, userService *services.UserService) PostController {
|
||||
return PostController{
|
||||
service: service,
|
||||
service: service,
|
||||
userService: userService,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +63,8 @@ func (r *PostController) Post(c *gin.Context) {
|
|||
Title: request.Title,
|
||||
Description: request.Description,
|
||||
Content: request.Content,
|
||||
Category: request.Category,
|
||||
Tags: request.Tags,
|
||||
}
|
||||
|
||||
res, err := r.service.Create(cmd)
|
||||
|
|
@ -70,7 +74,16 @@ func (r *PostController) Post(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// Get username by userid
|
||||
user, err := r.userService.FindById(queries.UserFindByIdQuery{Id: userId})
|
||||
if err != nil {
|
||||
resp := utils.HandleError(err)
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
response := mapper.ResponseFromPostResult(res)
|
||||
response.Username = user.Result.UserName
|
||||
|
||||
c.JSON(http.StatusCreated, response)
|
||||
}
|
||||
|
|
@ -94,6 +107,17 @@ func (r *PostController) GetAll(c *gin.Context) {
|
|||
|
||||
res := mapper.ResponseFromPostGetAllResult(result)
|
||||
|
||||
for e, i := range res {
|
||||
// Get username by userid
|
||||
user, err := r.userService.FindById(queries.UserFindByIdQuery{Id: uuid.MustParse(i.UserId)})
|
||||
if err != nil {
|
||||
resp := utils.HandleError(err)
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
res[e].Username = user.Result.UserName
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +151,17 @@ func (r *PostController) GetAllWithOffset(c *gin.Context) {
|
|||
|
||||
res := mapper.ResponseFromPostGetAllResult(result)
|
||||
|
||||
for e, i := range res {
|
||||
// Get username by userid
|
||||
user, err := r.userService.FindById(queries.UserFindByIdQuery{Id: uuid.MustParse(i.UserId)})
|
||||
if err != nil {
|
||||
resp := utils.HandleError(err)
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
res[e].Username = user.Result.UserName
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
|
|
@ -166,6 +201,14 @@ func (r *PostController) GetById(c *gin.Context) {
|
|||
|
||||
result := mapper.ResponseFormPostFindByIdResult(posts)
|
||||
|
||||
user, err := r.userService.FindById(queries.UserFindByIdQuery{Id: uuid.MustParse(result.UserId)})
|
||||
if err != nil {
|
||||
resp := utils.HandleError(err)
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
result.Username = user.Result.UserName
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,20 +11,117 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
service *services.UserService
|
||||
adminName string
|
||||
adminPass string
|
||||
service *services.UserService
|
||||
}
|
||||
|
||||
func CreateUserController(service *services.UserService) UserController {
|
||||
func CreateUserController(service *services.UserService, adminName string, adminPass string) UserController {
|
||||
return UserController{
|
||||
service: service,
|
||||
service: service,
|
||||
adminName: adminName,
|
||||
adminPass: adminPass,
|
||||
}
|
||||
}
|
||||
|
||||
// @Summary Login
|
||||
// @Description Login user into system
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body requests.LoginUserRequest true "User login data"
|
||||
// @Success 200
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Failure 401 {object} responses.ErrorResponse
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /login [post]
|
||||
func (r *UserController) Login(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
|
||||
var request requests.LoginUserRequest
|
||||
if err := c.BindJSON(&request); err != nil {
|
||||
log.Println("User invalid request: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusBadRequest, err.Error())
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
// Check admin login
|
||||
if request.Username == r.adminName && request.Password == r.adminPass {
|
||||
session.Set("user", uuid.NewString())
|
||||
if err := session.Save(); err != nil {
|
||||
log.Println("User save session error: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := r.service.FindByName(queries.UserFindByNameQuery{Name: request.Username})
|
||||
if err != nil {
|
||||
resp := utils.HandleError(err)
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
pass, err := utils.EncryptPassword(request.Password)
|
||||
if err != nil {
|
||||
log.Println("User encrypt password error: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
if utils.CheckPassword(user.Result.Password, pass) {
|
||||
log.Println("Pass ", user.Result.Password, " != ", pass)
|
||||
resp := responses.CreateErrorResponse(http.StatusUnauthorized, "Authentication error")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
session.Set("user", user.Result.Id.String())
|
||||
if err := session.Save(); err != nil {
|
||||
log.Println("User save session error: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
// @Summary Create new user
|
||||
// @Description Creates new user in system
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Success 200
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /logout [get]
|
||||
func (r *UserController) Logout(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
user := session.Get("user")
|
||||
if user == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid session token"})
|
||||
return
|
||||
}
|
||||
session.Delete("user")
|
||||
if err := session.Save(); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save session"})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
// @Summary Create new user
|
||||
// @Description Creates new user in system
|
||||
// @Tags user
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue