aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorGabriel Arakaki Giovanini <mail@gabrielgio.me>2023-06-26 22:26:10 +0200
committerGabriel Arakaki Giovanini <mail@gabrielgio.me>2023-06-26 22:40:16 +0200
commit4d930c0c8cb585979798fac2bb254f991faa62fb (patch)
tree0c33e0e0f2a2f47b0f64843f7d9a3eb299abb260 /pkg
parentd4e1ca3a48e74573df6965ceee217e119ff899ae (diff)
downloadlens-4d930c0c8cb585979798fac2bb254f991faa62fb.tar.gz
lens-4d930c0c8cb585979798fac2bb254f991faa62fb.tar.bz2
lens-4d930c0c8cb585979798fac2bb254f991faa62fb.zip
feat: Add initial user setup
Diffstat (limited to 'pkg')
-rw-r--r--pkg/components/auth/controller.go44
-rw-r--r--pkg/components/auth/controller_test.go19
-rw-r--r--pkg/components/errors.go8
-rw-r--r--pkg/components/media/model.go5
-rw-r--r--pkg/components/user/model.go3
-rw-r--r--pkg/database/sql/user.go15
-rw-r--r--pkg/database/sql/user_test.go20
-rw-r--r--pkg/ext/middleware.go42
-rw-r--r--pkg/view/auth.go21
9 files changed, 151 insertions, 26 deletions
diff --git a/pkg/components/auth/controller.go b/pkg/components/auth/controller.go
index a81a1c0..2f30fb5 100644
--- a/pkg/components/auth/controller.go
+++ b/pkg/components/auth/controller.go
@@ -5,18 +5,26 @@ 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/ext"
)
type Controller struct {
- repository Repository
- key []byte
+ repository Repository
+ userRepository user.Repository
+ key []byte
}
-func NewController(repository Repository, key []byte) *Controller {
+func NewController(
+ repository Repository,
+ userRepository user.Repository,
+ key []byte,
+) *Controller {
return &Controller{
- repository: repository,
- key: key,
+ repository: repository,
+ userRepository: userRepository,
+ key: key,
}
}
@@ -41,3 +49,29 @@ func (c *Controller) Login(ctx context.Context, username, password []byte) ([]by
}
return ext.WriteToken(token, c.key)
}
+
+// InitialRegister register a initial user, it will validate if there is another
+// user stored already. If so an error `InvlidaInput` will be returned
+func (c *Controller) InitialRegister(ctx context.Context, username, password []byte, path []byte) error {
+ exist, err := c.userRepository.Any(ctx)
+ if err != nil {
+ return err
+ }
+
+ if exist {
+ return components.InvlidaInput
+ }
+
+ hash, err := bcrypt.GenerateFromPassword(password, bcrypt.MinCost)
+ if err != nil {
+ return err
+ }
+
+ err = c.userRepository.Create(ctx, &user.CreateUser{
+ Username: string(username),
+ Password: hash,
+ Path: string(path),
+ })
+
+ return err
+}
diff --git a/pkg/components/auth/controller_test.go b/pkg/components/auth/controller_test.go
index 33aa901..6b4e3cd 100644
--- a/pkg/components/auth/controller_test.go
+++ b/pkg/components/auth/controller_test.go
@@ -9,6 +9,7 @@ import (
"github.com/samber/lo"
+ "git.sr.ht/~gabrielgio/img/pkg/components/user"
"git.sr.ht/~gabrielgio/img/pkg/ext"
"git.sr.ht/~gabrielgio/img/pkg/testkit"
)
@@ -43,11 +44,11 @@ func setUp() *scene {
return &scene{
ctx: context.Background(),
mockRepository: mockUserRepository,
- controller: *NewController(mockUserRepository, key),
+ controller: *NewController(mockUserRepository, nil, key),
}
}
-func TestRegisterAndLogin(t *testing.T) {
+func TestInitialRegisterAndLogin(t *testing.T) {
testCases := []struct {
name string
username string
@@ -64,7 +65,7 @@ func TestRegisterAndLogin(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
scene := setUp()
- err := scene.controller.Register(scene.ctx, []byte(tc.username), tc.password)
+ err := scene.controller.InitialRegister(scene.ctx, []byte(tc.username), tc.password, []byte("/"))
testkit.TestFatalError(t, "Register", err)
userID := scene.mockRepository.GetLastId()
@@ -85,8 +86,8 @@ func TestRegisterAndLogin(t *testing.T) {
}
}
-func toUser(m *mockUser, _ int) *User {
- return &User{
+func toUser(m *mockUser, _ int) *user.User {
+ return &user.User{
ID: m.id,
Username: m.username,
}
@@ -96,7 +97,7 @@ func (m *MockUserRepository) GetLastId() uint {
return m.index
}
-func (m *MockUserRepository) List(ctx context.Context) ([]*User, error) {
+func (m *MockUserRepository) List(ctx context.Context) ([]*user.User, error) {
if m.err != nil {
return nil, m.err
}
@@ -104,7 +105,7 @@ func (m *MockUserRepository) List(ctx context.Context) ([]*User, error) {
return lo.Map(m.users, toUser), nil
}
-func (m *MockUserRepository) Get(ctx context.Context, id uint) (*User, error) {
+func (m *MockUserRepository) Get(ctx context.Context, id uint) (*user.User, error) {
if m.err != nil {
return nil, m.err
}
@@ -143,7 +144,7 @@ func (m *MockUserRepository) GetPassword(ctx context.Context, id uint) ([]byte,
return nil, errors.New("Item not found")
}
-func (m *MockUserRepository) Create(ctx context.Context, createUser *CreateUser) (uint, error) {
+func (m *MockUserRepository) Create(ctx context.Context, createUser *user.CreateUser) (uint, error) {
if m.err != nil {
return 0, m.err
}
@@ -159,7 +160,7 @@ func (m *MockUserRepository) Create(ctx context.Context, createUser *CreateUser)
return m.index, nil
}
-func (m *MockUserRepository) Update(ctx context.Context, id uint, update *UpdateUser) error {
+func (m *MockUserRepository) Update(ctx context.Context, id uint, update *user.UpdateUser) error {
if m.err != nil {
return m.err
}
diff --git a/pkg/components/errors.go b/pkg/components/errors.go
new file mode 100644
index 0000000..aedbe88
--- /dev/null
+++ b/pkg/components/errors.go
@@ -0,0 +1,8 @@
+package components
+
+import "errors"
+
+var (
+ NotFound = errors.New("Not found")
+ InvlidaInput = errors.New("Invalid Input")
+)
diff --git a/pkg/components/media/model.go b/pkg/components/media/model.go
index 0e17e92..1962a23 100644
--- a/pkg/components/media/model.go
+++ b/pkg/components/media/model.go
@@ -2,6 +2,7 @@ package media
import (
"context"
+ "strings"
"time"
)
@@ -57,3 +58,7 @@ type (
CreateEXIF(context.Context, uint, *MediaEXIF) error
}
)
+
+func (m *Media) IsVideo() bool {
+ return strings.HasPrefix(m.MIMEType, "video")
+}
diff --git a/pkg/components/user/model.go b/pkg/components/user/model.go
index f957c39..ce1b3a5 100644
--- a/pkg/components/user/model.go
+++ b/pkg/components/user/model.go
@@ -20,7 +20,7 @@ type (
CreateUser struct {
Username string
Name string
- Password string
+ Password []byte
IsAdmin bool
Path string
}
@@ -29,5 +29,6 @@ type (
List(ctx context.Context) ([]*User, error)
Create(ctx context.Context, createUser *CreateUser) error
Update(ctx context.Context, id uint, updateUser *UpdateUser) error
+ Any(ctx context.Context) (bool, error)
}
)
diff --git a/pkg/database/sql/user.go b/pkg/database/sql/user.go
index 2d74162..a02b67b 100644
--- a/pkg/database/sql/user.go
+++ b/pkg/database/sql/user.go
@@ -187,3 +187,18 @@ func (self *UserRepository) Delete(ctx context.Context, id uint) error {
}
return nil
}
+
+func (u *UserRepository) Any(ctx context.Context) (bool, error) {
+ var exists bool
+ result := u.db.
+ WithContext(ctx).
+ Model(&User{}).
+ Select("count(id) > 0").
+ Find(&exists)
+
+ if result.Error != nil {
+ return false, result.Error
+ }
+
+ return exists, nil
+}
diff --git a/pkg/database/sql/user_test.go b/pkg/database/sql/user_test.go
index 875b8e6..473ce03 100644
--- a/pkg/database/sql/user_test.go
+++ b/pkg/database/sql/user_test.go
@@ -12,7 +12,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/logger"
- "git.sr.ht/~gabrielgio/img/pkg/components/auth"
+ "git.sr.ht/~gabrielgio/img/pkg/components/user"
)
func setup(t *testing.T) (*gorm.DB, func()) {
@@ -48,7 +48,7 @@ func TestCreate(t *testing.T) {
repository := NewUserRepository(db)
- id, err := repository.Create(context.Background(), &auth.CreateUser{
+ err := repository.Create(context.Background(), &user.CreateUser{
Username: "new_username",
Name: "new_name",
})
@@ -56,12 +56,12 @@ func TestCreate(t *testing.T) {
t.Fatalf("Error creating: %s", err.Error())
}
- got, err := repository.Get(context.Background(), id)
+ got, err := repository.Get(context.Background(), 1)
if err != nil {
t.Fatalf("Error getting: %s", err.Error())
}
- want := &auth.User{
- ID: id,
+ want := &user.User{
+ ID: 1,
Username: "new_username",
Name: "new_name",
}
@@ -78,7 +78,7 @@ func TestUpdate(t *testing.T) {
repository := NewUserRepository(db)
- id, err := repository.Create(context.Background(), &auth.CreateUser{
+ err := repository.Create(context.Background(), &user.CreateUser{
Username: "username",
Name: "name",
})
@@ -86,7 +86,7 @@ func TestUpdate(t *testing.T) {
t.Fatalf("Error creating user: %s", err.Error())
}
- err = repository.Update(context.Background(), id, &auth.UpdateUser{
+ err = repository.Update(context.Background(), 1, &user.UpdateUser{
Username: "new_username",
Name: "new_name",
})
@@ -94,12 +94,12 @@ func TestUpdate(t *testing.T) {
t.Fatalf("Error update user: %s", err.Error())
}
- got, err := repository.Get(context.Background(), id)
+ got, err := repository.Get(context.Background(), 1)
if err != nil {
t.Fatalf("Error getting user: %s", err.Error())
}
- want := &auth.User{
- ID: id,
+ want := &user.User{
+ ID: 1,
Username: "new_username",
Name: "new_name",
}
diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go
index 771c0ac..649272e 100644
--- a/pkg/ext/middleware.go
+++ b/pkg/ext/middleware.go
@@ -4,6 +4,7 @@ import (
"encoding/base64"
"time"
+ "git.sr.ht/~gabrielgio/img/pkg/components/user"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
)
@@ -54,7 +55,7 @@ func NewAuthMiddleware(key []byte, log *logrus.Entry) *AuthMiddleware {
func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
path := string(ctx.Path())
- if path == "/login" {
+ if path == "/login" || path == "/initial" {
next(ctx)
return
}
@@ -87,3 +88,42 @@ func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.Request
next(ctx)
}
}
+
+type InitialSetupMiddleware struct {
+ userRepository user.Repository
+}
+
+func NewInitialSetupMiddleware(userRepository user.Repository) *InitialSetupMiddleware {
+ return &InitialSetupMiddleware{
+ userRepository: userRepository,
+ }
+}
+
+func (i *InitialSetupMiddleware) Check(next fasthttp.RequestHandler) fasthttp.RequestHandler {
+ return func(ctx *fasthttp.RequestCtx) {
+ // if user has been set to context it is logged in already
+ _, ok := ctx.UserValue("token").(*Token)
+ if ok {
+ next(ctx)
+ return
+ }
+
+ path := string(ctx.Path())
+ if path == "/initial" {
+ next(ctx)
+ return
+ }
+
+ exists, err := i.userRepository.Any(ctx)
+ if err != nil {
+ InternalServerError(ctx, err)
+ return
+ }
+
+ if exists {
+ next(ctx)
+ return
+ }
+ ctx.Redirect("/initial", 307)
+ }
+}
diff --git a/pkg/view/auth.go b/pkg/view/auth.go
index d44424d..3f9e414 100644
--- a/pkg/view/auth.go
+++ b/pkg/view/auth.go
@@ -68,10 +68,31 @@ func Index(ctx *fasthttp.RequestCtx) {
ctx.Redirect("/login", 307)
}
+func (v *AuthView) InitialRegisterView(ctx *fasthttp.RequestCtx) error {
+ return img.Render[interface{}](ctx, "register.html", nil)
+}
+
+func (v *AuthView) InitialRegister(ctx *fasthttp.RequestCtx) error {
+ username := ctx.FormValue("username")
+ password := ctx.FormValue("password")
+ path := ctx.FormValue("path")
+
+ err := v.userController.InitialRegister(ctx, username, password, path)
+ if err != nil {
+ return err
+ }
+
+ ctx.Redirect("/login", 307)
+ return nil
+}
+
func (v *AuthView) SetMyselfIn(r *ext.Router) {
r.GET("/login", v.LoginView)
r.POST("/login", v.Login)
r.GET("/logout", v.Logout)
r.POST("/logout", v.Logout)
+
+ r.GET("/initial", v.InitialRegisterView)
+ r.POST("/initial", v.InitialRegister)
}