v2 #43

Merged
h4kor merged 41 commits from v2 into main 2023-07-19 19:09:19 +00:00
10 changed files with 195 additions and 11 deletions
Showing only changes of commit 9301790408 - Show all commits

22
app/binary_service.go Normal file
View File

@ -0,0 +1,22 @@
package app
import (
"owl-blogs/app/repository"
"owl-blogs/domain/model"
)
type BinaryService struct {
repo repository.BinaryRepository
}
func NewBinaryFileService(repo repository.BinaryRepository) *BinaryService {
return &BinaryService{repo: repo}
}
func (s *BinaryService) Create(name string, file []byte) (*model.BinaryFile, error) {
return s.repo.Create(name, file)
}
func (s *BinaryService) FindById(id string) (*model.BinaryFile, error) {
return s.repo.FindById(id)
}

View File

@ -47,5 +47,12 @@ func (r *EntryTypeRegistry) Type(name string) (model.Entry, error) {
if _, ok := r.types[name]; !ok { if _, ok := r.types[name]; !ok {
return nil, errors.New("entry type not registered") return nil, errors.New("entry type not registered")
} }
return r.types[name], nil
val := reflect.ValueOf(r.types[name])
if val.Kind() == reflect.Ptr {
val = reflect.Indirect(val)
}
newEntry := reflect.New(val.Type()).Interface().(model.Entry)
return newEntry, nil
} }

View File

@ -12,3 +12,8 @@ type EntryRepository interface {
FindById(id string) (model.Entry, error) FindById(id string) (model.Entry, error)
FindAll(types *[]string) ([]model.Entry, error) FindAll(types *[]string) ([]model.Entry, error)
} }
type BinaryRepository interface {
Create(name string, data []byte) (*model.BinaryFile, error)
FindById(id string) (*model.BinaryFile, error)
}

View File

@ -14,9 +14,12 @@ func App(db infra.Database) *web.WebApp {
registry.Register(&model.ImageEntry{}) registry.Register(&model.ImageEntry{})
repo := infra.NewEntryRepository(db, registry) entryRepo := infra.NewEntryRepository(db, registry)
entryService := app.NewEntryService(repo) binRepo := infra.NewBinaryFileRepo(db)
return web.NewWebApp(entryService, registry)
entryService := app.NewEntryService(entryRepo)
binaryService := app.NewBinaryFileService(binRepo)
return web.NewWebApp(entryService, registry, binaryService)
} }

View File

@ -0,0 +1,7 @@
package model
type BinaryFile struct {
Id string
Name string
Data []byte
}

View File

@ -9,7 +9,7 @@ type ImageEntry struct {
} }
type ImageEntryMetaData struct { type ImageEntryMetaData struct {
ImagePath string `owl:"inputType=file"` ImageId string `owl:"inputType=file"`
Content string `owl:"inputType=text widget=textarea"` Content string `owl:"inputType=text widget=textarea"`
} }

View File

@ -0,0 +1,51 @@
package infra
import (
"owl-blogs/domain/model"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
)
type sqlBinaryFile struct {
Id string `db:"id"`
Name string `db:"name"`
Data []byte `db:"data"`
}
type DefaultBinaryFileRepo struct {
db *sqlx.DB
}
func NewBinaryFileRepo(db Database) *DefaultBinaryFileRepo {
sqlxdb := db.Get()
// Create table if not exists
sqlxdb.MustExec(`
CREATE TABLE IF NOT EXISTS binary_files (
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
data BLOB NOT NULL
);
`)
return &DefaultBinaryFileRepo{db: sqlxdb}
}
func (repo *DefaultBinaryFileRepo) Create(name string, data []byte) (*model.BinaryFile, error) {
id := uuid.New().String()
_, err := repo.db.Exec("INSERT INTO binary_files (id, name, data) VALUES (?, ?, ?)", id, name, data)
if err != nil {
return nil, err
}
return &model.BinaryFile{Id: id, Name: name, Data: data}, nil
}
func (repo *DefaultBinaryFileRepo) FindById(id string) (*model.BinaryFile, error) {
var sqlFile sqlBinaryFile
err := repo.db.Get(&sqlFile, "SELECT * FROM binary_files WHERE id = ?", id)
if err != nil {
return nil, err
}
return &model.BinaryFile{Id: sqlFile.Id, Name: sqlFile.Name, Data: sqlFile.Data}, nil
}

View File

@ -0,0 +1,47 @@
package infra_test
import (
"owl-blogs/app/repository"
"owl-blogs/infra"
"owl-blogs/test"
"testing"
"github.com/stretchr/testify/require"
)
func setupBinaryRepo() repository.BinaryRepository {
db := test.NewMockDb()
repo := infra.NewBinaryFileRepo(db)
return repo
}
func TestBinaryRepoCreate(t *testing.T) {
repo := setupBinaryRepo()
file, err := repo.Create("name", []byte("😀 😃 😄 😁"))
require.NoError(t, err)
file, err = repo.FindById(file.Id)
require.NoError(t, err)
require.Equal(t, file.Name, "name")
require.Equal(t, file.Data, []byte("😀 😃 😄 😁"))
}
func TestBinaryRepoNoSideEffect(t *testing.T) {
repo := setupBinaryRepo()
file, err := repo.Create("name1", []byte("111"))
require.NoError(t, err)
file2, err := repo.Create("name2", []byte("222"))
require.NoError(t, err)
file, err = repo.FindById(file.Id)
require.NoError(t, err)
file2, err = repo.FindById(file2.Id)
require.NoError(t, err)
require.Equal(t, file.Name, "name1")
require.Equal(t, file.Data, []byte("111"))
require.Equal(t, file2.Name, "name2")
require.Equal(t, file2.Data, []byte("222"))
}

View File

@ -131,3 +131,39 @@ func TestRepoUpdate(t *testing.T) {
require.Equal(t, meta.Number, meta2.Number) require.Equal(t, meta.Number, meta2.Number)
require.Equal(t, meta.Date.Unix(), meta2.Date.Unix()) require.Equal(t, meta.Date.Unix(), meta2.Date.Unix())
} }
func TestRepoNoSideEffect(t *testing.T) {
repo := setupRepo()
entry1 := &test.MockEntry{}
now1 := time.Now()
err := repo.Create(entry1, &now1, &test.MockEntryMetaData{
Str: "1",
Number: 1,
Date: now1,
})
require.NoError(t, err)
entry2 := &test.MockEntry{}
now2 := time.Now()
err = repo.Create(entry2, &now2, &test.MockEntryMetaData{
Str: "2",
Number: 2,
Date: now2,
})
require.NoError(t, err)
r1, err := repo.FindById(entry1.ID())
require.NoError(t, err)
r2, err := repo.FindById(entry2.ID())
require.NoError(t, err)
require.Equal(t, r1.MetaData().(*test.MockEntryMetaData).Str, "1")
require.Equal(t, r1.MetaData().(*test.MockEntryMetaData).Number, 1)
require.Equal(t, r1.MetaData().(*test.MockEntryMetaData).Date.Unix(), now1.Unix())
require.Equal(t, r2.MetaData().(*test.MockEntryMetaData).Str, "2")
require.Equal(t, r2.MetaData().(*test.MockEntryMetaData).Number, 2)
require.Equal(t, r2.MetaData().(*test.MockEntryMetaData).Date.Unix(), now2.Unix())
}

View File

@ -9,10 +9,11 @@ import (
type WebApp struct { type WebApp struct {
FiberApp *fiber.App FiberApp *fiber.App
EntryService *app.EntryService EntryService *app.EntryService
BinaryService *app.BinaryService
Registry *app.EntryTypeRegistry Registry *app.EntryTypeRegistry
} }
func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegistry) *WebApp { func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegistry, binService *app.BinaryService) *WebApp {
app := fiber.New() app := fiber.New()
indexHandler := NewIndexHandler(entryService) indexHandler := NewIndexHandler(entryService)
@ -51,7 +52,12 @@ func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegist
// app.Post("/auth/token/", userAuthTokenHandler(repo)) // app.Post("/auth/token/", userAuthTokenHandler(repo))
// app.Get("/.well-known/oauth-authorization-server", userAuthMetadataHandler(repo)) // app.Get("/.well-known/oauth-authorization-server", userAuthMetadataHandler(repo))
// app.NotFound = http.HandlerFunc(notFoundHandler(repo)) // app.NotFound = http.HandlerFunc(notFoundHandler(repo))
return &WebApp{FiberApp: app, EntryService: entryService, Registry: typeRegistry} return &WebApp{
FiberApp: app,
EntryService: entryService,
Registry: typeRegistry,
BinaryService: binService,
}
} }
func (w *WebApp) Run() { func (w *WebApp) Run() {