diff options
-rw-r--r-- | pkg/components/auth/controller.go | 18 | ||||
-rw-r--r-- | pkg/components/auth/controller_test.go | 162 | ||||
-rw-r--r-- | pkg/components/auth/mock_test.go | 121 | ||||
-rw-r--r-- | pkg/database/repository/auth.go (renamed from pkg/components/auth/model.go) | 4 | ||||
-rw-r--r-- | pkg/database/repository/user.go (renamed from pkg/components/user/model.go) | 7 | ||||
-rw-r--r-- | pkg/database/sql/user.go | 23 | ||||
-rw-r--r-- | pkg/ext/middleware.go | 6 | ||||
-rw-r--r-- | pkg/testkit/testkit.go | 3 | ||||
-rw-r--r-- | pkg/view/media.go | 2 | ||||
-rw-r--r-- | pkg/view/settings.go | 8 |
10 files changed, 171 insertions, 183 deletions
diff --git a/pkg/components/auth/controller.go b/pkg/components/auth/controller.go index a33d9b3..0b08fcc 100644 --- a/pkg/components/auth/controller.go +++ b/pkg/components/auth/controller.go @@ -6,35 +6,35 @@ import ( "golang.org/x/crypto/bcrypt" "git.sr.ht/~gabrielgio/img/pkg/components" - "git.sr.ht/~gabrielgio/img/pkg/components/user" + "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/ext" ) type Controller struct { - repository Repository - userRepository user.Repository + authRepository repository.AuthRepository + userRepository repository.UserRepository key []byte } func NewController( - repository Repository, - userRepository user.Repository, + authRepository repository.AuthRepository, + userRepository repository.UserRepository, key []byte, ) *Controller { return &Controller{ - repository: repository, + authRepository: authRepository, userRepository: userRepository, key: key, } } func (c *Controller) Login(ctx context.Context, username, password []byte) ([]byte, error) { - id, err := c.repository.GetIDByUsername(ctx, string(username)) + id, err := c.authRepository.GetIDByUsername(ctx, string(username)) if err != nil { return nil, err } - hashedPassword, err := c.repository.GetPassword(ctx, id) + hashedPassword, err := c.authRepository.GetPassword(ctx, id) if err != nil { return nil, err } @@ -67,7 +67,7 @@ func (c *Controller) InitialRegister(ctx context.Context, username, password []b return err } - _, err = c.userRepository.Create(ctx, &user.CreateUser{ + _, err = c.userRepository.Create(ctx, &repository.CreateUser{ Username: string(username), Password: hash, Path: string(path), diff --git a/pkg/components/auth/controller_test.go b/pkg/components/auth/controller_test.go index 50bf69b..b1ca065 100644 --- a/pkg/components/auth/controller_test.go +++ b/pkg/components/auth/controller_test.go @@ -4,12 +4,9 @@ package auth import ( "context" - "errors" "testing" - "github.com/samber/lo" - - "git.sr.ht/~gabrielgio/img/pkg/components/user" + "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/ext" "git.sr.ht/~gabrielgio/img/pkg/testkit" ) @@ -17,41 +14,23 @@ import ( type ( scene struct { ctx context.Context - mockRepository *MockAuthRepository - controller Controller - } - - mockUser struct { - id uint - username string - password []byte - } - - MockAuthRepository struct { - index uint - users []*mockUser - err error - } - - MockUserRepository struct { - index uint - users []*mockUser - err error + authRepository repository.AuthRepository + userRepository repository.UserRepository + controller *Controller } ) var ( - _ Repository = &MockAuthRepository{} - key = []byte("6368616e676520746869732070617373") + key = []byte("6368616e676520746869732070617373") ) func setUp() *scene { - mockAuthRepository := &MockAuthRepository{} - mockUserRepository := &MockUserRepository{} + userRepository := NewUserRepository() return &scene{ ctx: context.Background(), - mockRepository: mockAuthRepository, - controller: *NewController(mockAuthRepository, mockUserRepository, key), + authRepository: userRepository, + userRepository: userRepository, + controller: NewController(userRepository, userRepository, key), } } @@ -64,7 +43,7 @@ func TestInitialRegisterAndLogin(t *testing.T) { { name: "Normal register", username: "username", - password: []byte("password"), + password: []byte("this is an password"), }, } @@ -75,9 +54,10 @@ func TestInitialRegisterAndLogin(t *testing.T) { err := scene.controller.InitialRegister(scene.ctx, []byte(tc.username), tc.password, []byte("/")) testkit.TestFatalError(t, "Register", err) - userID := scene.mockRepository.GetLastId() + users, err := scene.userRepository.List(scene.ctx) + userID := users[0].ID - user, err := scene.mockRepository.Get(scene.ctx, userID) + user, err := scene.userRepository.Get(scene.ctx, userID) testkit.TestFatalError(t, "Get", err) testkit.TestValue(t, "Register", tc.username, user.Username) @@ -93,122 +73,6 @@ func TestInitialRegisterAndLogin(t *testing.T) { } } -func toUser(m *mockUser, _ int) *user.User { - return &user.User{ - ID: m.id, - Username: m.username, - } -} - -func (m *MockAuthRepository) GetLastId() uint { - return m.index -} - -func (m *MockAuthRepository) List(ctx context.Context) ([]*user.User, error) { - if m.err != nil { - return nil, m.err - } - - return lo.Map(m.users, toUser), nil -} - -func (m *MockAuthRepository) Get(ctx context.Context, id uint) (*user.User, error) { - if m.err != nil { - return nil, m.err - } - - for _, m := range m.users { - if m.id == id { - return toUser(m, 0), nil - } - } - return nil, errors.New("Item not found") -} - -func (m *MockAuthRepository) GetIDByUsername(ctx context.Context, username string) (uint, error) { - if m.err != nil { - return 0, m.err - } - - for _, m := range m.users { - if m.username == username { - return m.id, nil - } - } - return 0, errors.New("Item not found") -} - -func (m *MockAuthRepository) GetPassword(ctx context.Context, id uint) ([]byte, error) { - if m.err != nil { - return nil, m.err - } - - for _, m := range m.users { - if m.id == id { - return m.password, nil - } - } - return nil, errors.New("Item not found") -} - -func (m *MockAuthRepository) Create(ctx context.Context, createUser *user.CreateUser) (uint, error) { - if m.err != nil { - return 0, m.err - } - - m.index++ - - m.users = append(m.users, &mockUser{ - id: m.index, - username: createUser.Username, - password: createUser.Password, - }) - - return m.index, nil -} - -func (m *MockAuthRepository) Update(ctx context.Context, id uint, update *user.UpdateUser) error { - if m.err != nil { - return m.err - } - - for _, m := range m.users { - if m.id == id { - m.username = update.Username - } - } - return nil -} - func remove[T any](slice []T, s int) []T { return append(slice[:s], slice[s+1:]...) } - -func (r *MockAuthRepository) Delete(ctx context.Context, id uint) error { - if r.err != nil { - return r.err - } - - for i, m := range r.users { - if m.id == id { - r.users = remove(r.users, i) - } - } - return nil -} - -func (m *MockUserRepository) List(ctx context.Context) ([]*user.User, error) { - panic("not implemented") // TODO: Implement -} - -func (m *MockUserRepository) Create(ctx context.Context, createUser *user.CreateUser) (uint, error) { - panic("not implemented") // TODO: Implement -} - -func (m *MockUserRepository) Update(ctx context.Context, id uint, updateUser *user.UpdateUser) error { - panic("not implemented") // TODO: Implement -} - -func (m *MockUserRepository) Any(ctx context.Context) (bool, error) { - panic("not implemented") // TODO: Implement -} diff --git a/pkg/components/auth/mock_test.go b/pkg/components/auth/mock_test.go new file mode 100644 index 0000000..885f643 --- /dev/null +++ b/pkg/components/auth/mock_test.go @@ -0,0 +1,121 @@ +//go:build unit + +package auth + +import ( + "context" + "errors" + + "git.sr.ht/~gabrielgio/img/pkg/database/repository" +) + +type ( + User struct { + ID uint + Username string + Name string + Password []byte + IsAdmin bool + Path string + } + + Users map[uint]*User + + UserRepository struct { + icount uint + users Users + } +) + +var _ repository.UserRepository = &UserRepository{} +var _ repository.AuthRepository = &UserRepository{} + +func NewUserRepository() *UserRepository { + return &UserRepository{ + users: make(map[uint]*User), + } +} + +func (u *User) ToModel() *repository.User { + return &repository.User{ + ID: u.ID, + Username: u.Username, + Name: u.Name, + IsAdmin: u.IsAdmin, + Path: u.Path, + } +} + +func (u Users) ToModels() []*repository.User { + users := make([]*repository.User, 0, len(u)) + for _, i := range u { + users = append(users, i.ToModel()) + } + return users +} + +func (u *UserRepository) Get(ctx context.Context, id uint) (*repository.User, error) { + if user, ok := u.users[id]; ok { + return user.ToModel(), nil + } + + return nil, errors.New("Not Found") +} + +func (u *UserRepository) List(_ context.Context) ([]*repository.User, error) { + return u.users.ToModels(), nil +} + +func (u *UserRepository) Create(_ context.Context, createUser *repository.CreateUser) (uint, error) { + id := u.furtherID() + u.users[id] = &User{ + ID: id, + Name: createUser.Name, + Username: createUser.Username, + Path: createUser.Path, + Password: createUser.Password, + } + return id, nil +} + +func (u *UserRepository) Update(_ context.Context, id uint, updateUser *repository.UpdateUser) error { + user, ok := u.users[id] + if !ok { + return errors.New("Invalid ID") + } + + user.Name = updateUser.Name + user.Username = updateUser.Username + if updateUser.Password != "" { + user.Password = []byte(updateUser.Password) + } + + return nil +} + +func (u *UserRepository) Any(_ context.Context) (bool, error) { + return len(u.users) > 0, nil +} + +func (u *UserRepository) GetIDByUsername(ctx context.Context, username string) (uint, error) { + for id, u := range u.users { + if u.Username == username { + return id, nil + } + } + + return 0, errors.New("Not Found") +} + +func (u *UserRepository) GetPassword(ctx context.Context, id uint) ([]byte, error) { + if user, ok := u.users[id]; ok { + return []byte(user.Password), nil + } + + return nil, errors.New("Not Found") +} + +func (u *UserRepository) furtherID() uint { + u.icount++ + return u.icount +} diff --git a/pkg/components/auth/model.go b/pkg/database/repository/auth.go index dd6ce50..b319495 100644 --- a/pkg/components/auth/model.go +++ b/pkg/database/repository/auth.go @@ -1,9 +1,9 @@ -package auth +package repository import "context" type ( - Repository interface { + AuthRepository interface { GetIDByUsername(ctx context.Context, username string) (uint, error) GetPassword(ctx context.Context, id uint) ([]byte, error) } diff --git a/pkg/components/user/model.go b/pkg/database/repository/user.go index 0ff6d0a..f8bd719 100644 --- a/pkg/components/user/model.go +++ b/pkg/database/repository/user.go @@ -1,4 +1,4 @@ -package user +package repository import "context" @@ -14,7 +14,7 @@ type ( UpdateUser struct { Username string Name string - Password *string + Password string } CreateUser struct { @@ -25,7 +25,8 @@ type ( Path string } - Repository interface { + UserRepository interface { + Get(ctx context.Context, id uint) (*User, error) List(ctx context.Context) ([]*User, error) Create(ctx context.Context, createUser *CreateUser) (uint, error) Update(ctx context.Context, id uint, updateUser *UpdateUser) error diff --git a/pkg/database/sql/user.go b/pkg/database/sql/user.go index a0884f4..479a9c5 100644 --- a/pkg/database/sql/user.go +++ b/pkg/database/sql/user.go @@ -6,8 +6,7 @@ import ( "golang.org/x/crypto/bcrypt" "gorm.io/gorm" - "git.sr.ht/~gabrielgio/img/pkg/components/auth" - "git.sr.ht/~gabrielgio/img/pkg/components/user" + "git.sr.ht/~gabrielgio/img/pkg/database/repository" ) type ( @@ -27,8 +26,8 @@ type ( } ) -var _ auth.Repository = &UserRepository{} -var _ user.Repository = &UserRepository{} +var _ repository.UserRepository = &UserRepository{} +var _ repository.AuthRepository = &UserRepository{} func NewUserRepository(db *gorm.DB) *UserRepository { return &UserRepository{ @@ -36,8 +35,8 @@ func NewUserRepository(db *gorm.DB) *UserRepository { } } -func (self *User) ToModel() *user.User { - return &user.User{ +func (self *User) ToModel() *repository.User { + return &repository.User{ ID: self.Model.ID, Name: self.Name, Username: self.Username, @@ -46,7 +45,7 @@ func (self *User) ToModel() *user.User { } } -func (self Users) ToModel() (users []*user.User) { +func (self Users) ToModel() (users []*repository.User) { for _, user := range self { users = append(users, user.ToModel()) } @@ -75,7 +74,7 @@ func (self *UserRepository) EnsureAdmin(ctx context.Context) { } } -func (self *UserRepository) List(ctx context.Context) ([]*user.User, error) { +func (self *UserRepository) List(ctx context.Context) ([]*repository.User, error) { users := Users{} result := self.db. WithContext(ctx). @@ -88,8 +87,8 @@ func (self *UserRepository) List(ctx context.Context) ([]*user.User, error) { return users.ToModel(), nil } -func (self *UserRepository) Get(ctx context.Context, id uint) (*user.User, error) { - var user = &user.User{ID: id} +func (self *UserRepository) Get(ctx context.Context, id uint) (*repository.User, error) { + var user = &repository.User{ID: id} result := self.db. WithContext(ctx). First(user) @@ -137,7 +136,7 @@ func (self *UserRepository) GetPassword(ctx context.Context, id uint) ([]byte, e return userPassword.Password, nil } -func (self *UserRepository) Create(ctx context.Context, createUser *user.CreateUser) (uint, error) { +func (self *UserRepository) Create(ctx context.Context, createUser *repository.CreateUser) (uint, error) { user := &User{ Username: createUser.Username, Name: createUser.Name, @@ -154,7 +153,7 @@ func (self *UserRepository) Create(ctx context.Context, createUser *user.CreateU return user.Model.ID, nil } -func (self *UserRepository) Update(ctx context.Context, id uint, update *user.UpdateUser) error { +func (self *UserRepository) Update(ctx context.Context, id uint, update *repository.UpdateUser) error { user := &User{ Model: gorm.Model{ ID: id, diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go index bc23b90..d255c6d 100644 --- a/pkg/ext/middleware.go +++ b/pkg/ext/middleware.go @@ -7,7 +7,7 @@ import ( "github.com/sirupsen/logrus" "github.com/valyala/fasthttp" - "git.sr.ht/~gabrielgio/img/pkg/components/user" + "git.sr.ht/~gabrielgio/img/pkg/database/repository" ) func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler { @@ -91,10 +91,10 @@ func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.Request } type InitialSetupMiddleware struct { - userRepository user.Repository + userRepository repository.UserRepository } -func NewInitialSetupMiddleware(userRepository user.Repository) *InitialSetupMiddleware { +func NewInitialSetupMiddleware(userRepository repository.UserRepository) *InitialSetupMiddleware { return &InitialSetupMiddleware{ userRepository: userRepository, } diff --git a/pkg/testkit/testkit.go b/pkg/testkit/testkit.go index 526e1b3..3cc4afd 100644 --- a/pkg/testkit/testkit.go +++ b/pkg/testkit/testkit.go @@ -9,18 +9,21 @@ import ( ) func TestValue[T any](t *testing.T, method string, want, got T) { + t.Helper() if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%s() mismatch (-want +got):\n%s", method, diff) } } func TestFatalError(t *testing.T, method string, err error) { + t.Helper() if err != nil { t.Fatalf("%s() fatal error : %+v", method, err) } } func TestError(t *testing.T, method string, want, got error) { + t.Helper() if !equalError(want, got) { t.Errorf("%s() err mismatch want: %+v got %+v", method, want, got) } diff --git a/pkg/view/media.go b/pkg/view/media.go index 22f950d..66e3020 100644 --- a/pkg/view/media.go +++ b/pkg/view/media.go @@ -89,7 +89,7 @@ func (self *MediaView) GetImage(ctx *fasthttp.RequestCtx) error { } ctx.Response.Header.SetContentType(media.MIMEType) - ctx.SendFile(media.Path) + fasthttp.ServeFileUncompressed(ctx, media.Path) return nil } diff --git a/pkg/view/settings.go b/pkg/view/settings.go index e5acb1b..954cc98 100644 --- a/pkg/view/settings.go +++ b/pkg/view/settings.go @@ -5,7 +5,7 @@ import ( "git.sr.ht/~gabrielgio/img" "git.sr.ht/~gabrielgio/img/pkg/components/settings" - "git.sr.ht/~gabrielgio/img/pkg/components/user" + "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/ext" ) @@ -13,18 +13,18 @@ type ( SettingsView struct { // there is not need to create a controller for this settingsRepository settings.Repository - userRepository user.Repository + userRepository repository.UserRepository } SettingsPage struct { Settings *settings.Settings - Users []*user.User + Users []*repository.User } ) func NewSettingsView( settingsRespository settings.Repository, - userRepository user.Repository, + userRepository repository.UserRepository, ) *SettingsView { return &SettingsView{ settingsRepository: settingsRespository, |