Skip to content
This repository has been archived by the owner on Aug 16, 2022. It is now read-only.

refactor: signup #65

Merged
merged 25 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/goccy/go-yaml v1.9.2
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/iancoleman/strcase v0.1.3
github.com/idubinskiy/schematyper v0.0.0-20190118213059-f71b40dac30d
Expand All @@ -22,6 +23,7 @@ require (
github.com/kennygrant/sanitize v1.2.4
github.com/labstack/echo/v4 v4.2.1
github.com/labstack/gommon v0.3.0
github.com/matthewhartstonge/argon2 v0.1.5
github.com/mitchellh/mapstructure v1.4.2
github.com/oklog/ulid v1.3.1
github.com/paulmach/go.geojson v1.4.0
Expand Down Expand Up @@ -66,7 +68,6 @@ require (
github.com/golang/snappy v0.0.3 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
github.com/gorilla/schema v1.2.0 // indirect
Expand Down Expand Up @@ -95,13 +96,13 @@ require (
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/mod v0.5.0 // indirect
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 // indirect
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
13 changes: 8 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/matthewhartstonge/argon2 v0.1.5 h1:vkb9Z/AsIiKT8ko8Bx9jOPbgh0skcrBQVaniYJ61F+w=
github.com/matthewhartstonge/argon2 v0.1.5/go.mod h1:6W3fFh3ekKV+VZvOqjc15r4Od36RRxpBtQO5RWE0ef4=
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
Expand Down Expand Up @@ -559,8 +561,9 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down Expand Up @@ -722,11 +725,11 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
6 changes: 3 additions & 3 deletions internal/adapter/gql/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions internal/adapter/gql/resolver_mutation_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ func (r *mutationResolver) Signup(ctx context.Context, input gqlmodel.SignupInpu
if input.Secret != nil {
secret = *input.Secret
}

sub := getSub(ctx)
u, team, err := r.usecases.User.Signup(ctx, interfaces.SignupParam{
Sub: getSub(ctx),
Sub: &sub,
Lang: input.Lang,
Theme: gqlmodel.ToTheme(input.Theme),
UserID: id.UserIDFromRefID(input.UserID),
TeamID: id.TeamIDFromRefID(input.TeamID),
Secret: secret,
Secret: &secret,
})
if err != nil {
return nil, err
Expand Down
48 changes: 41 additions & 7 deletions internal/adapter/http/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ func NewUserController(usecase interfaces.User) *UserController {
}
}

type PasswordResetInput struct {
Email string `json:"email"`
Token string `json:"token"`
Password string `json:"password"`
}

type SignupInput struct {
Sub *string `json:"sub"`
Secret *string `json:"secret"`
UserID *id.UserID `json:"userId"`
TeamID *id.TeamID `json:"teamId"`
Name *string `json:"username"`
Email *string `json:"email"`
Password *string `json:"password"`
}

type CreateVerificationInput struct {
Email string `json:"email"`
}
Expand All @@ -33,24 +49,27 @@ type CreateUserInput struct {
TeamID *id.TeamID `json:"teamId"`
}

type CreateUserOutput struct {
type SignupOutput struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}

func (c *UserController) CreateUser(ctx context.Context, input CreateUserInput) (interface{}, error) {
func (c *UserController) Signup(ctx context.Context, input SignupInput) (interface{}, error) {
u, _, err := c.usecase.Signup(ctx, interfaces.SignupParam{
Sub: input.Sub,
Secret: input.Secret,
UserID: input.UserID,
TeamID: input.TeamID,
Sub: input.Sub,
Secret: input.Secret,
UserID: input.UserID,
TeamID: input.TeamID,
Name: input.Name,
Email: input.Email,
Password: input.Password,
})
if err != nil {
return nil, err
}

return CreateUserOutput{
return SignupOutput{
ID: u.ID().String(),
Name: u.Name(),
Email: u.Email(),
Expand All @@ -74,3 +93,18 @@ func (c *UserController) VerifyUser(ctx context.Context, code string) (interface
Verified: u.Verification().IsVerified(),
}, nil
}

func (c *UserController) StartPasswordReset(ctx context.Context, input PasswordResetInput) error {
err := c.usecase.StartPasswordReset(ctx, input.Email)
if err != nil {
return err
}

// TODO: send password reset link via email

return nil
}

func (c *UserController) PasswordReset(ctx context.Context, input PasswordResetInput) error {
return c.usecase.PasswordReset(ctx, input.Password, input.Token)
}
27 changes: 25 additions & 2 deletions internal/app/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,42 @@ func publicAPI(
})

r.POST("/signup", func(c echo.Context) error {
var inp http1.CreateUserInput
var inp http1.SignupInput
if err := c.Bind(&inp); err != nil {
return &echo.HTTPError{Code: http.StatusBadRequest, Message: fmt.Errorf("failed to parse request body: %w", err)}
}

output, err := controller.CreateUser(c.Request().Context(), inp)
output, err := controller.Signup(c.Request().Context(), inp)
if err != nil {
return err
}

return c.JSON(http.StatusOK, output)
})

r.POST("/password-reset", func(c echo.Context) error {
var inp http1.PasswordResetInput
if err := c.Bind(&inp); err != nil {
return err
}

if len(inp.Email) > 0 {
if err := controller.StartPasswordReset(c.Request().Context(), inp); err != nil {
return err
}
return c.JSON(http.StatusOK, true)
}

if len(inp.Token) > 0 && len(inp.Password) > 0 {
if err := controller.PasswordReset(c.Request().Context(), inp); err != nil {
return err
}
return c.JSON(http.StatusOK, true)
}

return &echo.HTTPError{Code: http.StatusBadRequest, Message: "Bad reset password request"}
})

r.POST("/signup/verify", func(c echo.Context) error {
var inp http1.CreateVerificationInput
if err := c.Bind(&inp); err != nil {
Expand Down
18 changes: 18 additions & 0 deletions internal/infrastructure/memory/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ func (r *User) FindByAuth0Sub(ctx context.Context, auth0sub string) (*user.User,
return nil, rerror.ErrNotFound
}

func (r *User) FindByPasswordResetRequest(ctx context.Context, token string) (*user.User, error) {
r.lock.Lock()
defer r.lock.Unlock()

if token == "" {
return nil, rerror.ErrInvalidParams
}

for _, u := range r.data {
pwdReq := u.PasswordReset()
if pwdReq != nil && pwdReq.Token == token {
return &u, nil
}
}

return nil, rerror.ErrNotFound
}

func (r *User) FindByEmail(ctx context.Context, email string) (*user.User, error) {
r.lock.Lock()
defer r.lock.Unlock()
Expand Down
69 changes: 50 additions & 19 deletions internal/infrastructure/mongo/mongodoc/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,23 @@ import (
user1 "github.com/reearth/reearth-backend/pkg/user"
)

type PasswordResetDocument struct {
Token string
CreatedAt time.Time
}

type UserDocument struct {
ID string
Name string
Email string
Auth0Sub string
Auth0SubList []string
Team string
Lang string
Theme string
Verification *UserVerificationDoc
ID string
Name string
Email string
Auth0Sub string
Auth0SubList []string
Team string
Lang string
Theme string
Password []byte
PasswordReset *PasswordResetDocument
Verification *UserVerificationDoc
}

type UserVerificationDoc struct {
Expand Down Expand Up @@ -64,16 +71,27 @@ func NewUser(user *user1.User) (*UserDocument, string) {
Verified: user.Verification().IsVerified(),
}
}
pwdReset := user.PasswordReset()

var pwdResetDoc *PasswordResetDocument
if pwdReset != nil {
pwdResetDoc = &PasswordResetDocument{
Token: pwdReset.Token,
CreatedAt: pwdReset.CreatedAt,
}
}

return &UserDocument{
ID: id,
Name: user.Name(),
Email: user.Email(),
Auth0SubList: authsdoc,
Team: user.Team().String(),
Lang: user.Lang().String(),
Theme: string(user.Theme()),
Verification: v,
ID: id,
Name: user.Name(),
Email: user.Email(),
Auth0SubList: authsdoc,
Team: user.Team().String(),
Lang: user.Lang().String(),
Theme: string(user.Theme()),
Verification: v,
Password: user.Password(),
PasswordReset: pwdResetDoc,
}, id
}

Expand All @@ -98,18 +116,31 @@ func (d *UserDocument) Model() (*user1.User, error) {
v = user.VerificationFrom(d.Verification.Code, d.Verification.Expiration, d.Verification.Verified)
}

user, err := user1.New().
u, err := user1.New().
ID(uid).
Name(d.Name).
Email(d.Email).
Auths(auths).
Team(tid).
LangFrom(d.Lang).
Verification(v).
Password(d.Password).
PasswordReset(d.PasswordReset.Model()).
Theme(user.Theme(d.Theme)).
Build()

if err != nil {
return nil, err
}
return user, nil
return u, nil
}

func (d *PasswordResetDocument) Model() *user1.PasswordReset {
if d == nil {
return nil
}
return &user1.PasswordReset{
Token: d.Token,
CreatedAt: d.CreatedAt,
}
}
7 changes: 7 additions & 0 deletions internal/infrastructure/mongo/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ func (r *userRepo) FindByVerification(ctx context.Context, code string) (*user.U
return r.findOne(ctx, filter)
}

func (r *userRepo) FindByPasswordResetRequest(ctx context.Context, pwdResetToken string) (*user.User, error) {
filter := bson.D{
{Key: "passwordreset.token", Value: pwdResetToken},
}
return r.findOne(ctx, filter)
}

func (r *userRepo) Save(ctx context.Context, user *user.User) error {
doc, id := mongodoc.NewUser(user)
return r.client.SaveOne(ctx, id, doc)
Expand Down
Loading