edit feature
This commit is contained in:
parent
a610515d5e
commit
e628735ab2
|
@ -38,7 +38,7 @@ func TestEditorFormGet(t *testing.T) {
|
||||||
app := owlApp.FiberApp
|
app := owlApp.FiberApp
|
||||||
token := getUserToken(owlApp.AuthorService)
|
token := getUserToken(owlApp.AuthorService)
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "/editor/Image", nil)
|
req := httptest.NewRequest("GET", "/editor/new/Image", nil)
|
||||||
req.AddCookie(&http.Cookie{Name: "token", Value: token})
|
req.AddCookie(&http.Cookie{Name: "token", Value: token})
|
||||||
resp, err := app.Test(req)
|
resp, err := app.Test(req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -50,7 +50,7 @@ func TestEditorFormGetNoAuth(t *testing.T) {
|
||||||
owlApp := App(db)
|
owlApp := App(db)
|
||||||
app := owlApp.FiberApp
|
app := owlApp.FiberApp
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "/editor/Image", nil)
|
req := httptest.NewRequest("GET", "/editor/new/Image", nil)
|
||||||
req.AddCookie(&http.Cookie{Name: "token", Value: "invalid"})
|
req.AddCookie(&http.Cookie{Name: "token", Value: "invalid"})
|
||||||
resp, err := app.Test(req)
|
resp, err := app.Test(req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -83,7 +83,7 @@ func TestEditorFormPost(t *testing.T) {
|
||||||
io.WriteString(part, "test content")
|
io.WriteString(part, "test content")
|
||||||
writer.Close()
|
writer.Close()
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "/editor/Image", body)
|
req := httptest.NewRequest("POST", "/editor/new/Image", body)
|
||||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
req.AddCookie(&http.Cookie{Name: "token", Value: token})
|
req.AddCookie(&http.Cookie{Name: "token", Value: token})
|
||||||
resp, err := app.Test(req)
|
resp, err := app.Test(req)
|
||||||
|
@ -125,7 +125,7 @@ func TestEditorFormPostNoAuth(t *testing.T) {
|
||||||
io.WriteString(part, "test content")
|
io.WriteString(part, "test content")
|
||||||
writer.Close()
|
writer.Close()
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "/editor/Image", body)
|
req := httptest.NewRequest("POST", "/editor/new/Image", body)
|
||||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
req.AddCookie(&http.Cookie{Name: "token", Value: "invalid"})
|
req.AddCookie(&http.Cookie{Name: "token", Value: "invalid"})
|
||||||
resp, err := app.Test(req)
|
resp, err := app.Test(req)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{{range .Types}}
|
{{range .Types}}
|
||||||
<li><a href="/editor/{{.}}">{{.}}</a></li>
|
<li><a href="/editor/new/{{.}}/">{{.}}</a></li>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
|
@ -29,6 +29,13 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{ if .LoggedIn }}
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<a href="/editor/edit/{{.Entry.ID}}/" role="button" class="secondary outline">Edit</a>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ func NewWebApp(
|
||||||
configRegister *app.ConfigRegister,
|
configRegister *app.ConfigRegister,
|
||||||
) *WebApp {
|
) *WebApp {
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
app.Use(middleware.NewUserMiddleware(authorService).Handle)
|
||||||
|
|
||||||
indexHandler := NewIndexHandler(entryService, configRepo)
|
indexHandler := NewIndexHandler(entryService, configRepo)
|
||||||
listHandler := NewListHandler(entryService, configRepo)
|
listHandler := NewListHandler(entryService, configRepo)
|
||||||
|
@ -62,8 +63,10 @@ func NewWebApp(
|
||||||
editor := app.Group("/editor")
|
editor := app.Group("/editor")
|
||||||
editor.Use(middleware.NewAuthMiddleware(authorService).Handle)
|
editor.Use(middleware.NewAuthMiddleware(authorService).Handle)
|
||||||
editor.Get("/", editorListHandler.Handle)
|
editor.Get("/", editorListHandler.Handle)
|
||||||
editor.Get("/:editor/", editorHandler.HandleGet)
|
editor.Get("/new/:editor/", editorHandler.HandleGetNew)
|
||||||
editor.Post("/:editor/", editorHandler.HandlePost)
|
editor.Post("/new/:editor/", editorHandler.HandlePostNew)
|
||||||
|
editor.Get("/edit/:id/", editorHandler.HandleGetEdit)
|
||||||
|
editor.Post("/edit/:id/", editorHandler.HandlePostEdit)
|
||||||
|
|
||||||
// SiteConfig
|
// SiteConfig
|
||||||
siteConfig := app.Group("/site-config")
|
siteConfig := app.Group("/site-config")
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
package editor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"mime/multipart"
|
|
||||||
"owl-blogs/app"
|
|
||||||
"owl-blogs/domain/model"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HttpFormData interface {
|
|
||||||
// FormFile returns the first file by key from a MultipartForm.
|
|
||||||
FormFile(key string) (*multipart.FileHeader, error)
|
|
||||||
// FormValue returns the first value by key from a MultipartForm.
|
|
||||||
// Search is performed in QueryArgs, PostArgs, MultipartForm and FormFile in this particular order.
|
|
||||||
// Defaults to the empty string "" if the form value doesn't exist.
|
|
||||||
// If a default value is given, it will return that value if the form value does not exist.
|
|
||||||
// Returned value is only valid within the handler. Do not store any references.
|
|
||||||
// Make copies or use the Immutable setting instead.
|
|
||||||
FormValue(key string, defaultValue ...string) string
|
|
||||||
}
|
|
||||||
|
|
||||||
type EditorEntryForm struct {
|
|
||||||
entry model.Entry
|
|
||||||
binSvc *app.BinaryService
|
|
||||||
}
|
|
||||||
|
|
||||||
type EntryFormFieldParams struct {
|
|
||||||
InputType string
|
|
||||||
Widget string
|
|
||||||
}
|
|
||||||
|
|
||||||
type EntryFormField struct {
|
|
||||||
Name string
|
|
||||||
Params EntryFormFieldParams
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEntryForm(entry model.Entry, binaryService *app.BinaryService) *EditorEntryForm {
|
|
||||||
return &EditorEntryForm{
|
|
||||||
entry: entry,
|
|
||||||
binSvc: binaryService,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EntryFormFieldParams) ApplyTag(tagKey string, tagValue string) error {
|
|
||||||
switch tagKey {
|
|
||||||
case "inputType":
|
|
||||||
s.InputType = tagValue
|
|
||||||
case "widget":
|
|
||||||
s.Widget = tagValue
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unknown tag key: %v", tagKey)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EntryFormField) Html() string {
|
|
||||||
html := ""
|
|
||||||
html += fmt.Sprintf("<label for=\"%v\">%v</label>\n", s.Name, s.Name)
|
|
||||||
if s.Params.InputType == "text" && s.Params.Widget == "textarea" {
|
|
||||||
html += fmt.Sprintf("<textarea name=\"%v\" id=\"%v\" rows=\"20\"></textarea>\n", s.Name, s.Name)
|
|
||||||
} else {
|
|
||||||
html += fmt.Sprintf("<input type=\"%v\" name=\"%v\" id=\"%v\" />\n", s.Params.InputType, s.Name, s.Name)
|
|
||||||
}
|
|
||||||
return html
|
|
||||||
}
|
|
||||||
|
|
||||||
func FieldToFormField(field reflect.StructField) (EntryFormField, error) {
|
|
||||||
formField := EntryFormField{
|
|
||||||
Name: field.Name,
|
|
||||||
Params: EntryFormFieldParams{},
|
|
||||||
}
|
|
||||||
tag := field.Tag.Get("owl")
|
|
||||||
for _, param := range strings.Split(tag, " ") {
|
|
||||||
parts := strings.Split(param, "=")
|
|
||||||
if len(parts) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err := formField.Params.ApplyTag(parts[0], parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return EntryFormField{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return formField, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func StructToFormFields(meta interface{}) ([]EntryFormField, error) {
|
|
||||||
entryType := reflect.TypeOf(meta).Elem()
|
|
||||||
numFields := entryType.NumField()
|
|
||||||
fields := []EntryFormField{}
|
|
||||||
for i := 0; i < numFields; i++ {
|
|
||||||
field, err := FieldToFormField(entryType.Field(i))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fields = append(fields, field)
|
|
||||||
}
|
|
||||||
return fields, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EditorEntryForm) HtmlForm() (string, error) {
|
|
||||||
meta := s.entry.MetaData()
|
|
||||||
fields, err := StructToFormFields(meta)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
html := "<form method=\"POST\" enctype=\"multipart/form-data\">\n"
|
|
||||||
for _, field := range fields {
|
|
||||||
html += field.Html()
|
|
||||||
}
|
|
||||||
html += "<input type=\"submit\" value=\"Submit\" />\n"
|
|
||||||
html += "</form>\n"
|
|
||||||
|
|
||||||
return html, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EditorEntryForm) Parse(ctx HttpFormData) (model.Entry, error) {
|
|
||||||
if ctx == nil {
|
|
||||||
return nil, fmt.Errorf("nil context")
|
|
||||||
}
|
|
||||||
meta := s.entry.MetaData()
|
|
||||||
metaVal := reflect.ValueOf(meta)
|
|
||||||
if metaVal.Kind() != reflect.Ptr {
|
|
||||||
return nil, fmt.Errorf("meta data is not a pointer")
|
|
||||||
}
|
|
||||||
fields, err := StructToFormFields(meta)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, field := range fields {
|
|
||||||
fieldName := field.Name
|
|
||||||
|
|
||||||
if field.Params.InputType == "file" {
|
|
||||||
file, err := ctx.FormFile(fieldName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fileData, err := file.Open()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer fileData.Close()
|
|
||||||
fileBytes := make([]byte, file.Size)
|
|
||||||
_, err = fileData.Read(fileBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
binaryFile, err := s.binSvc.Create(file.Filename, fileBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
metaField := metaVal.Elem().FieldByName(fieldName)
|
|
||||||
if metaField.IsValid() {
|
|
||||||
metaField.SetString(binaryFile.Id)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
formValue := ctx.FormValue(fieldName)
|
|
||||||
metaField := metaVal.Elem().FieldByName(fieldName)
|
|
||||||
if metaField.IsValid() {
|
|
||||||
metaField.SetString(formValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.entry, nil
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"owl-blogs/app/repository"
|
"owl-blogs/app/repository"
|
||||||
"owl-blogs/domain/model"
|
"owl-blogs/domain/model"
|
||||||
"owl-blogs/render"
|
"owl-blogs/render"
|
||||||
"owl-blogs/web/editor"
|
"owl-blogs/web/forms"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
@ -41,7 +41,7 @@ func (h *EditorHandler) paramToEntry(c *fiber.Ctx) (model.Entry, error) {
|
||||||
return entryType, nil
|
return entryType, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *EditorHandler) HandleGet(c *fiber.Ctx) error {
|
func (h *EditorHandler) HandleGetNew(c *fiber.Ctx) error {
|
||||||
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
||||||
|
|
||||||
entryType, err := h.paramToEntry(c)
|
entryType, err := h.paramToEntry(c)
|
||||||
|
@ -49,7 +49,7 @@ func (h *EditorHandler) HandleGet(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
form := editor.NewEntryForm(entryType, h.binSvc)
|
form := forms.NewForm(entryType.MetaData(), h.binSvc)
|
||||||
htmlForm, err := form.HtmlForm()
|
htmlForm, err := form.HtmlForm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -57,23 +57,24 @@ func (h *EditorHandler) HandleGet(c *fiber.Ctx) error {
|
||||||
return render.RenderTemplateWithBase(c, getSiteConfig(h.configRepo), "views/editor", htmlForm)
|
return render.RenderTemplateWithBase(c, getSiteConfig(h.configRepo), "views/editor", htmlForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *EditorHandler) HandlePost(c *fiber.Ctx) error {
|
func (h *EditorHandler) HandlePostNew(c *fiber.Ctx) error {
|
||||||
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
||||||
|
|
||||||
entryType, err := h.paramToEntry(c)
|
entry, err := h.paramToEntry(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
form := editor.NewEntryForm(entryType, h.binSvc)
|
form := forms.NewForm(entry.MetaData(), h.binSvc)
|
||||||
// get form data
|
// get form data
|
||||||
entry, err := form.Parse(c)
|
entryMeta, err := form.Parse(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create entry
|
// create entry
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
entry.SetMetaData(entryMeta)
|
||||||
entry.SetPublishedAt(&now)
|
entry.SetPublishedAt(&now)
|
||||||
entry.SetAuthorId(c.Locals("author").(string))
|
entry.SetAuthorId(c.Locals("author").(string))
|
||||||
|
|
||||||
|
@ -84,3 +85,45 @@ func (h *EditorHandler) HandlePost(c *fiber.Ctx) error {
|
||||||
return c.Redirect("/posts/" + entry.ID() + "/")
|
return c.Redirect("/posts/" + entry.ID() + "/")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *EditorHandler) HandleGetEdit(c *fiber.Ctx) error {
|
||||||
|
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
||||||
|
|
||||||
|
id := c.Params("id")
|
||||||
|
entry, err := h.entrySvc.FindById(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
form := forms.NewForm(entry.MetaData(), h.binSvc)
|
||||||
|
htmlForm, err := form.HtmlForm()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return render.RenderTemplateWithBase(c, getSiteConfig(h.configRepo), "views/editor", htmlForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *EditorHandler) HandlePostEdit(c *fiber.Ctx) error {
|
||||||
|
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
||||||
|
|
||||||
|
id := c.Params("id")
|
||||||
|
entry, err := h.entrySvc.FindById(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
form := forms.NewForm(entry.MetaData(), h.binSvc)
|
||||||
|
// get form data
|
||||||
|
meta, err := form.Parse(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update entry
|
||||||
|
entry.SetMetaData(meta)
|
||||||
|
err = h.entrySvc.Update(entry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.Redirect("/posts/" + entry.ID() + "/")
|
||||||
|
}
|
||||||
|
|
|
@ -17,8 +17,9 @@ type EntryHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type entryData struct {
|
type entryData struct {
|
||||||
Entry model.Entry
|
Entry model.Entry
|
||||||
Author *model.Author
|
Author *model.Author
|
||||||
|
LoggedIn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEntryHandler(
|
func NewEntryHandler(
|
||||||
|
@ -49,5 +50,14 @@ func (h *EntryHandler) Handle(c *fiber.Ctx) error {
|
||||||
author = &model.Author{}
|
author = &model.Author{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return render.RenderTemplateWithBase(c, getSiteConfig(h.configRepo), "views/entry", entryData{Entry: entry, Author: author})
|
return render.RenderTemplateWithBase(
|
||||||
|
c,
|
||||||
|
getSiteConfig(h.configRepo),
|
||||||
|
"views/entry",
|
||||||
|
entryData{
|
||||||
|
Entry: entry,
|
||||||
|
Author: author,
|
||||||
|
LoggedIn: c.Locals("author") != nil,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,14 @@ func (s *Form) Parse(ctx HttpFormData) (interface{}, error) {
|
||||||
if field.Params.InputType == "file" {
|
if field.Params.InputType == "file" {
|
||||||
file, err := ctx.FormFile(fieldName)
|
file, err := ctx.FormFile(fieldName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// If field already has a value, we can ignore the error
|
||||||
|
if field.Value != "" {
|
||||||
|
metaField := dataVal.Elem().FieldByName(fieldName)
|
||||||
|
if metaField.IsValid() {
|
||||||
|
metaField.SetString(field.Value)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fileData, err := file.Open()
|
fileData, err := file.Open()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package editor_test
|
package forms_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -6,10 +6,9 @@ import (
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
"owl-blogs/app"
|
"owl-blogs/app"
|
||||||
"owl-blogs/domain/model"
|
|
||||||
"owl-blogs/infra"
|
"owl-blogs/infra"
|
||||||
"owl-blogs/test"
|
"owl-blogs/test"
|
||||||
"owl-blogs/web/editor"
|
"owl-blogs/web/forms"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -18,7 +17,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockEntryMetaData struct {
|
type MockData struct {
|
||||||
Image string `owl:"inputType=file"`
|
Image string `owl:"inputType=file"`
|
||||||
Content string `owl:"inputType=text"`
|
Content string `owl:"inputType=text"`
|
||||||
}
|
}
|
||||||
|
@ -65,37 +64,16 @@ func (f *MockFormData) FormValue(key string, defaultValue ...string) string {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
type MockEntry struct {
|
|
||||||
model.EntryBase
|
|
||||||
metaData MockEntryMetaData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *MockEntry) Content() model.EntryContent {
|
|
||||||
return model.EntryContent(e.metaData.Content)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *MockEntry) MetaData() interface{} {
|
|
||||||
return &e.metaData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *MockEntry) SetMetaData(metaData interface{}) {
|
|
||||||
e.metaData = *metaData.(*MockEntryMetaData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *MockEntry) Title() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFieldToFormField(t *testing.T) {
|
func TestFieldToFormField(t *testing.T) {
|
||||||
field := reflect.TypeOf(&MockEntryMetaData{}).Elem().Field(0)
|
field := reflect.TypeOf(&MockData{}).Elem().Field(0)
|
||||||
formField, err := editor.FieldToFormField(field)
|
formField, err := forms.FieldToFormField(field, "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "Image", formField.Name)
|
require.Equal(t, "Image", formField.Name)
|
||||||
require.Equal(t, "file", formField.Params.InputType)
|
require.Equal(t, "file", formField.Params.InputType)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructToFields(t *testing.T) {
|
func TestStructToFields(t *testing.T) {
|
||||||
fields, err := editor.StructToFormFields(&MockEntryMetaData{})
|
fields, err := forms.StructToFormFields(&MockData{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, fields, 2)
|
require.Len(t, fields, 2)
|
||||||
require.Equal(t, "Image", fields[0].Name)
|
require.Equal(t, "Image", fields[0].Name)
|
||||||
|
@ -104,8 +82,8 @@ func TestStructToFields(t *testing.T) {
|
||||||
require.Equal(t, "text", fields[1].Params.InputType)
|
require.Equal(t, "text", fields[1].Params.InputType)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEditorEntryForm_HtmlForm(t *testing.T) {
|
func TestForm_HtmlForm(t *testing.T) {
|
||||||
form := editor.NewEntryForm(&MockEntry{}, nil)
|
form := forms.NewForm(&MockData{}, nil)
|
||||||
html, err := form.HtmlForm()
|
html, err := form.HtmlForm()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Contains(t, html, "<form")
|
require.Contains(t, html, "<form")
|
||||||
|
@ -117,7 +95,7 @@ func TestEditorEntryForm_HtmlForm(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormParseNil(t *testing.T) {
|
func TestFormParseNil(t *testing.T) {
|
||||||
form := editor.NewEntryForm(&MockEntry{}, nil)
|
form := forms.NewForm(&MockData{}, nil)
|
||||||
_, err := form.Parse(nil)
|
_, err := form.Parse(nil)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
@ -125,9 +103,9 @@ func TestFormParseNil(t *testing.T) {
|
||||||
func TestFormParse(t *testing.T) {
|
func TestFormParse(t *testing.T) {
|
||||||
binRepo := infra.NewBinaryFileRepo(test.NewMockDb())
|
binRepo := infra.NewBinaryFileRepo(test.NewMockDb())
|
||||||
binService := app.NewBinaryFileService(binRepo)
|
binService := app.NewBinaryFileService(binRepo)
|
||||||
form := editor.NewEntryForm(&MockEntry{}, binService)
|
form := forms.NewForm(&MockData{}, binService)
|
||||||
entry, err := form.Parse(NewMockFormData())
|
data, err := form.Parse(NewMockFormData())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotZero(t, entry.MetaData().(*MockEntryMetaData).Image)
|
require.NotZero(t, data.(*MockData).Image)
|
||||||
require.Equal(t, "Content", entry.MetaData().(*MockEntryMetaData).Content)
|
require.Equal(t, "Content", data.(*MockData).Content)
|
||||||
}
|
}
|
|
@ -10,21 +10,37 @@ type AuthMiddleware struct {
|
||||||
authorService *app.AuthorService
|
authorService *app.AuthorService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserMiddleware struct {
|
||||||
|
authorService *app.AuthorService
|
||||||
|
}
|
||||||
|
|
||||||
func NewAuthMiddleware(authorService *app.AuthorService) *AuthMiddleware {
|
func NewAuthMiddleware(authorService *app.AuthorService) *AuthMiddleware {
|
||||||
return &AuthMiddleware{authorService: authorService}
|
return &AuthMiddleware{authorService: authorService}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewUserMiddleware(authorService *app.AuthorService) *UserMiddleware {
|
||||||
|
return &UserMiddleware{authorService: authorService}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *AuthMiddleware) Handle(c *fiber.Ctx) error {
|
func (m *AuthMiddleware) Handle(c *fiber.Ctx) error {
|
||||||
|
if c.Locals("author") == nil {
|
||||||
|
return c.Redirect("/auth/login")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UserMiddleware) Handle(c *fiber.Ctx) error {
|
||||||
// get token from cookie
|
// get token from cookie
|
||||||
token := c.Cookies("token")
|
token := c.Cookies("token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
return c.Redirect("/auth/login")
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check token
|
// check token
|
||||||
valid, name := m.authorService.ValidateToken(token)
|
valid, name := m.authorService.ValidateToken(token)
|
||||||
if !valid {
|
if !valid {
|
||||||
return c.Redirect("/auth/login")
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// set author name to context
|
// set author name to context
|
||||||
|
|
Loading…
Reference in New Issue