implement auth
ci.vdhsn.com/push Build is failing
Details
ci.vdhsn.com/push Build is failing
Details
parent
649bcefbef
commit
5a191a2c72
@ -1,9 +1,161 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data"
|
||||
)
|
||||
|
||||
type (
|
||||
Domain struct {
|
||||
Storage
|
||||
PasswordHasher
|
||||
}
|
||||
|
||||
HashedPassword []byte
|
||||
|
||||
PasswordHasher interface {
|
||||
Hash(string) HashedPassword
|
||||
Compare(string, HashedPassword) bool
|
||||
}
|
||||
|
||||
Storage interface{}
|
||||
Storage interface {
|
||||
RegisterAccount(context.Context, data.RegisterAccountInput) (int, error)
|
||||
GetAccount(context.Context, data.GetAccountInput) (data.AccountResult, error)
|
||||
CreateSession(context.Context, data.CreateSessionInput) (data.Session, error)
|
||||
VerifyAccount(context.Context, data.VerifyAccountInput) error
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CreateAccountCommand struct {
|
||||
Email string
|
||||
Password string
|
||||
Role Role
|
||||
}
|
||||
AccountCreated struct {
|
||||
Account
|
||||
}
|
||||
)
|
||||
|
||||
func (d *Domain) CreateAccount(ctx context.Context, in CreateAccountCommand) (out AccountCreated, err error) {
|
||||
if in.Email == "" {
|
||||
err = errors.New("email cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if in.Password == "" {
|
||||
err = errors.New("password cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if in.Role == EmptyRole {
|
||||
in.Role = UserRole
|
||||
}
|
||||
|
||||
var accountID int
|
||||
if accountID, err = d.Storage.RegisterAccount(ctx, data.RegisterAccountInput{
|
||||
Email: in.Email,
|
||||
PasswordHash: in.Password,
|
||||
Role: in.Role.String(),
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not register account: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
var ar data.AccountResult
|
||||
if ar, err = d.Storage.GetAccount(ctx, data.GetAccountInput{
|
||||
Email: in.Email,
|
||||
AccountID: accountID,
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not find account by ID: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = AccountCreated{
|
||||
Account: Account{
|
||||
ID: ar.ID,
|
||||
Created: ar.Created,
|
||||
Verified: ar.Verified,
|
||||
Email: ar.Email,
|
||||
Role: Role(ar.Role),
|
||||
Enabled: ar.Enabled,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
LoginCommand struct{}
|
||||
LoggedIn struct {
|
||||
Account
|
||||
SessionID int
|
||||
Created time.Time
|
||||
}
|
||||
)
|
||||
|
||||
func (d *Domain) Login(ctx context.Context, in LoginCommand) (out LoggedIn, err error) {
|
||||
var sess data.Session
|
||||
if sess, err = d.Storage.CreateSession(ctx, data.CreateSessionInput{}); err != nil {
|
||||
err = fmt.Errorf("could not create session: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
var ar data.AccountResult
|
||||
if ar, err = d.Storage.GetAccount(ctx, data.GetAccountInput{
|
||||
AccountID: sess.AccountID,
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not find account by ID: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = LoggedIn{
|
||||
Account: Account{
|
||||
ID: ar.ID,
|
||||
Created: ar.Created,
|
||||
Verified: ar.Verified,
|
||||
Email: ar.Email,
|
||||
Role: Role(ar.Role),
|
||||
Enabled: ar.Enabled,
|
||||
},
|
||||
Created: sess.Created,
|
||||
SessionID: sess.ID,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
GetAccountCommand struct{}
|
||||
)
|
||||
|
||||
func (d *Domain) GetAccount(ctx context.Context, in GetAccountCommand) (out Account, err error) {
|
||||
var ar data.AccountResult
|
||||
if ar, err = d.Storage.GetAccount(ctx, data.GetAccountInput{}); err != nil {
|
||||
err = fmt.Errorf("could not get account: %w", err)
|
||||
}
|
||||
|
||||
out = Account{
|
||||
ID: ar.ID,
|
||||
Created: ar.Created,
|
||||
Verified: ar.Verified,
|
||||
Email: ar.Email,
|
||||
Role: Role(ar.Role),
|
||||
Enabled: ar.Enabled,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
VerifyAccountCommand struct{}
|
||||
AccountVerified struct{}
|
||||
)
|
||||
|
||||
func (d *Domain) VerifyAccount(ctx context.Context, in VerifyAccountCommand) (out AccountVerified, err error) {
|
||||
err = errors.New("Unimplemented")
|
||||
return
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDomain_CreateAccount(t *testing.T) {
|
||||
type fields struct {
|
||||
Storage Storage
|
||||
}
|
||||
type args struct {
|
||||
in CreateAccountCommand
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantOut AccountCreated
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
d := &Domain{
|
||||
Storage: tt.fields.Storage,
|
||||
}
|
||||
gotOut, err := d.CreateAccount(tt.args.in)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Domain.CreateAccount() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(gotOut, tt.wantOut) {
|
||||
t.Errorf("Domain.CreateAccount() = %v, want %v", gotOut, tt.wantOut)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<script lang="ts">
|
||||
let showPassword = false;
|
||||
let showRegistration = false;
|
||||
|
||||
const revealPass = () => (showPassword = !showPassword);
|
||||
|
||||
function execLogin() {
|
||||
console.log('LOGGING IN');
|
||||
}
|
||||
</script>
|
||||
|
||||
<form class="flex" on:submit|preventDefault={execLogin}>
|
||||
<span class="flex flex-col justify-around w-20">
|
||||
<label for="email"> Email </label>
|
||||
<label for="password"> Password </label>
|
||||
</span>
|
||||
|
||||
<span class="flex flex-col">
|
||||
<span class="flex">
|
||||
<input class="py-1" type="text" />
|
||||
<button class="w-20"> Login </button>
|
||||
</span>
|
||||
<span class="flex">
|
||||
<input
|
||||
class="px-2 py-1 border-r-0"
|
||||
name="password"
|
||||
on:blur={() => (showPassword = false)}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
/>
|
||||
{#if showRegistration}
|
||||
<input
|
||||
class="px-2 py-1 border-r-0"
|
||||
name="confirm_password"
|
||||
on:blur={() => (showPassword = false)}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
/>
|
||||
{/if}
|
||||
<button class="border-l-0 px-2 py-1 w-16" on:click|stopPropagation={revealPass}>
|
||||
{showPassword ? 'Hide' : 'Show'}
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</form>
|
@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
let password;
|
||||
let confirm_password;
|
||||
let email;
|
||||
|
||||
let showPassword = false;
|
||||
|
||||
const revealPass = () => (showPassword = !showPassword);
|
||||
|
||||
function execRegister() {
|
||||
console.log('Regstering User');
|
||||
}
|
||||
</script>
|
||||
|
||||
<form class="flex" on:submit|preventDefault={execRegister}>
|
||||
<span class="flex flex-col justify-around w-20">
|
||||
<label for="email"> Email </label>
|
||||
<label for="password"> Password </label>
|
||||
</span>
|
||||
|
||||
<span class="flex flex-col">
|
||||
<span class="flex">
|
||||
<input class="py-1" type="text" />
|
||||
<button class="w-20"> Login </button>
|
||||
</span>
|
||||
<span class="flex">
|
||||
<input
|
||||
class="px-2 py-1 border-r-0"
|
||||
name="password"
|
||||
on:blur={() => (showPassword = false)}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
/>
|
||||
<input
|
||||
class="px-2 py-1 border-r-0"
|
||||
name="confirm_password"
|
||||
on:blur={() => (showPassword = false)}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
/>
|
||||
<button class="border-l-0 px-2 py-1 w-16" on:click|stopPropagation={revealPass}>
|
||||
{showPassword ? 'Hide' : 'Show'}
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</form>
|
Loading…
Reference in new issue