Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: login and registration with code
Browse files Browse the repository at this point in the history
Benehiko committed Jul 25, 2023

Unverified

This user has not yet uploaded their public signing key.
1 parent 3a79a63 commit e51d791
Showing 166 changed files with 3,919 additions and 1,436 deletions.
18 changes: 18 additions & 0 deletions courier/email_templates.go
Original file line number Diff line number Diff line change
@@ -40,6 +40,8 @@ const (
TypeVerificationCodeValid TemplateType = "verification_code_valid"
TypeOTP TemplateType = "otp"
TypeTestStub TemplateType = "stub"
TypeLoginCodeValid TemplateType = "login_code_valid"
TypeRegistrationCodeValid TemplateType = "registration_code_valid"
)

func GetEmailTemplateType(t EmailTemplate) (TemplateType, error) {
@@ -60,6 +62,10 @@ func GetEmailTemplateType(t EmailTemplate) (TemplateType, error) {
return TypeVerificationCodeInvalid, nil
case *email.VerificationCodeValid:
return TypeVerificationCodeValid, nil
case *email.LoginCodeValid:
return TypeLoginCodeValid, nil
case *email.RegistrationCodeValid:
return TypeRegistrationCodeValid, nil
case *email.TestStub:
return TypeTestStub, nil
default:
@@ -123,6 +129,18 @@ func NewEmailTemplateFromMessage(d template.Dependencies, msg Message) (EmailTem
return nil, err
}
return email.NewTestStub(d, &t), nil
case TypeLoginCodeValid:
var t email.LoginCodeValidModel
if err := json.Unmarshal(msg.TemplateData, &t); err != nil {
return nil, err
}
return email.NewLoginCodeValid(d, &t), nil
case TypeRegistrationCodeValid:
var t email.RegistrationCodeValidModel
if err := json.Unmarshal(msg.TemplateData, &t); err != nil {
return nil, err
}
return email.NewRegistrationCodeValid(d, &t), nil
default:
return nil, errors.Errorf("received unexpected message template type: %s", msg.TemplateType)
}
5 changes: 4 additions & 1 deletion courier/email_templates_test.go
Original file line number Diff line number Diff line change
@@ -27,6 +27,8 @@ func TestGetTemplateType(t *testing.T) {
courier.TypeVerificationCodeInvalid: &email.VerificationCodeInvalid{},
courier.TypeVerificationCodeValid: &email.VerificationCodeValid{},
courier.TypeTestStub: &email.TestStub{},
courier.TypeLoginCodeValid: &email.LoginCodeValid{},
courier.TypeRegistrationCodeValid: &email.RegistrationCodeValid{},
} {
t.Run(fmt.Sprintf("case=%s", expectedType), func(t *testing.T) {
actualType, err := courier.GetEmailTemplateType(tmpl)
@@ -50,6 +52,8 @@ func TestNewEmailTemplateFromMessage(t *testing.T) {
courier.TypeVerificationCodeInvalid: email.NewVerificationCodeInvalid(reg, &email.VerificationCodeInvalidModel{To: "baz"}),
courier.TypeVerificationCodeValid: email.NewVerificationCodeValid(reg, &email.VerificationCodeValidModel{To: "faz", VerificationURL: "http://bar.foo", VerificationCode: "123456678"}),
courier.TypeTestStub: email.NewTestStub(reg, &email.TestStubModel{To: "far", Subject: "test subject", Body: "test body"}),
courier.TypeLoginCodeValid: email.NewLoginCodeValid(reg, &email.LoginCodeValidModel{To: "far", LoginCode: "123456"}),
courier.TypeRegistrationCodeValid: email.NewRegistrationCodeValid(reg, &email.RegistrationCodeValidModel{To: "far", RegistrationCode: "123456"}),
} {
t.Run(fmt.Sprintf("case=%s", tmplType), func(t *testing.T) {
tmplData, err := json.Marshal(expectedTmpl)
@@ -84,7 +88,6 @@ func TestNewEmailTemplateFromMessage(t *testing.T) {
actualBodyPlaintext, err := actualTmpl.EmailBodyPlaintext(ctx)
require.NoError(t, err)
require.Equal(t, expectedBodyPlaintext, actualBodyPlaintext)

})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Hi,

please login to your account by entering the following code:

{{ .LoginCode }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Hi,

please login to your account by entering the following code:

{{ .LoginCode }}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Login to your account
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Hi,

please complete your account registration by entering the following code:

{{ .RegistrationCode }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Hi,

please complete your account registration by entering the following code:

{{ .RegistrationCode }}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Complete your account registration
51 changes: 51 additions & 0 deletions courier/template/email/login_code_valid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package email

import (
"context"
"encoding/json"
"os"
"strings"

"github.com/ory/kratos/courier/template"
)

type (
LoginCodeValid struct {
deps template.Dependencies
model *LoginCodeValidModel
}
LoginCodeValidModel struct {
To string
LoginCode string
Identity map[string]interface{}
}
)

func NewLoginCodeValid(d template.Dependencies, m *LoginCodeValidModel) *LoginCodeValid {
return &LoginCodeValid{deps: d, model: m}
}

func (t *LoginCodeValid) EmailRecipient() (string, error) {
return t.model.To, nil
}

func (t *LoginCodeValid) EmailSubject(ctx context.Context) (string, error) {
subject, err := template.LoadText(ctx, t.deps, os.DirFS(t.deps.CourierConfig().CourierTemplatesRoot(ctx)), "login_code/valid/email.subject.gotmpl", "login_code/valid/email.subject*", t.model, t.deps.CourierConfig().CourierTemplatesLoginCodeValid(ctx).Subject)

return strings.TrimSpace(subject), err
}

func (t *LoginCodeValid) EmailBody(ctx context.Context) (string, error) {
return template.LoadHTML(ctx, t.deps, os.DirFS(t.deps.CourierConfig().CourierTemplatesRoot(ctx)), "login_code/valid/email.body.gotmpl", "login_code/valid/email.body*", t.model, t.deps.CourierConfig().CourierTemplatesLoginCodeValid(ctx).Body.HTML)
}

func (t *LoginCodeValid) EmailBodyPlaintext(ctx context.Context) (string, error) {
return template.LoadText(ctx, t.deps, os.DirFS(t.deps.CourierConfig().CourierTemplatesRoot(ctx)), "login_code/valid/email.body.plaintext.gotmpl", "login_code/valid/email.body.plaintext*", t.model, t.deps.CourierConfig().CourierTemplatesLoginCodeValid(ctx).Body.PlainText)
}

func (t *LoginCodeValid) MarshalJSON() ([]byte, error) {
return json.Marshal(t.model)
}
30 changes: 30 additions & 0 deletions courier/template/email/login_code_valid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package email_test

import (
"context"
"testing"

"github.com/ory/kratos/courier"
"github.com/ory/kratos/courier/template/email"
"github.com/ory/kratos/courier/template/testhelpers"
"github.com/ory/kratos/internal"
)

func TestLoginCodeValid(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

t.Run("test=with courier templates directory", func(t *testing.T) {
_, reg := internal.NewFastRegistryWithMocks(t)
tpl := email.NewLoginCodeValid(reg, &email.LoginCodeValidModel{})

testhelpers.TestRendered(t, ctx, tpl)
})

t.Run("test=with remote resources", func(t *testing.T) {
testhelpers.TestRemoteTemplates(t, "../courier/builtin/templates/login_code/valid", courier.TypeLoginCodeValid)
})
}
51 changes: 51 additions & 0 deletions courier/template/email/registration_code_valid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package email

import (
"context"
"encoding/json"
"os"
"strings"

"github.com/ory/kratos/courier/template"
)

type (
RegistrationCodeValid struct {
deps template.Dependencies
model *RegistrationCodeValidModel
}
RegistrationCodeValidModel struct {
To string
Traits map[string]interface{}
RegistrationCode string
}
)

func NewRegistrationCodeValid(d template.Dependencies, m *RegistrationCodeValidModel) *RegistrationCodeValid {
return &RegistrationCodeValid{deps: d, model: m}
}

func (t *RegistrationCodeValid) EmailRecipient() (string, error) {
return t.model.To, nil
}

func (t *RegistrationCodeValid) EmailSubject(ctx context.Context) (string, error) {
subject, err := template.LoadText(ctx, t.deps, os.DirFS(t.deps.CourierConfig().CourierTemplatesRoot(ctx)), "registration_code/valid/email.subject.gotmpl", "registration_code/valid/email.subject*", t.model, t.deps.CourierConfig().CourierTemplatesRegistrationCodeValid(ctx).Subject)

return strings.TrimSpace(subject), err
}

func (t *RegistrationCodeValid) EmailBody(ctx context.Context) (string, error) {
return template.LoadHTML(ctx, t.deps, os.DirFS(t.deps.CourierConfig().CourierTemplatesRoot(ctx)), "registration_code/valid/email.body.gotmpl", "registration_code/valid/email.body*", t.model, t.deps.CourierConfig().CourierTemplatesRegistrationCodeValid(ctx).Body.HTML)
}

func (t *RegistrationCodeValid) EmailBodyPlaintext(ctx context.Context) (string, error) {
return template.LoadText(ctx, t.deps, os.DirFS(t.deps.CourierConfig().CourierTemplatesRoot(ctx)), "registration_code/valid/email.body.plaintext.gotmpl", "registration_code/valid/email.body.plaintext*", t.model, t.deps.CourierConfig().CourierTemplatesRegistrationCodeValid(ctx).Body.PlainText)
}

func (t *RegistrationCodeValid) MarshalJSON() ([]byte, error) {
return json.Marshal(t.model)
}
30 changes: 30 additions & 0 deletions courier/template/email/registration_code_valid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package email_test

import (
"context"
"testing"

"github.com/ory/kratos/courier"
"github.com/ory/kratos/courier/template/email"
"github.com/ory/kratos/courier/template/testhelpers"
"github.com/ory/kratos/internal"
)

func TestRegistrationCodeValid(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

t.Run("test=with courier templates directory", func(t *testing.T) {
_, reg := internal.NewFastRegistryWithMocks(t)
tpl := email.NewRegistrationCodeValid(reg, &email.RegistrationCodeValidModel{})

testhelpers.TestRendered(t, ctx, tpl)
})

t.Run("test=with remote resources", func(t *testing.T) {
testhelpers.TestRemoteTemplates(t, "../courier/builtin/templates/registration_code/valid", courier.TypeRegistrationCodeValid)
})
}
2 changes: 2 additions & 0 deletions courier/template/template.go
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@ type (
CourierTemplatesVerificationValid() *config.CourierEmailTemplate
CourierTemplatesRecoveryInvalid() *config.CourierEmailTemplate
CourierTemplatesRecoveryValid() *config.CourierEmailTemplate
CourierTemplatesLoginValid() *config.CourierEmailTemplate
CourierTemplatesRegistrationValid() *config.CourierEmailTemplate
}

Dependencies interface {
56 changes: 55 additions & 1 deletion driver/config/config.go
Original file line number Diff line number Diff line change
@@ -68,6 +68,8 @@ const (
ViperKeyCourierTemplatesVerificationCodeValidEmail = "courier.templates.verification_code.valid.email"
ViperKeyCourierDeliveryStrategy = "courier.delivery_strategy"
ViperKeyCourierHTTPRequestConfig = "courier.http.request_config"
ViperKeyCourierTemplatesLoginCodeValidEmail = "courier.templates.login_code.valid.email"
ViperKeyCourierTemplatesRegistrationCodeValidEmail = "courier.templates.registration_code.valid.email"
ViperKeyCourierSMTPFrom = "courier.smtp.from_address"
ViperKeyCourierSMTPFromName = "courier.smtp.from_name"
ViperKeyCourierSMTPHeaders = "courier.smtp.headers"
@@ -225,6 +227,11 @@ type (
Enabled bool `json:"enabled"`
Config json.RawMessage `json:"config"`
}
SelfServiceStrategyCode struct {
RegistrationEnabled bool `json:"registration_enabled"`
LoginEnabled bool `json:"login_enabled"`
*SelfServiceStrategy
}
Schema struct {
ID string `json:"id" koanf:"id"`
URL string `json:"url" koanf:"url"`
@@ -278,6 +285,8 @@ type (
CourierTemplatesRecoveryCodeValid(ctx context.Context) *CourierEmailTemplate
CourierTemplatesVerificationCodeInvalid(ctx context.Context) *CourierEmailTemplate
CourierTemplatesVerificationCodeValid(ctx context.Context) *CourierEmailTemplate
CourierTemplatesLoginCodeValid(ctx context.Context) *CourierEmailTemplate
CourierTemplatesRegistrationCodeValid(ctx context.Context) *CourierEmailTemplate
CourierMessageRetries(ctx context.Context) int
}
)
@@ -723,7 +732,9 @@ func (p *Config) SelfServiceStrategy(ctx context.Context, strategy string) *Self
config = c
}

enabledKey := fmt.Sprintf("%s.%s.enabled", ViperKeySelfServiceStrategyConfig, strategy)
basePath := fmt.Sprintf("%s.%s", ViperKeySelfServiceStrategyConfig, strategy)

enabledKey := fmt.Sprintf("%s.enabled", basePath)
s := &SelfServiceStrategy{
Enabled: pp.Bool(enabledKey),
Config: json.RawMessage(config),
@@ -733,6 +744,7 @@ func (p *Config) SelfServiceStrategy(ctx context.Context, strategy string) *Self
// we need to forcibly set these values here:
if !pp.Exists(enabledKey) {
switch strategy {
case "otp":
case "password":
fallthrough
case "profile":
@@ -749,6 +761,40 @@ func (p *Config) SelfServiceStrategy(ctx context.Context, strategy string) *Self
return s
}

func (p *Config) SelfServiceCodeStrategy(ctx context.Context) *SelfServiceStrategyCode {
pp := p.GetProvider(ctx)

config := "{}"
out, err := pp.Marshal(kjson.Parser())
if err != nil {
p.l.WithError(err).Warn("Unable to marshal self service strategy configuration.")
} else if c := gjson.GetBytes(out,
fmt.Sprintf("%s.%s.config", ViperKeySelfServiceStrategyConfig, "code")).Raw; len(c) > 0 {
config = c
}

basePath := fmt.Sprintf("%s.%s", ViperKeySelfServiceStrategyConfig, "code")
enabledKey := fmt.Sprintf("%s.enabled", basePath)
registrationKey := fmt.Sprintf("%s.registration_enabled", basePath)
loginKey := fmt.Sprintf("%s.login_enabled", basePath)

s := &SelfServiceStrategyCode{
SelfServiceStrategy: &SelfServiceStrategy{
Enabled: pp.Bool(enabledKey),
Config: json.RawMessage(config),
},
RegistrationEnabled: pp.Bool(registrationKey),
LoginEnabled: pp.Bool(loginKey),
}

if !pp.Exists(enabledKey) {
s.RegistrationEnabled = false
s.LoginEnabled = false
s.Enabled = true
}
return s
}

func (p *Config) SecretsDefault(ctx context.Context) [][]byte {
pp := p.GetProvider(ctx)
secrets := pp.Strings(ViperKeySecretsDefault)
@@ -1090,6 +1136,14 @@ func (p *Config) CourierTemplatesVerificationCodeValid(ctx context.Context) *Cou
return p.CourierTemplatesHelper(ctx, ViperKeyCourierTemplatesVerificationCodeValidEmail)
}

func (p *Config) CourierTemplatesLoginCodeValid(ctx context.Context) *CourierEmailTemplate {
return p.CourierTemplatesHelper(ctx, ViperKeyCourierTemplatesLoginCodeValidEmail)
}

func (p *Config) CourierTemplatesRegistrationCodeValid(ctx context.Context) *CourierEmailTemplate {
return p.CourierTemplatesHelper(ctx, ViperKeyCourierTemplatesRegistrationCodeValidEmail)
}

func (p *Config) CourierMessageRetries(ctx context.Context) int {
return p.GetProvider(ctx).IntF(ViperKeyCourierMessageRetries, 5)
}
Loading

0 comments on commit e51d791

Please sign in to comment.