Skip to content

Commit

Permalink
feat: introduce hanko profile element and related api changes (teamha…
Browse files Browse the repository at this point in the history
…nko#495)

* feat: introduce hanko profile element and related api changes
  • Loading branch information
bjoern-m authored Jan 25, 2023
1 parent 93ad9c4 commit ca62cf4
Show file tree
Hide file tree
Showing 254 changed files with 13,813 additions and 4,003 deletions.
10 changes: 7 additions & 3 deletions backend/audit_log/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ func (c *logger) store(context echo.Context, auditLogType models.AuditLogType, u
var userEmail *string = nil
if user != nil {
userId = &user.ID
userEmail = &user.Email
if e := user.Emails.GetPrimary(); e != nil {
userEmail = &e.Address
}
}
var errString *string = nil
if logError != nil {
Expand Down Expand Up @@ -103,8 +105,10 @@ func (c *logger) logToConsole(context echo.Context, auditLogType models.AuditLog
Str("time_unix", strconv.FormatInt(now.Unix(), 10))

if user != nil {
loggerEvent.Str("user_id", user.ID.String()).
Str("user_email", user.Email)
loggerEvent.Str("user_id", user.ID.String())
if e := user.Emails.GetPrimary(); e != nil {
loggerEvent.Str("user_email", e.Address)
}
}

loggerEvent.Send()
Expand Down
10 changes: 10 additions & 0 deletions backend/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Config struct {
Service Service `yaml:"service" json:"service" koanf:"service"`
Session Session `yaml:"session" json:"session" koanf:"session"`
AuditLog AuditLog `yaml:"audit_log" json:"audit_log" koanf:"audit_log"`
Emails Emails `yaml:"emails" json:"emails" koanf:"emails"`
}

func Load(cfgFile *string) (*Config, error) {
Expand Down Expand Up @@ -97,6 +98,10 @@ func DefaultConfig() *Config {
OutputStream: OutputStreamStdOut,
},
},
Emails: Emails{
RequireVerification: true,
MaxNumOfAddresses: 5,
},
}
}

Expand Down Expand Up @@ -348,6 +353,11 @@ type AuditLogConsole struct {
OutputStream OutputStream `yaml:"output" json:"output" koanf:"output"`
}

type Emails struct {
RequireVerification bool `yaml:"require_verification" json:"require_verification" koanf:"require_verification"`
MaxNumOfAddresses int `yaml:"max_num_of_addresses" json:"max_num_of_addresses" koanf:"max_num_of_addresses"`
}

type OutputStream string

var (
Expand Down
6 changes: 5 additions & 1 deletion backend/dto/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import (
// PublicConfig is the part of the configuration that will be shared with the frontend
type PublicConfig struct {
Password config.Password `json:"password"`
Emails config.Emails `json:"emails"`
}

// FromConfig Returns a PublicConfig from the Application configuration
func FromConfig(config config.Config) PublicConfig {
return PublicConfig{Password: config.Password}
return PublicConfig{
Password: config.Password,
Emails: config.Emails,
}
}
31 changes: 31 additions & 0 deletions backend/dto/email.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package dto

import (
"github.com/gofrs/uuid"
"github.com/teamhanko/hanko/backend/persistence/models"
)

type EmailResponse struct {
ID uuid.UUID `json:"id"`
Address string `json:"address"`
IsVerified bool `json:"is_verified"`
IsPrimary bool `json:"is_primary"`
}

type EmailCreateRequest struct {
Address string `json:"address"`
}

type EmailUpdateRequest struct {
IsPrimary *bool `json:"is_primary"`
}

// FromEmailModel Converts the DB model to a DTO object
func FromEmailModel(email *models.Email) *EmailResponse {
return &EmailResponse{
ID: email.ID,
Address: email.Address,
IsVerified: email.Verified,
IsPrimary: email.IsPrimary(),
}
}
2 changes: 1 addition & 1 deletion backend/dto/intern/WebauthnCredential.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func WebauthnCredentialToModel(credential *webauthn.Credential, userId uuid.UUID) *models.WebauthnCredential {
now := time.Now()
now := time.Now().UTC()
aaguid, _ := uuid.FromBytes(credential.Authenticator.AAGUID)
credentialID := base64.RawURLEncoding.EncodeToString(credential.ID)

Expand Down
12 changes: 9 additions & 3 deletions backend/dto/intern/WebauthnUser.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package intern

import (
"errors"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/gofrs/uuid"
"github.com/teamhanko/hanko/backend/persistence/models"
)

func NewWebauthnUser(user models.User, credentials []models.WebauthnCredential) *WebauthnUser {
func NewWebauthnUser(user models.User, credentials []models.WebauthnCredential) (*WebauthnUser, error) {
email := user.Emails.GetPrimary()
if email == nil {
return nil, errors.New("primary email unavailable")
}

return &WebauthnUser{
UserId: user.ID,
Email: user.Email,
Email: email.Address,
WebauthnCredentials: credentials,
}
}, nil
}

type WebauthnUser struct {
Expand Down
3 changes: 2 additions & 1 deletion backend/dto/passcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ type PasscodeFinishRequest struct {
}

type PasscodeInitRequest struct {
UserId string `json:"user_id" validate:"required,uuid4"`
UserId string `json:"user_id" validate:"required,uuid4"`
EmailId *string `json:"email_id"`
}

type PasscodeReturn struct {
Expand Down
28 changes: 28 additions & 0 deletions backend/dto/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dto

import (
"github.com/gofrs/uuid"
"github.com/teamhanko/hanko/backend/persistence/models"
"time"
)

type CreateUserResponse struct {
ID uuid.UUID `json:"id"` // deprecated
UserID uuid.UUID `json:"user_id"`
EmailID uuid.UUID `json:"email_id"`
}

type GetUserResponse struct {
ID uuid.UUID `json:"id"`
Email *string `json:"email,omitempty"`
WebauthnCredentials []models.WebauthnCredential `json:"webauthn_credentials"` // deprecated
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}

type UserInfoResponse struct {
ID uuid.UUID `json:"id"`
EmailID uuid.UUID `json:"email_id"`
Verified bool `json:"verified"`
HasWebauthnCredential bool `json:"has_webauthn_credential"`
}
34 changes: 34 additions & 0 deletions backend/dto/webauthn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package dto

import (
"github.com/gofrs/uuid"
"github.com/teamhanko/hanko/backend/persistence/models"
"time"
)

type WebauthnCredentialUpdateRequest struct {
Name *string `json:"name"`
}

type WebauthnCredentialResponse struct {
ID string `json:"id"`
Name *string `json:"name,omitempty"`
PublicKey string `json:"public_key"`
AttestationType string `json:"attestation_type"`
AAGUID uuid.UUID `json:"aaguid"`
CreatedAt time.Time `json:"created_at"`
Transports []string `json:"transports"`
}

// FromWebauthnCredentialModel Converts the DB model to a DTO object
func FromWebauthnCredentialModel(c *models.WebauthnCredential) *WebauthnCredentialResponse {
return &WebauthnCredentialResponse{
ID: c.ID,
Name: c.Name,
PublicKey: c.PublicKey,
AttestationType: c.AttestationType,
AAGUID: c.AAGUID,
CreatedAt: c.CreatedAt,
Transports: c.Transports.GetNames(),
}
}
Loading

0 comments on commit ca62cf4

Please sign in to comment.