lens @ fbcac585cf626917e2baf1d0065c7b632341ba01

ref: Move auth functions to service
diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go
deleted file mode 100644
index ed122bb6b2631d882efac0f6191fe3c29e0dd050..0000000000000000000000000000000000000000
--- a/pkg/ext/auth.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package ext
-
-import (
-	"bytes"
-	"crypto/aes"
-	"crypto/cipher"
-	"crypto/rand"
-	"encoding/gob"
-	"errors"
-	"io"
-)
-
-type Token struct {
-	UserID   uint
-	Username string
-}
-
-func ReadToken(data []byte, key []byte) (*Token, error) {
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-
-	aesgcm, err := cipher.NewGCM(block)
-	if err != nil {
-		panic(err.Error())
-	}
-
-	nonceSize := aesgcm.NonceSize()
-	if len(data) < nonceSize {
-		return nil, errors.New("nonce size greater than data's size")
-	}
-
-	nonce, ciphertext := data[:nonceSize], data[nonceSize:]
-	plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
-	if err != nil {
-		return nil, err
-	}
-
-	r := bytes.NewReader(plaintext)
-	var token Token
-	dec := gob.NewDecoder(r)
-	if err = dec.Decode(&token); err != nil {
-		return nil, err
-	}
-	return &token, nil
-}
-
-func WriteToken(token *Token, key []byte) ([]byte, error) {
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-
-	aesgcm, err := cipher.NewGCM(block)
-	if err != nil {
-		return nil, err
-	}
-
-	var buffer bytes.Buffer
-	enc := gob.NewEncoder(&buffer)
-	if err := enc.Encode(token); err != nil {
-		return nil, err
-	}
-	nonce := make([]byte, aesgcm.NonceSize())
-	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
-		return nil, err
-	}
-
-	ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
-	return ciphertext, nil
-}
diff --git a/pkg/ext/auth_test.go b/pkg/ext/auth_test.go
deleted file mode 100644
index dc72a0cd66d92a1a07de9ee36a08120d954f6e60..0000000000000000000000000000000000000000
--- a/pkg/ext/auth_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-//go:build unit
-
-package ext
-
-import (
-	"testing"
-
-	"git.sr.ht/~gabrielgio/img/pkg/testkit"
-)
-
-func TestReadWriteToken(t *testing.T) {
-	t.Parallel()
-
-	testCases := []struct {
-		name  string
-		key   []byte
-		token *Token
-	}{
-		{
-			name: "Normal write",
-			key:  []byte("AES256Key-32Characters1234567890"),
-			token: &Token{
-				UserID:   3,
-				Username: "username",
-			},
-		},
-	}
-
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			data, err := WriteToken(tc.token, tc.key)
-			testkit.TestFatalError(t, "WriteToken", err)
-
-			token, err := ReadToken(data, tc.key)
-			testkit.TestFatalError(t, "ReadToken", err)
-
-			testkit.TestValue(t, "ReadWriteToken", token, tc.token)
-		})
-	}
-}
diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go
index 2dd1cca57f49e61df5123bdb61fa71dd6439d99d..bcc6c5feb3fa1e30f54afc64d96dfc2c6ad5ca2d 100644
--- a/pkg/ext/middleware.go
+++ b/pkg/ext/middleware.go
@@ -8,6 +8,7 @@ 	"github.com/sirupsen/logrus"
 	"github.com/valyala/fasthttp"
 
 	"git.sr.ht/~gabrielgio/img/pkg/database/repository"
+	"git.sr.ht/~gabrielgio/img/pkg/service"
 )
 
 func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler {
@@ -77,7 +78,7 @@ 			a.entry.Error(err)
 			return
 		}
 
-		token, err := ReadToken(auth, a.key)
+		token, err := service.ReadToken(auth, a.key)
 		if err != nil {
 			a.entry.Error(err)
 			ctx.Redirect(redirectLogin, 307)
@@ -92,9 +93,9 @@ 		next(ctx)
 	}
 }
 
-func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *Token {
+func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *service.Token {
 	tokenValue := ctx.UserValue("token")
-	if token, ok := tokenValue.(*Token); ok {
+	if token, ok := tokenValue.(*service.Token); ok {
 		return token
 	}
 	return nil
@@ -113,7 +114,7 @@
 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)
+		_, ok := ctx.UserValue("token").(*service.Token)
 		if ok {
 			next(ctx)
 			return
diff --git a/pkg/service/auth.go b/pkg/service/auth.go
index 761c70b4e0a416d0f556bb929318f1e1170f11c4..1966e702241f86248aeb5101a1d2463bfa280a01 100644
--- a/pkg/service/auth.go
+++ b/pkg/service/auth.go
@@ -1,12 +1,18 @@
 package service
 
 import (
+	"bytes"
 	"context"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"encoding/gob"
+	"errors"
+	"io"
 
 	"golang.org/x/crypto/bcrypt"
 
 	"git.sr.ht/~gabrielgio/img/pkg/database/repository"
-	"git.sr.ht/~gabrielgio/img/pkg/ext"
 )
 
 type AuthController struct {
@@ -42,11 +48,11 @@ 	if err := bcrypt.CompareHashAndPassword(hashedPassword, password); err != nil {
 		return nil, err
 	}
 
-	token := &ext.Token{
+	token := &Token{
 		UserID:   id,
 		Username: string(username),
 	}
-	return ext.WriteToken(token, c.key)
+	return WriteToken(token, c.key)
 }
 
 // InitialRegister register a initial user, it will validate if there is another
@@ -75,3 +81,64 @@ 	})
 
 	return err
 }
+
+type Token struct {
+	UserID   uint
+	Username string
+}
+
+func ReadToken(data []byte, key []byte) (*Token, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	aesgcm, err := cipher.NewGCM(block)
+	if err != nil {
+		panic(err.Error())
+	}
+
+	nonceSize := aesgcm.NonceSize()
+	if len(data) < nonceSize {
+		return nil, errors.New("nonce size greater than data's size")
+	}
+
+	nonce, ciphertext := data[:nonceSize], data[nonceSize:]
+	plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	r := bytes.NewReader(plaintext)
+	var token Token
+	dec := gob.NewDecoder(r)
+	if err = dec.Decode(&token); err != nil {
+		return nil, err
+	}
+	return &token, nil
+}
+
+func WriteToken(token *Token, key []byte) ([]byte, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	aesgcm, err := cipher.NewGCM(block)
+	if err != nil {
+		return nil, err
+	}
+
+	var buffer bytes.Buffer
+	enc := gob.NewEncoder(&buffer)
+	if err := enc.Encode(token); err != nil {
+		return nil, err
+	}
+	nonce := make([]byte, aesgcm.NonceSize())
+	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
+		return nil, err
+	}
+
+	ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
+	return ciphertext, nil
+}
diff --git a/pkg/service/auth_test.go b/pkg/service/auth_test.go
index 35b247575a785ddb5db5c0df0b810c2b6ec08fd8..7083d0c90ea75569f4e2532f86228a57c49df253 100644
--- a/pkg/service/auth_test.go
+++ b/pkg/service/auth_test.go
@@ -64,7 +64,7 @@
 			auth, err := scene.controller.Login(scene.ctx, []byte(tc.username), tc.password)
 			testkit.TestFatalError(t, "Login", err)
 
-			token, err := ext.ReadToken(auth, key)
+			token, err := ReadToken(auth, key)
 			testkit.TestFatalError(t, "Login", err)
 
 			testkit.TestValue(t, "Login", tc.username, token.Username)
@@ -76,3 +76,34 @@
 func remove[T any](slice []T, s int) []T {
 	return append(slice[:s], slice[s+1:]...)
 }
+
+func TestReadWriteToken(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		name  string
+		key   []byte
+		token *Token
+	}{
+		{
+			name: "Normal write",
+			key:  []byte("AES256Key-32Characters1234567890"),
+			token: &Token{
+				UserID:   3,
+				Username: "username",
+			},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			data, err := WriteToken(tc.token, tc.key)
+			testkit.TestFatalError(t, "WriteToken", err)
+
+			token, err := ReadToken(data, tc.key)
+			testkit.TestFatalError(t, "ReadToken", err)
+
+			testkit.TestValue(t, "ReadWriteToken", token, tc.token)
+		})
+	}
+}