Create users package
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Torjus Håkestad 2022-01-20 03:35:55 +01:00
parent c6b282fbcc
commit d4b7702bad
12 changed files with 55 additions and 40 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"git.t-juice.club/torjus/gpaste/users"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -17,11 +18,11 @@ const (
) )
type AuthService struct { type AuthService struct {
users UserStore users users.UserStore
hmacSecret []byte hmacSecret []byte
} }
func NewAuthService(store UserStore, signingSecret []byte) *AuthService { func NewAuthService(store users.UserStore, signingSecret []byte) *AuthService {
return &AuthService{users: store, hmacSecret: signingSecret} return &AuthService{users: store, hmacSecret: signingSecret}
} }

View File

@ -1,21 +1,23 @@
package gpaste_test package gpaste_test
import ( import (
"math/rand"
"testing" "testing"
"git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste"
"git.t-juice.club/torjus/gpaste/users"
) )
func TestAuth(t *testing.T) { func TestAuth(t *testing.T) {
t.Run("Token", func(t *testing.T) { t.Run("Token", func(t *testing.T) {
us := gpaste.NewMemoryUserStore() us := users.NewMemoryUserStore()
secret := []byte(randomString(16)) secret := []byte(randomString(16))
as := gpaste.NewAuthService(us, secret) as := gpaste.NewAuthService(us, secret)
username := randomString(8) username := randomString(8)
password := randomString(16) password := randomString(16)
user := &gpaste.User{Username: username} user := &users.User{Username: username}
if err := user.SetPassword(password); err != nil { if err := user.SetPassword(password); err != nil {
t.Fatalf("error setting user password: %s", err) t.Fatalf("error setting user password: %s", err)
} }
@ -37,3 +39,13 @@ func TestAuth(t *testing.T) {
} }
}) })
} }
func randomString(length int) string {
const charset = "abcdefghijklmnopqrstabcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, length)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
return string(b)
}

View File

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"strings" "strings"
"git.t-juice.club/torjus/gpaste/users"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"github.com/google/uuid" "github.com/google/uuid"
@ -14,7 +15,7 @@ import (
type HTTPServer struct { type HTTPServer struct {
Files FileStore Files FileStore
Users UserStore Users users.UserStore
Auth *AuthService Auth *AuthService
config *ServerConfig config *ServerConfig
Logger *zap.SugaredLogger Logger *zap.SugaredLogger
@ -29,12 +30,12 @@ func NewHTTPServer(cfg *ServerConfig) *HTTPServer {
AccessLogger: zap.NewNop().Sugar(), AccessLogger: zap.NewNop().Sugar(),
} }
srv.Files = NewMemoryFileStore() srv.Files = NewMemoryFileStore()
srv.Users = NewMemoryUserStore() srv.Users = users.NewMemoryUserStore()
srv.Auth = NewAuthService(srv.Users, []byte(srv.config.SigningSecret)) srv.Auth = NewAuthService(srv.Users, []byte(srv.config.SigningSecret))
// Create initial user // Create initial user
// TODO: Do properly // TODO: Do properly
user := &User{Username: "admin"} user := &users.User{Username: "admin"}
user.SetPassword("admin") user.SetPassword("admin")
srv.Users.Store(user) srv.Users.Store(user)
@ -214,7 +215,7 @@ func (s *HTTPServer) HandlerAPIUserCreate(w http.ResponseWriter, r *http.Request
} }
// TODO: Ensure user does not already exist // TODO: Ensure user does not already exist
user := &User{Username: req.Username} user := &users.User{Username: req.Username}
if err := user.SetPassword(req.Password); err != nil { if err := user.SetPassword(req.Password); err != nil {
s.Logger.Warnw("Error setting user password.", "req_id", reqID, "error", err, "remote_addr", r.RemoteAddr) s.Logger.Warnw("Error setting user password.", "req_id", reqID, "error", err, "remote_addr", r.RemoteAddr)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)

View File

@ -11,6 +11,7 @@ import (
"testing" "testing"
"git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste"
"git.t-juice.club/torjus/gpaste/users"
) )
func TestHandlers(t *testing.T) { func TestHandlers(t *testing.T) {
@ -101,7 +102,7 @@ func TestHandlers(t *testing.T) {
// TODO: Add test // TODO: Add test
username := "admin" username := "admin"
password := "admin" password := "admin"
user := &gpaste.User{Username: username} user := &users.User{Username: username}
if err := user.SetPassword(password); err != nil { if err := user.SetPassword(password); err != nil {
t.Fatalf("Error setting user password: %s", err) t.Fatalf("Error setting user password: %s", err)
} }

View File

@ -1,4 +1,4 @@
package gpaste package users
import "golang.org/x/crypto/bcrypt" import "golang.org/x/crypto/bcrypt"

View File

@ -1,10 +1,10 @@
package gpaste_test package users_test
import ( import (
"math/rand" "math/rand"
"testing" "testing"
"git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste/users"
) )
func TestUser(t *testing.T) { func TestUser(t *testing.T) {
@ -15,7 +15,7 @@ func TestUser(t *testing.T) {
} }
for username, password := range userMap { for username, password := range userMap {
user := &gpaste.User{Username: username} user := &users.User{Username: username}
if err := user.SetPassword(password); err != nil { if err := user.SetPassword(password); err != nil {
t.Fatalf("Error setting password: %s", err) t.Fatalf("Error setting password: %s", err)
} }

View File

@ -1,4 +1,4 @@
package gpaste package users
import ( import (
"encoding/json" "encoding/json"

View File

@ -1,18 +1,18 @@
package gpaste_test package users_test
import ( import (
"path/filepath" "path/filepath"
"testing" "testing"
"git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste/users"
) )
func TestBoltUserStore(t *testing.T) { func TestBoltUserStore(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
newFunc := func() (func(), gpaste.UserStore) { newFunc := func() (func(), users.UserStore) {
tmpFile := filepath.Join(tmpDir, randomString(8)) tmpFile := filepath.Join(tmpDir, randomString(8))
store, err := gpaste.NewBoltUserStore(tmpFile) store, err := users.NewBoltUserStore(tmpFile)
if err != nil { if err != nil {
t.Fatalf("Error creating store: %s", err) t.Fatalf("Error creating store: %s", err)
} }

View File

@ -1,4 +1,4 @@
package gpaste package users
import ( import (
"fmt" "fmt"

View File

@ -0,0 +1,15 @@
package users_test
import (
"testing"
"git.t-juice.club/torjus/gpaste/users"
)
func TestMemoryUserStore(t *testing.T) {
newFunc := func() (func(), users.UserStore) {
return func() {}, users.NewMemoryUserStore()
}
RunUserStoreTest(newFunc, t)
}

View File

@ -1,26 +1,26 @@
package gpaste_test package users_test
import ( import (
"testing" "testing"
"git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste/users"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
) )
func RunUserStoreTest(newFunc func() (func(), gpaste.UserStore), t *testing.T) { func RunUserStoreTest(newFunc func() (func(), users.UserStore), t *testing.T) {
t.Run("Basics", func(t *testing.T) { t.Run("Basics", func(t *testing.T) {
cleanup, s := newFunc() cleanup, s := newFunc()
t.Cleanup(cleanup) t.Cleanup(cleanup)
userMap := make(map[string]*gpaste.User) userMap := make(map[string]*users.User)
passwordMap := make(map[string]string) passwordMap := make(map[string]string)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
username := randomString(8) username := randomString(8)
password := randomString(16) password := randomString(16)
passwordMap[username] = password passwordMap[username] = password
user := &gpaste.User{ user := &users.User{
Username: username, Username: username,
Roles: []gpaste.Role{gpaste.RoleAdmin}, Roles: []users.Role{users.RoleAdmin},
} }
if err := user.SetPassword(password); err != nil { if err := user.SetPassword(password); err != nil {
t.Fatalf("Error setting password: %s", err) t.Fatalf("Error setting password: %s", err)

View File

@ -1,15 +0,0 @@
package gpaste_test
import (
"testing"
"git.t-juice.club/torjus/gpaste"
)
func TestMemoryUserStore(t *testing.T) {
newFunc := func() (func(), gpaste.UserStore) {
return func() {}, gpaste.NewMemoryUserStore()
}
RunUserStoreTest(newFunc, t)
}