feat: images

This commit is contained in:
Florian Sylvain
2024-06-13 13:34:10 +02:00
parent eb98a1003e
commit c25fb1b0a3
19 changed files with 387 additions and 100 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ tmp_dir = "tmp"
bin = "tmp\\main.exe" bin = "tmp\\main.exe"
cmd = "go build -o ./tmp/main.exe ./main" cmd = "go build -o ./tmp/main.exe ./main"
delay = 1000 delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata", "api\\static\\tinymce", "api\\static\\bootstrap-icons"] exclude_dir = ["assets", "tmp", "vendor", "testdata", "api\\static\\tinymce", "api\\static\\bootstrap-icons", "api\\static\\uploadedImages"]
exclude_file = [] exclude_file = []
exclude_regex = ["_test.go"] exclude_regex = ["_test.go"]
exclude_unchanged = false exclude_unchanged = false
+1 -1
View File
@@ -46,7 +46,7 @@ of course required, but not necessarily via the `.env` file.
| PORT | int | port the API will use | required | | PORT | int | port the API will use | required |
| JWT_SECRET | string | secret for the jwt auth | required | | JWT_SECRET | string | secret for the jwt auth | required |
| CORS_ALLOWED_ORIGINS | string | allowed origins for CORS | required, semicolon separated list | | CORS_ALLOWED_ORIGINS | string | allowed origins for CORS | required, semicolon separated list |
| DB_FILE | string | path to the sqlite db file | required, can be at the root but name still required (e.g. `./gocms.db`) ; have to end up with `.db` | | DB_FILE | string | path to the sqlite db file | required, can be at the root but name still required (e.g. `./gocms.db`) ; have to end up with `.db` |
| DOCKER_DB_FOLDER | string | path to the sqlite db file's folder | required with docker, this will basically be the host machine folder (e.g. `./data`) that contains the sqlite db file | | DOCKER_DB_FOLDER | string | path to the sqlite db file's folder | required with docker, this will basically be the host machine folder (e.g. `./data`) that contains the sqlite db file |
| SMTP_EMAIL | string | sender email | required | | SMTP_EMAIL | string | sender email | required |
| SMTP_PASSWORD | string | smtp account password | required | | SMTP_PASSWORD | string | smtp account password | required |
@@ -0,0 +1,85 @@
package gateways
import (
entity "GoCMS/adapters/secondary/gateways/models"
"GoCMS/domain/gateways"
domain "GoCMS/domain/image"
"errors"
"github.com/google/uuid"
"gorm.io/gorm"
"mime/multipart"
"os"
)
type ImageRepository struct {
db *gorm.DB
}
func NewImageRepository(db *gorm.DB) *ImageRepository {
return &ImageRepository{db}
}
var contentTypeExtensions = map[string]string{
"image/png": ".png",
"image/jpeg": ".jpeg",
"image/webp": ".webp",
"image/svg+xml": ".svg",
}
func mapImageToDomain(image entity.Image) domain.Image {
return domain.FromDB(
image.ID,
image.Path,
image.PostID,
image.CreatedAt,
image.UpdatedAt,
)
}
func (i ImageRepository) Create(file multipart.File, fileHeader multipart.FileHeader) (domain.Image, error) {
fileBytes := make([]byte, fileHeader.Size)
_, err := file.Read(fileBytes)
if err != nil {
return domain.Image{}, err
}
err = os.MkdirAll("api/static/uploadedImages/", 0666)
if err != nil {
return domain.Image{}, err
}
contentType := fileHeader.Header.Get("Content-Type")
extension := contentTypeExtensions[contentType]
if extension == "" {
return domain.Image{}, errors.New("the file must be a PNG, JPEG, WEBP, or SVG image")
}
newName := uuid.NewString() + extension
err = os.WriteFile("api/static/uploadedImages/"+newName, fileBytes, 0666)
if err != nil {
return domain.Image{}, err
}
newImage := i.db.Create(&domain.Image{Path: "/static/uploadedImages/" + newName})
var createdImage entity.Image
newImage.Scan(&createdImage)
return mapImageToDomain(createdImage), nil
}
func (i ImageRepository) Delete(id uint32) error {
var image entity.Image
err := i.db.Model(&entity.Image{}).First(&image, id).Error
if err != nil {
return err
}
err = os.Remove("api" + image.Path)
if err != nil {
return err
}
return i.db.Delete(&entity.Image{}, id).Error
}
var _ gateways.IImageRepository = &ImageRepository{}
@@ -0,0 +1,15 @@
package models
import (
"gorm.io/gorm"
"time"
)
type Image struct {
gorm.Model
ID uint32 `gorm:"primary_key;auto_increment;not_null"`
Path string
PostID uint32
CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"`
}
@@ -10,6 +10,7 @@ type Post struct {
ID uint32 `gorm:"primary_key;auto_increment;not_null"` ID uint32 `gorm:"primary_key;auto_increment;not_null"`
Title string Title string
Body string Body string
Images []*Image `gorm:"many2many:post_images;"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"`
} }
+38 -8
View File
@@ -16,12 +16,12 @@ func NewPostRepository(db *gorm.DB) *PostRepository {
} }
func mapPostToDomain(post entity.Post) domain.Post { func mapPostToDomain(post entity.Post) domain.Post {
return domain.FromDb(post.ID, post.Title, post.Body, post.CreatedAt, post.UpdatedAt) return domain.FromDb(post.ID, post.Title, post.Body, post.Images, post.CreatedAt, post.UpdatedAt)
} }
func (a *PostRepository) Get(id uint32) (domain.Post, error) { func (a *PostRepository) Get(id uint32) (domain.Post, error) {
var post entity.Post var post entity.Post
err := a.db.Model(&entity.Post{}).First(&post, id).Error err := a.db.Model(&entity.Post{}).Preload("Images").First(&post, id).Error
if err != nil { if err != nil {
return domain.Post{}, err return domain.Post{}, err
} }
@@ -69,15 +69,49 @@ func (a *PostRepository) GetAll() []domain.Post {
return domainPosts return domainPosts
} }
func (a *PostRepository) UpdateBody(id uint32, body string) error { func (a *PostRepository) UpdateBody(id uint32, body string) (domain.Post, error) {
var localPost entity.Post var localPost entity.Post
err := a.db.Model(&entity.Post{}).First(&localPost, id).Error err := a.db.Model(&entity.Post{}).First(&localPost, id).Error
if err != nil { if err != nil {
return err return domain.Post{}, err
} }
localPost.Body = body localPost.Body = body
err = a.db.Save(&localPost).Error err = a.db.Save(&localPost).Error
if err != nil {
return domain.Post{}, err
}
newPost := domain.FromDb(
localPost.ID,
localPost.Title,
localPost.Body,
localPost.Images,
localPost.CreatedAt,
localPost.UpdatedAt,
)
return newPost, nil
}
func (a *PostRepository) Delete(id uint32) error {
return a.db.Delete(&entity.Post{}, id).Error
}
func (a *PostRepository) AddImage(postId uint32, imageId uint32) error {
var localPost entity.Post
err := a.db.Model(&entity.Post{}).First(&localPost, postId).Error
if err != nil {
return err
}
var localImage entity.Image
err = a.db.Model(&entity.Image{}).First(&localImage, imageId).Error
if err != nil {
return err
}
err = a.db.Model(&localPost).Association("Images").Append(&localImage)
if err != nil { if err != nil {
return err return err
} }
@@ -85,8 +119,4 @@ func (a *PostRepository) UpdateBody(id uint32, body string) error {
return nil return nil
} }
func (a *PostRepository) Delete(id uint32) error {
return a.db.Delete(&entity.Post{}, id).Error
}
var _ gateways.IPostRepository = &PostRepository{} var _ gateways.IPostRepository = &PostRepository{}
@@ -30,7 +30,7 @@
</div> </div>
</div> </div>
<div class="text-black-50 d-flex align-items-center justify-content-center h-100 py-3"> <div class="text-black-50 d-flex align-items-center justify-content-center h-100 py-3">
<textarea id="postBody" name="postBody">{{.Body}}</textarea> <textarea id="postBody" name="postBody">{{.Post.Body}}</textarea>
</div> </div>
</form> </form>
@@ -49,43 +49,43 @@
}, },
license_key: 'gpl', license_key: 'gpl',
images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {
// const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
// xhr.withCredentials = false; xhr.withCredentials = false;
// xhr.open('POST', 'postAcceptor.php'); xhr.open('POST', `/post/{{.Post.ID}}/image/create`);
//
// xhr.upload.onprogress = (e) => { xhr.upload.onprogress = (e) => {
// progress(e.loaded / e.total * 100); progress(e.loaded / e.total * 100);
// }; };
//
// xhr.onload = () => { xhr.onload = () => {
// if (xhr.status === 403) { if (xhr.status === 403) {
// reject({message: 'HTTP Error: ' + xhr.status, remove: true}); reject({message: 'HTTP Error: ' + xhr.status, remove: true});
// return; return;
// } }
//
// if (xhr.status < 200 || xhr.status >= 300) { if (xhr.status < 200 || xhr.status >= 300) {
// reject('HTTP Error: ' + xhr.status); reject('HTTP Error: ' + xhr.status);
// return; return;
// } }
//
// const json = JSON.parse(xhr.responseText); const json = JSON.parse(xhr.responseText);
//
// if (!json || typeof json.location != 'string') { if (!json || typeof json.location != 'string') {
// reject('Invalid JSON: ' + xhr.responseText); reject('Invalid JSON: ' + xhr.responseText);
// return; return;
// } }
//
// resolve(json.location); resolve(`http{{ if .Secured }}s{{ end }}://${window.location.host}${json.location}`);
// }; };
//
// xhr.onerror = () => { xhr.onerror = () => {
// reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status); reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
// }; };
//
// const formData = new FormData(); const formData = new FormData();
// formData.append('file', blobInfo.blob(), blobInfo.filename()); formData.append('file', blobInfo.blob(), blobInfo.filename());
//
// xhr.send(formData); xhr.send(formData);
}), }),
}) })
</script> </script>
+28 -24
View File
@@ -11,18 +11,20 @@ import (
) )
type UseCases struct { type UseCases struct {
CreatePostUseCase *useCases.CreatePostUseCase CreatePostUseCase *useCases.CreatePostUseCase
GetPostUseCase *useCases.GetPostUseCase GetPostUseCase *useCases.GetPostUseCase
ListPostsUseCase *useCases.ListPostsUseCase ListPostsUseCase *useCases.ListPostsUseCase
UpdatePostUseCase *useCases.UpdatePostUseCase UpdatePostUseCase *useCases.UpdatePostUseCase
DeletePostUseCase *useCases.DeletePostUseCase DeletePostUseCase *useCases.DeletePostUseCase
GetUserUseCase *useCases.GetUserUseCase GetUserUseCase *useCases.GetUserUseCase
CreateUserUseCase *useCases.CreateUserUseCase CreateUserUseCase *useCases.CreateUserUseCase
UpdateUserUseCase *useCases.UpdateUserUseCase UpdateUserUseCase *useCases.UpdateUserUseCase
DeleteUserUseCase *useCases.DeleteUserUseCase DeleteUserUseCase *useCases.DeleteUserUseCase
ListUsersUseCase *useCases.ListUsersUseCase ListUsersUseCase *useCases.ListUsersUseCase
GetPageUseCase *useCases.GetPageUseCase GetPageUseCase *useCases.GetPageUseCase
SendMailUseCase *useCases.SendMailUseCase SendMailUseCase *useCases.SendMailUseCase
CreateImageUseCase *useCases.CreateImageUseCase
DeleteImageUseCase *useCases.DeleteImageUseCase
} }
var Container *UseCases var Container *UseCases
@@ -48,18 +50,20 @@ func InitContainer() {
_ = digContainer.Provide(func(db *gorm.DB) *UseCases { _ = digContainer.Provide(func(db *gorm.DB) *UseCases {
return &UseCases{ return &UseCases{
CreatePostUseCase: useCases.NewCreatePostUseCase(db), CreatePostUseCase: useCases.NewCreatePostUseCase(db),
GetPostUseCase: useCases.NewGetPostUseCase(db), GetPostUseCase: useCases.NewGetPostUseCase(db),
ListPostsUseCase: useCases.NewListPostsUseCase(db), ListPostsUseCase: useCases.NewListPostsUseCase(db),
UpdatePostUseCase: useCases.NewUpdatePostUseCase(db), UpdatePostUseCase: useCases.NewUpdatePostUseCase(db),
DeletePostUseCase: useCases.NewDeletePostUseCase(db), DeletePostUseCase: useCases.NewDeletePostUseCase(db),
GetUserUseCase: useCases.NewGetUserUseCase(db), GetUserUseCase: useCases.NewGetUserUseCase(db),
CreateUserUseCase: useCases.NewCreateUserUseCase(db), CreateUserUseCase: useCases.NewCreateUserUseCase(db),
UpdateUserUseCase: useCases.NewUpdateUserUseCase(db), UpdateUserUseCase: useCases.NewUpdateUserUseCase(db),
DeleteUserUseCase: useCases.NewDeleteUserUseCase(db), DeleteUserUseCase: useCases.NewDeleteUserUseCase(db),
ListUsersUseCase: useCases.NewListUsersUseCase(db), ListUsersUseCase: useCases.NewListUsersUseCase(db),
GetPageUseCase: useCases.NewGetPageUseCase(), GetPageUseCase: useCases.NewGetPageUseCase(),
SendMailUseCase: useCases.NewSendMailUseCase(), SendMailUseCase: useCases.NewSendMailUseCase(),
CreateImageUseCase: useCases.NewCreateImageUseCase(db),
DeleteImageUseCase: useCases.NewDeleteImageUseCase(db),
} }
}) })
err := digContainer.Invoke(func(useCases *UseCases) { Container = useCases }) err := digContainer.Invoke(func(useCases *UseCases) { Container = useCases })
+38
View File
@@ -0,0 +1,38 @@
package api
import (
"encoding/json"
"github.com/go-chi/chi/v5"
"net/http"
"strconv"
)
func postImage(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm()
id := chi.URLParam(r, "id")
idInt, _ := strconv.Atoi(id)
file, fileHeader, err := r.FormFile("file")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
newImage, err := Container.CreateImageUseCase.CreateImage(file, *fileHeader)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = Container.UpdatePostUseCase.AddImage(uint32(idInt), newImage.ID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
newJson := map[string]interface{}{"location": newImage.Path}
newJsonBytes, _ := json.Marshal(newJson)
_, _ = w.Write(newJsonBytes)
}
+3 -8
View File
@@ -1,18 +1,13 @@
package api package api
import ( import (
"embed"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"html/template" "html/template"
"io/fs"
"net/http" "net/http"
"path/filepath" "path/filepath"
"strings" "strings"
) )
//go:embed static
var staticFolder embed.FS
var headTmpl template.HTML var headTmpl template.HTML
var contentTypes = map[string]string{ var contentTypes = map[string]string{
@@ -97,11 +92,10 @@ func InitHeadTmpl() {
func NewPageRouter() http.Handler { func NewPageRouter() http.Handler {
r := chi.NewRouter() r := chi.NewRouter()
contentStatic := fs.FS(staticFolder)
InitHeadTmpl() InitHeadTmpl()
r.Handle("/static/*", StaticFileServerWithContentType(http.FS(contentStatic))) fileServer := StaticFileServerWithContentType(http.Dir("api/static"))
r.Handle("/static/*", http.StripPrefix("/static/", fileServer))
r.Get("/", GetLogin) r.Get("/", GetLogin)
r.Get(LoginRoute, GetLoginPageHandler(EmptyLoginPage)) r.Get(LoginRoute, GetLoginPageHandler(EmptyLoginPage))
@@ -128,6 +122,7 @@ func NewPageRouter() http.Handler {
r.Get("/post/{id}/delete", GetPostDeletePage) r.Get("/post/{id}/delete", GetPostDeletePage)
r.Get("/post/create", GetPostCreatePage) r.Get("/post/create", GetPostCreatePage)
r.Post("/post/create", PostPostCreatePage) r.Post("/post/create", PostPostCreatePage)
r.Post("/post/{id}/image/create", postImage)
}) })
return r return r
+16
View File
@@ -1,6 +1,7 @@
package api package api
import ( import (
"fmt"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"net/http" "net/http"
"strconv" "strconv"
@@ -13,6 +14,21 @@ func GetPostDeletePage(w http.ResponseWriter, r *http.Request) {
return return
} }
localPost, err := Container.GetPostUseCase.GetPost(uint32(id))
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
fmt.Println(localPost.Images)
for _, image := range localPost.Images {
err = Container.DeleteImageUseCase.DeleteImage(image.ID)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
}
err = Container.DeletePostUseCase.DeletePost(uint32(id)) err = Container.DeletePostUseCase.DeletePost(uint32(id))
if err != nil { if err != nil {
http.Error(w, http.StatusText(400), http.StatusBadRequest) http.Error(w, http.StatusText(400), http.StatusBadRequest)
+15 -12
View File
@@ -1,9 +1,11 @@
package api package api
import ( import (
"GoCMS/domain/post"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"html/template" "html/template"
"net/http" "net/http"
"os"
"strconv" "strconv"
) )
@@ -12,13 +14,14 @@ type PostEditPageAlert struct {
Message string Message string
} }
func getPostEditPageTemplate(body string, alert PostEditPageAlert) []byte { func getPostEditPageTemplate(post post.Post, alert PostEditPageAlert) []byte {
navbarTmpl, _ := Container.GetPageUseCase.GetPage("componentNavbar", nil) navbarTmpl, _ := Container.GetPageUseCase.GetPage("componentNavbar", nil)
postTmpl, _ := Container.GetPageUseCase.GetPage("postEdit", map[string]interface{}{ postTmpl, _ := Container.GetPageUseCase.GetPage("postEdit", map[string]interface{}{
"Navbar": template.HTML(navbarTmpl), "Navbar": template.HTML(navbarTmpl),
"Head": headTmpl, "Head": headTmpl,
"Body": body, "Post": post,
"Alert": alert, "Alert": alert,
"Secured": os.Getenv("ENVIRONMENT") == "production",
}) })
return postTmpl return postTmpl
} }
@@ -27,7 +30,7 @@ func PostPostEditPage(w http.ResponseWriter, r *http.Request) {
postID := chi.URLParam(r, "id") postID := chi.URLParam(r, "id")
postIDint, err := strconv.Atoi(postID) postIDint, err := strconv.Atoi(postID)
if err != nil { if err != nil {
_, _ = w.Write(getPostEditPageTemplate("", PostEditPageAlert{ _, _ = w.Write(getPostEditPageTemplate(post.Post{}, PostEditPageAlert{
IsError: true, IsError: true,
Message: "Could not find the requested post.", Message: "Could not find the requested post.",
})) }))
@@ -37,17 +40,17 @@ func PostPostEditPage(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm() _ = r.ParseForm()
postBody := r.FormValue("postBody") postBody := r.FormValue("postBody")
post, _ := Container.GetPostUseCase.GetPost(uint32(postIDint)) getPost, _ := Container.GetPostUseCase.GetPost(uint32(postIDint))
err = Container.UpdatePostUseCase.UpdateBody(post.ID, postBody) updatedPost, err := Container.UpdatePostUseCase.UpdateBody(getPost.ID, postBody)
if err != nil { if err != nil {
_, _ = w.Write(getPostEditPageTemplate(postBody, PostEditPageAlert{ _, _ = w.Write(getPostEditPageTemplate(post.Post{Body: postBody}, PostEditPageAlert{
IsError: true, IsError: true,
Message: "Could not save the post: " + err.Error(), Message: "Could not save the post: " + err.Error(),
})) }))
return return
} }
_, _ = w.Write(getPostEditPageTemplate(postBody, PostEditPageAlert{ _, _ = w.Write(getPostEditPageTemplate(updatedPost, PostEditPageAlert{
IsError: false, IsError: false,
Message: "Post successfully edited!", Message: "Post successfully edited!",
})) }))
@@ -61,9 +64,9 @@ func GetPostEditPage(w http.ResponseWriter, r *http.Request) {
return return
} }
post, _ := Container.GetPostUseCase.GetPost(uint32(postIDint)) getPost, _ := Container.GetPostUseCase.GetPost(uint32(postIDint))
_, _ = w.Write(getPostEditPageTemplate(post.Body, PostEditPageAlert{ _, _ = w.Write(getPostEditPageTemplate(getPost, PostEditPageAlert{
IsError: false, IsError: false,
Message: "", Message: "",
})) }))
+11
View File
@@ -0,0 +1,11 @@
package gateways
import (
"GoCMS/domain/image"
"mime/multipart"
)
type IImageRepository interface {
Create(file multipart.File, fileHeader multipart.FileHeader) (image.Image, error)
Delete(id uint32) error
}
+2 -1
View File
@@ -9,6 +9,7 @@ type IPostRepository interface {
GetByName(name string) (post.Post, error) GetByName(name string) (post.Post, error)
GetAll() []post.Post GetAll() []post.Post
Create(post post.Post) (post.Post, error) Create(post post.Post) (post.Post, error)
UpdateBody(id uint32, body string) error UpdateBody(id uint32, body string) (post.Post, error)
Delete(id uint32) error Delete(id uint32) error
AddImage(postId uint32, imageId uint32) error
} }
+23
View File
@@ -0,0 +1,23 @@
package image
import (
"time"
)
type Image struct {
ID uint32
Path string
PostID uint32
CreatedAt time.Time
UpdatedAt time.Time
}
func FromDB(id uint32, path string, postId uint32, createdAt time.Time, updatedAt time.Time) Image {
return Image{
ID: id,
Path: path,
PostID: postId,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
}
}
+24 -6
View File
@@ -1,13 +1,18 @@
package post package post
import "time" import (
entity "GoCMS/adapters/secondary/gateways/models"
domain "GoCMS/domain/image"
"time"
)
type Post struct { type Post struct {
ID uint32 `json:"id"` ID uint32 `json:"id"`
Title string `json:"title"` Title string `json:"title"`
Body string `json:"body"` Body string `json:"body"`
CreatedAt time.Time `json:"created_at"` Images []*domain.Image `json:"images"`
UpdatedAt time.Time `json:"updated_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
} }
func FromApi( func FromApi(
@@ -24,13 +29,26 @@ func FromDb(
id uint32, id uint32,
title string, title string,
body string, body string,
images []*entity.Image,
createdAt time.Time, createdAt time.Time,
updatedAt time.Time, updatedAt time.Time,
) Post { ) Post {
domainImages := make([]*domain.Image, len(images))
for i, img := range images {
domainImage := domain.FromDB(
img.ID,
img.Path,
img.PostID,
img.CreatedAt,
img.UpdatedAt,
)
domainImages[i] = &domainImage
}
return Post{ return Post{
ID: id, ID: id,
Title: title, Title: title,
Body: body, Body: body,
Images: domainImages,
CreatedAt: createdAt, CreatedAt: createdAt,
UpdatedAt: updatedAt, UpdatedAt: updatedAt,
} }
+22
View File
@@ -0,0 +1,22 @@
package useCases
import (
"GoCMS/adapters/secondary/gateways"
"GoCMS/domain/image"
"gorm.io/gorm"
"mime/multipart"
)
type CreateImageUseCase struct {
imageRepository gateways.ImageRepository
}
func NewCreateImageUseCase(db *gorm.DB) *CreateImageUseCase {
return &CreateImageUseCase{
imageRepository: *gateways.NewImageRepository(db),
}
}
func (g *CreateImageUseCase) CreateImage(file multipart.File, fileHeader multipart.FileHeader) (image.Image, error) {
return g.imageRepository.Create(file, fileHeader)
}
+20
View File
@@ -0,0 +1,20 @@
package useCases
import (
"GoCMS/adapters/secondary/gateways"
"gorm.io/gorm"
)
type DeleteImageUseCase struct {
imageRepository gateways.ImageRepository
}
func NewDeleteImageUseCase(db *gorm.DB) *DeleteImageUseCase {
return &DeleteImageUseCase{
imageRepository: *gateways.NewImageRepository(db),
}
}
func (g *DeleteImageUseCase) DeleteImage(imageId uint32) error {
return g.imageRepository.Delete(imageId)
}
+6 -1
View File
@@ -2,6 +2,7 @@ package useCases
import ( import (
"GoCMS/adapters/secondary/gateways" "GoCMS/adapters/secondary/gateways"
"GoCMS/domain/post"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -15,6 +16,10 @@ func NewUpdatePostUseCase(db *gorm.DB) *UpdatePostUseCase {
} }
} }
func (g *UpdatePostUseCase) UpdateBody(id uint32, body string) error { func (g *UpdatePostUseCase) UpdateBody(id uint32, body string) (post.Post, error) {
return g.postRepository.UpdateBody(id, body) return g.postRepository.UpdateBody(id, body)
} }
func (g *UpdatePostUseCase) AddImage(postId uint32, imageId uint32) error {
return g.postRepository.AddImage(postId, imageId)
}