diff --git a/.air.toml b/.air.toml index a770bbd..cc88d09 100644 --- a/.air.toml +++ b/.air.toml @@ -7,7 +7,7 @@ tmp_dir = "tmp" bin = "tmp\\main.exe" cmd = "go build -o ./tmp/main.exe ./main" 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_regex = ["_test.go"] exclude_unchanged = false diff --git a/README.md b/README.md index cc4c7fc..dc46fe3 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ of course required, but not necessarily via the `.env` file. | PORT | int | port the API will use | required | | JWT_SECRET | string | secret for the jwt auth | required | | 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 | | SMTP_EMAIL | string | sender email | required | | SMTP_PASSWORD | string | smtp account password | required | diff --git a/adapters/secondary/gateways/imageRepository.go b/adapters/secondary/gateways/imageRepository.go new file mode 100644 index 0000000..be625ce --- /dev/null +++ b/adapters/secondary/gateways/imageRepository.go @@ -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{} diff --git a/adapters/secondary/gateways/models/image.go b/adapters/secondary/gateways/models/image.go new file mode 100644 index 0000000..6430f07 --- /dev/null +++ b/adapters/secondary/gateways/models/image.go @@ -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"` +} diff --git a/adapters/secondary/gateways/models/post.go b/adapters/secondary/gateways/models/post.go index f0bd730..497afda 100644 --- a/adapters/secondary/gateways/models/post.go +++ b/adapters/secondary/gateways/models/post.go @@ -10,6 +10,7 @@ type Post struct { ID uint32 `gorm:"primary_key;auto_increment;not_null"` Title string Body string + Images []*Image `gorm:"many2many:post_images;"` CreatedAt time.Time `gorm:"autoCreateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"` } diff --git a/adapters/secondary/gateways/postRepository.go b/adapters/secondary/gateways/postRepository.go index a3ec04c..068d1e3 100644 --- a/adapters/secondary/gateways/postRepository.go +++ b/adapters/secondary/gateways/postRepository.go @@ -16,12 +16,12 @@ func NewPostRepository(db *gorm.DB) *PostRepository { } 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) { 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 { return domain.Post{}, err } @@ -69,15 +69,49 @@ func (a *PostRepository) GetAll() []domain.Post { 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 err := a.db.Model(&entity.Post{}).First(&localPost, id).Error if err != nil { - return err + return domain.Post{}, err } localPost.Body = body 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 { return err } @@ -85,8 +119,4 @@ func (a *PostRepository) UpdateBody(id uint32, body string) error { return nil } -func (a *PostRepository) Delete(id uint32) error { - return a.db.Delete(&entity.Post{}, id).Error -} - var _ gateways.IPostRepository = &PostRepository{} diff --git a/adapters/secondary/gateways/web/templates/postEdit.html b/adapters/secondary/gateways/web/templates/postEdit.html index 2ce750e..7d50d86 100644 --- a/adapters/secondary/gateways/web/templates/postEdit.html +++ b/adapters/secondary/gateways/web/templates/postEdit.html @@ -30,7 +30,7 @@
- +
@@ -49,43 +49,43 @@ }, license_key: 'gpl', images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { - // const xhr = new XMLHttpRequest(); - // xhr.withCredentials = false; - // xhr.open('POST', 'postAcceptor.php'); - // - // xhr.upload.onprogress = (e) => { - // progress(e.loaded / e.total * 100); - // }; - // - // xhr.onload = () => { - // if (xhr.status === 403) { - // reject({message: 'HTTP Error: ' + xhr.status, remove: true}); - // return; - // } - // - // if (xhr.status < 200 || xhr.status >= 300) { - // reject('HTTP Error: ' + xhr.status); - // return; - // } - // - // const json = JSON.parse(xhr.responseText); - // - // if (!json || typeof json.location != 'string') { - // reject('Invalid JSON: ' + xhr.responseText); - // return; - // } - // - // resolve(json.location); - // }; - // - // xhr.onerror = () => { - // reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status); - // }; - // - // const formData = new FormData(); - // formData.append('file', blobInfo.blob(), blobInfo.filename()); - // - // xhr.send(formData); + const xhr = new XMLHttpRequest(); + xhr.withCredentials = false; + xhr.open('POST', `/post/{{.Post.ID}}/image/create`); + + xhr.upload.onprogress = (e) => { + progress(e.loaded / e.total * 100); + }; + + xhr.onload = () => { + if (xhr.status === 403) { + reject({message: 'HTTP Error: ' + xhr.status, remove: true}); + return; + } + + if (xhr.status < 200 || xhr.status >= 300) { + reject('HTTP Error: ' + xhr.status); + return; + } + + const json = JSON.parse(xhr.responseText); + + if (!json || typeof json.location != 'string') { + reject('Invalid JSON: ' + xhr.responseText); + return; + } + + resolve(`http{{ if .Secured }}s{{ end }}://${window.location.host}${json.location}`); + }; + + xhr.onerror = () => { + reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status); + }; + + const formData = new FormData(); + formData.append('file', blobInfo.blob(), blobInfo.filename()); + + xhr.send(formData); }), }) diff --git a/api/dependecyInjection.go b/api/dependecyInjection.go index 21d83e2..557616a 100644 --- a/api/dependecyInjection.go +++ b/api/dependecyInjection.go @@ -11,18 +11,20 @@ import ( ) type UseCases struct { - CreatePostUseCase *useCases.CreatePostUseCase - GetPostUseCase *useCases.GetPostUseCase - ListPostsUseCase *useCases.ListPostsUseCase - UpdatePostUseCase *useCases.UpdatePostUseCase - DeletePostUseCase *useCases.DeletePostUseCase - GetUserUseCase *useCases.GetUserUseCase - CreateUserUseCase *useCases.CreateUserUseCase - UpdateUserUseCase *useCases.UpdateUserUseCase - DeleteUserUseCase *useCases.DeleteUserUseCase - ListUsersUseCase *useCases.ListUsersUseCase - GetPageUseCase *useCases.GetPageUseCase - SendMailUseCase *useCases.SendMailUseCase + CreatePostUseCase *useCases.CreatePostUseCase + GetPostUseCase *useCases.GetPostUseCase + ListPostsUseCase *useCases.ListPostsUseCase + UpdatePostUseCase *useCases.UpdatePostUseCase + DeletePostUseCase *useCases.DeletePostUseCase + GetUserUseCase *useCases.GetUserUseCase + CreateUserUseCase *useCases.CreateUserUseCase + UpdateUserUseCase *useCases.UpdateUserUseCase + DeleteUserUseCase *useCases.DeleteUserUseCase + ListUsersUseCase *useCases.ListUsersUseCase + GetPageUseCase *useCases.GetPageUseCase + SendMailUseCase *useCases.SendMailUseCase + CreateImageUseCase *useCases.CreateImageUseCase + DeleteImageUseCase *useCases.DeleteImageUseCase } var Container *UseCases @@ -48,18 +50,20 @@ func InitContainer() { _ = digContainer.Provide(func(db *gorm.DB) *UseCases { return &UseCases{ - CreatePostUseCase: useCases.NewCreatePostUseCase(db), - GetPostUseCase: useCases.NewGetPostUseCase(db), - ListPostsUseCase: useCases.NewListPostsUseCase(db), - UpdatePostUseCase: useCases.NewUpdatePostUseCase(db), - DeletePostUseCase: useCases.NewDeletePostUseCase(db), - GetUserUseCase: useCases.NewGetUserUseCase(db), - CreateUserUseCase: useCases.NewCreateUserUseCase(db), - UpdateUserUseCase: useCases.NewUpdateUserUseCase(db), - DeleteUserUseCase: useCases.NewDeleteUserUseCase(db), - ListUsersUseCase: useCases.NewListUsersUseCase(db), - GetPageUseCase: useCases.NewGetPageUseCase(), - SendMailUseCase: useCases.NewSendMailUseCase(), + CreatePostUseCase: useCases.NewCreatePostUseCase(db), + GetPostUseCase: useCases.NewGetPostUseCase(db), + ListPostsUseCase: useCases.NewListPostsUseCase(db), + UpdatePostUseCase: useCases.NewUpdatePostUseCase(db), + DeletePostUseCase: useCases.NewDeletePostUseCase(db), + GetUserUseCase: useCases.NewGetUserUseCase(db), + CreateUserUseCase: useCases.NewCreateUserUseCase(db), + UpdateUserUseCase: useCases.NewUpdateUserUseCase(db), + DeleteUserUseCase: useCases.NewDeleteUserUseCase(db), + ListUsersUseCase: useCases.NewListUsersUseCase(db), + GetPageUseCase: useCases.NewGetPageUseCase(), + SendMailUseCase: useCases.NewSendMailUseCase(), + CreateImageUseCase: useCases.NewCreateImageUseCase(db), + DeleteImageUseCase: useCases.NewDeleteImageUseCase(db), } }) err := digContainer.Invoke(func(useCases *UseCases) { Container = useCases }) diff --git a/api/image.go b/api/image.go new file mode 100644 index 0000000..53e48c7 --- /dev/null +++ b/api/image.go @@ -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) +} diff --git a/api/page.go b/api/page.go index acf667f..0cd8885 100644 --- a/api/page.go +++ b/api/page.go @@ -1,18 +1,13 @@ package api import ( - "embed" "github.com/go-chi/chi/v5" "html/template" - "io/fs" "net/http" "path/filepath" "strings" ) -//go:embed static -var staticFolder embed.FS - var headTmpl template.HTML var contentTypes = map[string]string{ @@ -97,11 +92,10 @@ func InitHeadTmpl() { func NewPageRouter() http.Handler { r := chi.NewRouter() - contentStatic := fs.FS(staticFolder) - 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(LoginRoute, GetLoginPageHandler(EmptyLoginPage)) @@ -128,6 +122,7 @@ func NewPageRouter() http.Handler { r.Get("/post/{id}/delete", GetPostDeletePage) r.Get("/post/create", GetPostCreatePage) r.Post("/post/create", PostPostCreatePage) + r.Post("/post/{id}/image/create", postImage) }) return r diff --git a/api/pagePostDelete.go b/api/pagePostDelete.go index 2d4ea3a..ccc0784 100644 --- a/api/pagePostDelete.go +++ b/api/pagePostDelete.go @@ -1,6 +1,7 @@ package api import ( + "fmt" "github.com/go-chi/chi/v5" "net/http" "strconv" @@ -13,6 +14,21 @@ func GetPostDeletePage(w http.ResponseWriter, r *http.Request) { 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)) if err != nil { http.Error(w, http.StatusText(400), http.StatusBadRequest) diff --git a/api/pagePostEdit.go b/api/pagePostEdit.go index a706756..7f1e544 100644 --- a/api/pagePostEdit.go +++ b/api/pagePostEdit.go @@ -1,9 +1,11 @@ package api import ( + "GoCMS/domain/post" "github.com/go-chi/chi/v5" "html/template" "net/http" + "os" "strconv" ) @@ -12,13 +14,14 @@ type PostEditPageAlert struct { Message string } -func getPostEditPageTemplate(body string, alert PostEditPageAlert) []byte { +func getPostEditPageTemplate(post post.Post, alert PostEditPageAlert) []byte { navbarTmpl, _ := Container.GetPageUseCase.GetPage("componentNavbar", nil) postTmpl, _ := Container.GetPageUseCase.GetPage("postEdit", map[string]interface{}{ - "Navbar": template.HTML(navbarTmpl), - "Head": headTmpl, - "Body": body, - "Alert": alert, + "Navbar": template.HTML(navbarTmpl), + "Head": headTmpl, + "Post": post, + "Alert": alert, + "Secured": os.Getenv("ENVIRONMENT") == "production", }) return postTmpl } @@ -27,7 +30,7 @@ func PostPostEditPage(w http.ResponseWriter, r *http.Request) { postID := chi.URLParam(r, "id") postIDint, err := strconv.Atoi(postID) if err != nil { - _, _ = w.Write(getPostEditPageTemplate("", PostEditPageAlert{ + _, _ = w.Write(getPostEditPageTemplate(post.Post{}, PostEditPageAlert{ IsError: true, Message: "Could not find the requested post.", })) @@ -37,17 +40,17 @@ func PostPostEditPage(w http.ResponseWriter, r *http.Request) { _ = r.ParseForm() postBody := r.FormValue("postBody") - post, _ := Container.GetPostUseCase.GetPost(uint32(postIDint)) - err = Container.UpdatePostUseCase.UpdateBody(post.ID, postBody) + getPost, _ := Container.GetPostUseCase.GetPost(uint32(postIDint)) + updatedPost, err := Container.UpdatePostUseCase.UpdateBody(getPost.ID, postBody) if err != nil { - _, _ = w.Write(getPostEditPageTemplate(postBody, PostEditPageAlert{ + _, _ = w.Write(getPostEditPageTemplate(post.Post{Body: postBody}, PostEditPageAlert{ IsError: true, Message: "Could not save the post: " + err.Error(), })) return } - _, _ = w.Write(getPostEditPageTemplate(postBody, PostEditPageAlert{ + _, _ = w.Write(getPostEditPageTemplate(updatedPost, PostEditPageAlert{ IsError: false, Message: "Post successfully edited!", })) @@ -61,9 +64,9 @@ func GetPostEditPage(w http.ResponseWriter, r *http.Request) { 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, Message: "", })) diff --git a/domain/gateways/IImageRepository.go b/domain/gateways/IImageRepository.go new file mode 100644 index 0000000..0443ddb --- /dev/null +++ b/domain/gateways/IImageRepository.go @@ -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 +} diff --git a/domain/gateways/IPostRepository.go b/domain/gateways/IPostRepository.go index 66fe876..857ecbe 100644 --- a/domain/gateways/IPostRepository.go +++ b/domain/gateways/IPostRepository.go @@ -9,6 +9,7 @@ type IPostRepository interface { GetByName(name string) (post.Post, error) GetAll() []post.Post 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 + AddImage(postId uint32, imageId uint32) error } diff --git a/domain/image/image.go b/domain/image/image.go new file mode 100644 index 0000000..2f83483 --- /dev/null +++ b/domain/image/image.go @@ -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, + } +} diff --git a/domain/post/post.go b/domain/post/post.go index 2a42e0f..40e16c3 100644 --- a/domain/post/post.go +++ b/domain/post/post.go @@ -1,13 +1,18 @@ package post -import "time" +import ( + entity "GoCMS/adapters/secondary/gateways/models" + domain "GoCMS/domain/image" + "time" +) type Post struct { - ID uint32 `json:"id"` - Title string `json:"title"` - Body string `json:"body"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ID uint32 `json:"id"` + Title string `json:"title"` + Body string `json:"body"` + Images []*domain.Image `json:"images"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } func FromApi( @@ -24,13 +29,26 @@ func FromDb( id uint32, title string, body string, + images []*entity.Image, createdAt time.Time, updatedAt time.Time, ) 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{ ID: id, Title: title, Body: body, + Images: domainImages, CreatedAt: createdAt, UpdatedAt: updatedAt, } diff --git a/useCases/CreateImageUseCase.go b/useCases/CreateImageUseCase.go new file mode 100644 index 0000000..c598a5f --- /dev/null +++ b/useCases/CreateImageUseCase.go @@ -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) +} diff --git a/useCases/DeleteImageUseCase.go b/useCases/DeleteImageUseCase.go new file mode 100644 index 0000000..c1e63e9 --- /dev/null +++ b/useCases/DeleteImageUseCase.go @@ -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) +} diff --git a/useCases/UpdatePostUseCase.go b/useCases/UpdatePostUseCase.go index 60b9b0f..2674830 100644 --- a/useCases/UpdatePostUseCase.go +++ b/useCases/UpdatePostUseCase.go @@ -2,6 +2,7 @@ package useCases import ( "GoCMS/adapters/secondary/gateways" + "GoCMS/domain/post" "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) } + +func (g *UpdatePostUseCase) AddImage(postId uint32, imageId uint32) error { + return g.postRepository.AddImage(postId, imageId) +}