From 4307a6063b24617b525ebe9d067a77cf7ad6c07e Mon Sep 17 00:00:00 2001 From: Nguyen Marc Date: Tue, 20 Feb 2024 18:43:55 +0100 Subject: [PATCH] feat(lint): fix golang practice --- .golangci.yaml | 1 + .../session/memory/memory_session_store.go | 38 +++++++++++++++ auth/webauthn/session/session_store.go | 18 +++++++ .../session/webauthn_session_store.go | 47 ------------------- auth/webauthn/user/user_repository.go | 20 ++++++++ auth/webauthn/webauthn.go | 2 +- database/counter/counter.go | 17 +++---- database/user/user_repository.go | 36 +++++--------- handler/handler_counter.go | 2 +- main.go | 4 +- 10 files changed, 100 insertions(+), 85 deletions(-) create mode 100644 auth/webauthn/session/memory/memory_session_store.go create mode 100644 auth/webauthn/session/session_store.go delete mode 100644 auth/webauthn/session/webauthn_session_store.go create mode 100644 auth/webauthn/user/user_repository.go diff --git a/.golangci.yaml b/.golangci.yaml index 7728be2..5371d03 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -2,6 +2,7 @@ linters: enable: # Drop-in replacement of `golint`. - revive + - ireturn issues: include: diff --git a/auth/webauthn/session/memory/memory_session_store.go b/auth/webauthn/session/memory/memory_session_store.go new file mode 100644 index 0000000..6b6e724 --- /dev/null +++ b/auth/webauthn/session/memory/memory_session_store.go @@ -0,0 +1,38 @@ +// Package memory implements a session store in-memory. +package memory + +import ( + "context" + + "github.com/Darkness4/auth-htmx/auth/webauthn/session" + "github.com/go-webauthn/webauthn/webauthn" +) + +// Store stores the login/registration session in-memory. +// +// In production, you should use a Redis or ETCD, or any distributed Key-Value database. +// Because of this, you cannot create replicas. +type Store struct { + store map[string]*webauthn.SessionData +} + +// NewStore instanciates a session store in memory. +func NewStore() *Store { + return &Store{ + store: make(map[string]*webauthn.SessionData), + } +} + +// Get the login or registration session. +func (s *Store) Get(_ context.Context, userID []byte) (*webauthn.SessionData, error) { + if v, ok := s.store[string(userID)]; ok { + return v, nil + } + return nil, session.ErrNotFound +} + +// Save the login or registration session. +func (s *Store) Save(_ context.Context, session *webauthn.SessionData) error { + s.store[string(session.UserID)] = session + return nil +} diff --git a/auth/webauthn/session/session_store.go b/auth/webauthn/session/session_store.go new file mode 100644 index 0000000..e1f34c5 --- /dev/null +++ b/auth/webauthn/session/session_store.go @@ -0,0 +1,18 @@ +// Package session handles the login/register sessions of webauthn. +package session + +import ( + "context" + "errors" + + "github.com/go-webauthn/webauthn/webauthn" +) + +// Store stores the login/registration session. +type Store interface { + Save(ctx context.Context, session *webauthn.SessionData) error + Get(ctx context.Context, userID []byte) (*webauthn.SessionData, error) +} + +// ErrNotFound happens when the session is not found in the store. +var ErrNotFound = errors.New("not found in session store") diff --git a/auth/webauthn/session/webauthn_session_store.go b/auth/webauthn/session/webauthn_session_store.go deleted file mode 100644 index 773e627..0000000 --- a/auth/webauthn/session/webauthn_session_store.go +++ /dev/null @@ -1,47 +0,0 @@ -// Package session handles the login/register sessions of webauthn. -package session - -import ( - "context" - "errors" - - "github.com/go-webauthn/webauthn/webauthn" -) - -// Store stores the login/registration session. -type Store interface { - Save(ctx context.Context, session *webauthn.SessionData) error - Get(ctx context.Context, userID []byte) (*webauthn.SessionData, error) -} - -// ErrNotFound happens when the session is not found in the store. -var ErrNotFound = errors.New("not found in session store") - -// StoreInMemory stores the login/registration session in-memory. -// -// In production, you should use a Redis or ETCD, or any distributed Key-Value database. -// Because of this, you cannot create replicas. -type StoreInMemory struct { - store map[string]*webauthn.SessionData -} - -// NewInMemory instanciates a session store in memory. -func NewInMemory() Store { - return &StoreInMemory{ - store: make(map[string]*webauthn.SessionData), - } -} - -// Get the login or registration session. -func (s *StoreInMemory) Get(_ context.Context, userID []byte) (*webauthn.SessionData, error) { - if v, ok := s.store[string(userID)]; ok { - return v, nil - } - return nil, ErrNotFound -} - -// Save the login or registration session. -func (s *StoreInMemory) Save(_ context.Context, session *webauthn.SessionData) error { - s.store[string(session.UserID)] = session - return nil -} diff --git a/auth/webauthn/user/user_repository.go b/auth/webauthn/user/user_repository.go new file mode 100644 index 0000000..11858f8 --- /dev/null +++ b/auth/webauthn/user/user_repository.go @@ -0,0 +1,20 @@ +// Package user describes the methods to handle users needed for webauthn. +package user + +import ( + "context" + + "github.com/Darkness4/auth-htmx/database/user" + "github.com/go-webauthn/webauthn/webauthn" +) + +// Repository defines the user methods needed for webauthn. +type Repository interface { + GetOrCreateByName(ctx context.Context, name string) (*user.User, error) + GetByName(ctx context.Context, name string) (*user.User, error) + Get(ctx context.Context, id []byte) (*user.User, error) + Create(ctx context.Context, name string, displayName string) (*user.User, error) + AddCredential(ctx context.Context, id []byte, credential *webauthn.Credential) error + UpdateCredential(ctx context.Context, credential *webauthn.Credential) error + RemoveCredential(ctx context.Context, id []byte, credentialID []byte) error +} diff --git a/auth/webauthn/webauthn.go b/auth/webauthn/webauthn.go index 981d4c2..9e16762 100644 --- a/auth/webauthn/webauthn.go +++ b/auth/webauthn/webauthn.go @@ -8,7 +8,7 @@ import ( "time" "github.com/Darkness4/auth-htmx/auth/webauthn/session" - "github.com/Darkness4/auth-htmx/database/user" + "github.com/Darkness4/auth-htmx/auth/webauthn/user" "github.com/Darkness4/auth-htmx/jwt" "github.com/go-webauthn/webauthn/protocol" "github.com/go-webauthn/webauthn/webauthn" diff --git a/database/counter/counter.go b/database/counter/counter.go index 4cb26bf..b73ffbd 100644 --- a/database/counter/counter.go +++ b/database/counter/counter.go @@ -9,25 +9,20 @@ import ( "github.com/Darkness4/auth-htmx/database" ) -// Repository defines the counter methods. -type Repository interface { - Inc(ctx context.Context, userID string) (new int64, err error) - Get(ctx context.Context, userID string) (int64, error) -} - // NewRepository wraps around a SQL database to execute the counter methods. -func NewRepository(db *sql.DB) Repository { - return &repository{ +func NewRepository(db *sql.DB) *Repository { + return &Repository{ Queries: database.New(db), } } -type repository struct { +// Repository wraps around a SQL database to execute the counter methods. +type Repository struct { *database.Queries } // Inc increments the counter of a user in the database by one. -func (r *repository) Inc(ctx context.Context, userID string) (newValue int64, err error) { +func (r *Repository) Inc(ctx context.Context, userID string) (newValue int64, err error) { newValue, err = r.Queries.IncrementCounter(ctx, userID) if err != nil && !errors.Is(err, sql.ErrNoRows) { return newValue, err @@ -39,7 +34,7 @@ func (r *repository) Inc(ctx context.Context, userID string) (newValue int64, er } // Get the value of the counter of a user from the database. -func (r *repository) Get(ctx context.Context, userID string) (int64, error) { +func (r *Repository) Get(ctx context.Context, userID string) (int64, error) { counter, err := r.Queries.GetCounter(ctx, userID) if err != nil { if errors.Is(err, sql.ErrNoRows) { diff --git a/database/user/user_repository.go b/database/user/user_repository.go index 43f147b..7f97b76 100644 --- a/database/user/user_repository.go +++ b/database/user/user_repository.go @@ -12,25 +12,15 @@ import ( "github.com/go-webauthn/webauthn/webauthn" ) -// Repository defines the user methods. -type Repository interface { - GetOrCreateByName(ctx context.Context, name string) (*User, error) - GetByName(ctx context.Context, name string) (*User, error) - Get(ctx context.Context, id []byte) (*User, error) - Create(ctx context.Context, name string, displayName string) (*User, error) - AddCredential(ctx context.Context, id []byte, credential *webauthn.Credential) error - UpdateCredential(ctx context.Context, credential *webauthn.Credential) error - RemoveCredential(ctx context.Context, id []byte, credentialID []byte) error -} - -// NewRepository wraps around a SQL database to execute the counter methods. -func NewRepository(db *sql.DB) Repository { - return &repository{ +// NewRepository instanciates a new user repository. +func NewRepository(db *sql.DB) *Repository { + return &Repository{ Queries: database.New(db), } } -type repository struct { +// Repository wraps around a SQL database to execute the webauthn methods. +type Repository struct { *database.Queries } @@ -42,7 +32,7 @@ var ( ) // AddCredential to a user from the database. -func (r *repository) AddCredential( +func (r *Repository) AddCredential( ctx context.Context, id []byte, credential *webauthn.Credential, @@ -75,7 +65,7 @@ func (r *repository) AddCredential( } // UpdateCredential of a user from the database. -func (r *repository) UpdateCredential(ctx context.Context, credential *webauthn.Credential) error { +func (r *Repository) UpdateCredential(ctx context.Context, credential *webauthn.Credential) error { if credential.Transport == nil { credential.Transport = []protocol.AuthenticatorTransport{} } @@ -106,7 +96,7 @@ func (r *repository) UpdateCredential(ctx context.Context, credential *webauthn. // Create a user in the database. // // The user ID is completely randomized. -func (r *repository) Create(ctx context.Context, name string, displayName string) (*User, error) { +func (r *Repository) Create(ctx context.Context, name string, displayName string) (*User, error) { id := make([]byte, 64) if _, err := rand.Read(id); err != nil { return nil, err @@ -125,7 +115,7 @@ func (r *repository) Create(ctx context.Context, name string, displayName string } // GetOrCreateByName a user from the databse. -func (r *repository) GetOrCreateByName(ctx context.Context, name string) (*User, error) { +func (r *Repository) GetOrCreateByName(ctx context.Context, name string) (*User, error) { u, err := r.GetByName(ctx, name) if errors.Is(err, ErrUserNotFound) { u, err = r.Create(ctx, name, name) @@ -140,7 +130,7 @@ func (r *repository) GetOrCreateByName(ctx context.Context, name string) (*User, } // Gea user from the database. -func (r *repository) Get(ctx context.Context, id []byte) (*User, error) { +func (r *Repository) Get(ctx context.Context, id []byte) (*User, error) { u, err := r.Queries.GetUser(ctx, id) if errors.Is(err, sql.ErrNoRows) { return nil, ErrUserNotFound @@ -157,7 +147,7 @@ func (r *repository) Get(ctx context.Context, id []byte) (*User, error) { } // GetByName a user from the database. -func (r *repository) GetByName(ctx context.Context, name string) (*User, error) { +func (r *Repository) GetByName(ctx context.Context, name string) (*User, error) { u, err := r.Queries.GetUserByName(ctx, name) if errors.Is(err, sql.ErrNoRows) { return nil, ErrUserNotFound @@ -173,7 +163,7 @@ func (r *repository) GetByName(ctx context.Context, name string) (*User, error) return fromModel(&u, credentials), nil } -func (r *repository) getCredentialsByUser( +func (r *Repository) getCredentialsByUser( ctx context.Context, id []byte, ) ([]webauthn.Credential, error) { @@ -192,7 +182,7 @@ func (r *repository) getCredentialsByUser( } // RemoveCredential of a user from the database. -func (r *repository) RemoveCredential( +func (r *Repository) RemoveCredential( ctx context.Context, id []byte, credentialID []byte, diff --git a/handler/handler_counter.go b/handler/handler_counter.go index 2a9bf7d..3a2e92e 100644 --- a/handler/handler_counter.go +++ b/handler/handler_counter.go @@ -10,7 +10,7 @@ import ( ) // Count increments the counter and returns the new value. -func Count(counter counter.Repository) http.HandlerFunc { +func Count(counter *counter.Repository) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { claims, ok := jwt.GetClaimsFromRequest(r) if !ok { diff --git a/main.go b/main.go index 305cb68..8885dc9 100644 --- a/main.go +++ b/main.go @@ -20,7 +20,7 @@ import ( "github.com/Darkness4/auth-htmx/auth" "github.com/Darkness4/auth-htmx/auth/oauth" internalwebauthn "github.com/Darkness4/auth-htmx/auth/webauthn" - "github.com/Darkness4/auth-htmx/auth/webauthn/session" + "github.com/Darkness4/auth-htmx/auth/webauthn/session/memory" "github.com/Darkness4/auth-htmx/database" "github.com/Darkness4/auth-htmx/database/counter" "github.com/Darkness4/auth-htmx/database/user" @@ -168,7 +168,7 @@ var app = &cli.App{ webauthnS := internalwebauthn.New( webAuthn, user.NewRepository(d), - session.NewInMemory(), + memory.NewStore(), jwt.Secret(jwtSecret), )