From a07c4a519c3ec7f1c20baa82d34698e6f63d18be Mon Sep 17 00:00:00 2001 From: Cam Otts Date: Wed, 18 Jan 2023 13:05:10 -0600 Subject: [PATCH] initial pass for forgot password --- controller/config.go | 8 +- controller/controller.go | 2 + controller/emailUi/embed.go | 2 +- controller/emailUi/forgotPassword.gohtml | 11 + controller/emailUi/forgotPassword.gotext | 5 + controller/forgetPassword.go | 129 ++++++++++++ controller/forgetPasswordEmail.go | 79 +++++++ controller/store/account.go | 12 ++ controller/store/password_reset_request.go | 44 ++++ .../006_v0_3_0_password_reset_requests.sql | 15 ++ .../006_v0_3_0_password_reset_requests.sql | 15 ++ controller/verifyEmail.go | 3 +- rest_client_zrok/account/account_client.go | 80 +++++++ .../account/forgot_password_parameters.go | 150 +++++++++++++ .../account/forgot_password_responses.go | 140 +++++++++++++ .../account/reset_password_parameters.go | 150 +++++++++++++ .../account/reset_password_responses.go | 197 ++++++++++++++++++ rest_model_zrok/forgot_password_request.go | 50 +++++ rest_model_zrok/reset_password_request.go | 53 +++++ rest_server_zrok/embedded_spec.go | 144 +++++++++++++ .../operations/account/forgot_password.go | 56 +++++ .../account/forgot_password_parameters.go | 76 +++++++ .../account/forgot_password_responses.go | 62 ++++++ .../account/forgot_password_urlbuilder.go | 87 ++++++++ .../operations/account/reset_password.go | 56 +++++ .../account/reset_password_parameters.go | 76 +++++++ .../account/reset_password_responses.go | 87 ++++++++ .../account/reset_password_urlbuilder.go | 87 ++++++++ rest_server_zrok/operations/zrok_api.go | 24 +++ specs/zrok.yml | 48 +++++ ui/src/App.js | 2 + ui/src/api/account.js | 42 ++++ ui/src/api/types.js | 15 ++ .../console/forgotPassword/ForgotPassword.js | 24 +++ .../console/forgotPassword/ResetPassword.js | 90 ++++++++ ui/src/console/forgotPassword/SendRequest.js | 74 +++++++ ui/src/console/login/Login.js | 7 + 37 files changed, 2199 insertions(+), 3 deletions(-) create mode 100644 controller/emailUi/forgotPassword.gohtml create mode 100644 controller/emailUi/forgotPassword.gotext create mode 100644 controller/forgetPassword.go create mode 100644 controller/forgetPasswordEmail.go create mode 100644 controller/store/password_reset_request.go create mode 100644 controller/store/sql/postgresql/006_v0_3_0_password_reset_requests.sql create mode 100644 controller/store/sql/sqlite3/006_v0_3_0_password_reset_requests.sql create mode 100644 rest_client_zrok/account/forgot_password_parameters.go create mode 100644 rest_client_zrok/account/forgot_password_responses.go create mode 100644 rest_client_zrok/account/reset_password_parameters.go create mode 100644 rest_client_zrok/account/reset_password_responses.go create mode 100644 rest_model_zrok/forgot_password_request.go create mode 100644 rest_model_zrok/reset_password_request.go create mode 100644 rest_server_zrok/operations/account/forgot_password.go create mode 100644 rest_server_zrok/operations/account/forgot_password_parameters.go create mode 100644 rest_server_zrok/operations/account/forgot_password_responses.go create mode 100644 rest_server_zrok/operations/account/forgot_password_urlbuilder.go create mode 100644 rest_server_zrok/operations/account/reset_password.go create mode 100644 rest_server_zrok/operations/account/reset_password_parameters.go create mode 100644 rest_server_zrok/operations/account/reset_password_responses.go create mode 100644 rest_server_zrok/operations/account/reset_password_urlbuilder.go create mode 100644 ui/src/console/forgotPassword/ForgotPassword.js create mode 100644 ui/src/console/forgotPassword/ResetPassword.js create mode 100644 ui/src/console/forgotPassword/SendRequest.js diff --git a/controller/config.go b/controller/config.go index 9c3d753f..5a3c8c40 100644 --- a/controller/config.go +++ b/controller/config.go @@ -1,16 +1,18 @@ package controller import ( + "time" + "github.com/michaelquigley/cf" "github.com/openziti/zrok/controller/store" "github.com/pkg/errors" - "time" ) const ConfigVersion = 1 type Config struct { V int + Account *AccountConfig Admin *AdminConfig Endpoint *EndpointConfig Email *EmailConfig @@ -23,6 +25,10 @@ type Config struct { Ziti *ZitiConfig } +type AccountConfig struct { + ForgotPasswordUrlTemplate string +} + type AdminConfig struct { Secrets []string `cf:"+secret"` } diff --git a/controller/controller.go b/controller/controller.go index aad3a900..7fdb9778 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -29,8 +29,10 @@ func Run(inCfg *Config) error { api := operations.NewZrokAPI(swaggerSpec) api.KeyAuth = newZrokAuthenticator(cfg).authenticate api.AccountInviteHandler = newInviteHandler(cfg) + api.AccountForgotPasswordHandler = newForgetPasswordHandler() api.AccountLoginHandler = account.LoginHandlerFunc(loginHandler) api.AccountRegisterHandler = newRegisterHandler() + api.AccountResetPasswordHandler = newResetPasswordHandler() api.AccountVerifyHandler = newVerifyHandler() api.AdminCreateFrontendHandler = newCreateFrontendHandler() api.AdminCreateIdentityHandler = newCreateIdentityHandler() diff --git a/controller/emailUi/embed.go b/controller/emailUi/embed.go index 657e12de..81194fe9 100644 --- a/controller/emailUi/embed.go +++ b/controller/emailUi/embed.go @@ -2,5 +2,5 @@ package emailUi import "embed" -//go:embed verify.gohtml verify.gotext +//go:embed verify.gohtml verify.gotext forgotPassword.gohtml forgotPassword.gotext var FS embed.FS diff --git a/controller/emailUi/forgotPassword.gohtml b/controller/emailUi/forgotPassword.gohtml new file mode 100644 index 00000000..c9de434c --- /dev/null +++ b/controller/emailUi/forgotPassword.gohtml @@ -0,0 +1,11 @@ + + + + + zrok forgot password + + +

We see you requested a forgot password request, {{ .EmailAddress }}!

+

Please click this link to change your zrok account password.

+ + \ No newline at end of file diff --git a/controller/emailUi/forgotPassword.gotext b/controller/emailUi/forgotPassword.gotext new file mode 100644 index 00000000..d1ba3092 --- /dev/null +++ b/controller/emailUi/forgotPassword.gotext @@ -0,0 +1,5 @@ +We see you requested a forgot password request, {{ .EmailAddress }}! + +Please click this link to change your zrok account password: + +{{ .ForgotPasswordUrl }} \ No newline at end of file diff --git a/controller/forgetPassword.go b/controller/forgetPassword.go new file mode 100644 index 00000000..bb396526 --- /dev/null +++ b/controller/forgetPassword.go @@ -0,0 +1,129 @@ +package controller + +import ( + "github.com/go-openapi/runtime/middleware" + "github.com/openziti/zrok/controller/store" + "github.com/openziti/zrok/rest_server_zrok/operations/account" + "github.com/openziti/zrok/util" + "github.com/sirupsen/logrus" +) + +type forgetPasswordHandler struct{} + +func newForgetPasswordHandler() *forgetPasswordHandler { + return &forgetPasswordHandler{} +} + +func (handler *forgetPasswordHandler) Handle(params account.ForgotPasswordParams) middleware.Responder { + if params.Body == nil || params.Body.Email == "" { + logrus.Errorf("missing email") + return account.NewInviteBadRequest() + } + if !util.IsValidEmail(params.Body.Email) { + logrus.Errorf("'%v' is not a valid email address", params.Body.Email) + return account.NewInviteBadRequest() + } + logrus.Infof("received forgot password request for email '%v'", params.Body.Email) + var token string + + tx, err := str.Begin() + if err != nil { + logrus.Error(err) + return account.NewForgotPasswordInternalServerError() + } + defer func() { _ = tx.Rollback() }() + + token, err = createToken() + if err != nil { + logrus.Error(err) + return account.NewForgotPasswordInternalServerError() + } + + acct, err := str.FindAccountWithEmail(params.Body.Email, tx) + if err != nil { + logrus.Infof("no account found for '%v': %v", params.Body.Email, err) + return account.NewForgotPasswordInternalServerError() + } + + prr := &store.PasswordResetRequest{ + Token: token, + AccountId: acct.Id, + } + + if _, err := str.CreatePasswordResetRequest(prr, tx); err != nil { + logrus.Errorf("error creating forgot password request for '%v': %v", params.Body.Email, err) + return account.NewInviteInternalServerError() + } + + if err := tx.Commit(); err != nil { + logrus.Errorf("error committing forgot password request for '%v': %v", params.Body.Email, err) + return account.NewInviteInternalServerError() + } + + if cfg.Email != nil && cfg.Registration != nil && cfg.Account != nil { + if err := sendForgotPasswordEmail(acct.Email, token); err != nil { + logrus.Errorf("error sending forgot password email for '%v': %v", acct.Email, err) + return account.NewForgotPasswordInternalServerError() + } + } else { + logrus.Errorf("'email', 'registration', and 'account' configuration missing; skipping forgot password email") + } + + logrus.Infof("forgot password request for '%v' has token '%v'", params.Body.Email, prr.Token) + + return account.NewForgotPasswordCreated() +} + +type resetPasswordHandler struct{} + +func newResetPasswordHandler() *resetPasswordHandler { + return &resetPasswordHandler{} +} + +func (handler *resetPasswordHandler) Handle(params account.ResetPasswordParams) middleware.Responder { + if params.Body == nil || params.Body.Token == "" || params.Body.Password == "" { + logrus.Error("missing token or password") + return account.NewResetPasswordNotFound() + } + logrus.Infof("received password reset request for token '%v'", params.Body.Token) + + tx, err := str.Begin() + if err != nil { + logrus.Error(err) + return account.NewResetPasswordInternalServerError() + } + defer func() { _ = tx.Rollback() }() + + prr, err := str.FindPasswordResetRequestWithToken(params.Body.Token, tx) + if err != nil { + logrus.Error(err) + return account.NewResetPasswordNotFound() + } + + a, err := str.GetAccount(prr.AccountId, tx) + if err != nil { + logrus.Error(err) + return account.NewResetPasswordNotFound() + } + a.Password = hashPassword(params.Body.Password) + + if _, err := str.UpdateAccount(a, tx); err != nil { + logrus.Error(err) + return account.NewResetPasswordInternalServerError() + } + + if err := str.DeletePasswordResetRequest(prr.Id, tx); err != nil { + logrus.Error(err) + return account.NewResetPasswordInternalServerError() + } + + if err := tx.Commit(); err != nil { + logrus.Error(err) + return account.NewResetPasswordInternalServerError() + } + + logrus.Infof("reset password for '%v'", a.Email) + + return account.NewResetPasswordOK() + +} diff --git a/controller/forgetPasswordEmail.go b/controller/forgetPasswordEmail.go new file mode 100644 index 00000000..fd862de7 --- /dev/null +++ b/controller/forgetPasswordEmail.go @@ -0,0 +1,79 @@ +package controller + +import ( + "bytes" + "fmt" + "html/template" + + "github.com/openziti/zrok/controller/emailUi" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/wneessen/go-mail" +) + +type forgotPasswordEmail struct { + EmailAddress string + ForgotPasswordUrl string +} + +func sendForgotPasswordEmail(emailAddress, token string) error { + emailData := &forgotPasswordEmail{ + EmailAddress: emailAddress, + ForgotPasswordUrl: fmt.Sprintf("%s?token=%s", cfg.Account.ForgotPasswordUrlTemplate, token), + } + + plainBody, err := emailData.mergeTemplate("forgotPassword.gotext") + if err != nil { + return err + } + htmlBody, err := emailData.mergeTemplate("forgotPassword.gohtml") + if err != nil { + return err + } + + msg := mail.NewMsg() + if err := msg.From(cfg.Registration.EmailFrom); err != nil { + return errors.Wrap(err, "failed to set from address in forgot password email") + } + if err := msg.To(emailAddress); err != nil { + return errors.Wrap(err, "failed to set to address in forgot password email") + } + + msg.Subject("zrok Forgot Password") + msg.SetDate() + msg.SetMessageID() + msg.SetBulk() + msg.SetImportance(mail.ImportanceHigh) + msg.SetBodyString(mail.TypeTextPlain, plainBody) + msg.SetBodyString(mail.TypeTextHTML, htmlBody) + + client, err := mail.NewClient(cfg.Email.Host, + mail.WithPort(cfg.Email.Port), + mail.WithSMTPAuth(mail.SMTPAuthPlain), + mail.WithUsername(cfg.Email.Username), + mail.WithPassword(cfg.Email.Password), + mail.WithTLSPolicy(mail.TLSMandatory), + ) + + if err != nil { + return errors.Wrap(err, "error creating forgot password email client") + } + if err := client.DialAndSend(msg); err != nil { + return errors.Wrap(err, "error sending forgot password email") + } + + logrus.Infof("forgot password email sent to '%v'", emailAddress) + return nil +} + +func (fpe forgotPasswordEmail) mergeTemplate(filename string) (string, error) { + t, err := template.ParseFS(emailUi.FS, filename) + if err != nil { + return "", errors.Wrapf(err, "error parsing verification email template '%v'", filename) + } + buf := new(bytes.Buffer) + if err := t.Execute(buf, fpe); err != nil { + return "", errors.Wrapf(err, "error executing verification email template '%v'", filename) + } + return buf.String(), nil +} diff --git a/controller/store/account.go b/controller/store/account.go index 4861c7a0..c9584ffd 100644 --- a/controller/store/account.go +++ b/controller/store/account.go @@ -48,3 +48,15 @@ func (self *Store) FindAccountWithToken(token string, tx *sqlx.Tx) (*Account, er } return a, nil } + +func (self *Store) UpdateAccount(a *Account, tx *sqlx.Tx) (int, error) { + stmt, err := tx.Prepare("update accounts set email=$1, password=$2, token=$3, limitless=$4 where id = $5") + if err != nil { + return 0, errors.Wrap(err, "error preparing accounts update statement") + } + var id int + if _, err := stmt.Exec(a.Email, a.Password, a.Token, a.Limitless, a.Id); err != nil { + return 0, errors.Wrap(err, "error executing accounts update statement") + } + return id, nil +} diff --git a/controller/store/password_reset_request.go b/controller/store/password_reset_request.go new file mode 100644 index 00000000..b4dfb44a --- /dev/null +++ b/controller/store/password_reset_request.go @@ -0,0 +1,44 @@ +package store + +import ( + "github.com/jmoiron/sqlx" + "github.com/pkg/errors" +) + +type PasswordResetRequest struct { + Model + Token string + AccountId int +} + +func (self *Store) CreatePasswordResetRequest(prr *PasswordResetRequest, tx *sqlx.Tx) (int, error) { + stmt, err := tx.Prepare("insert into password_reset_requests (account_id, token) values ($1, $2) ON CONFLICT(account_id) DO UPDATE SET token=$2 returning id") + if err != nil { + return 0, errors.Wrap(err, "error preparing password_reset_requests insert statement") + } + var id int + if err := stmt.QueryRow(prr.AccountId, prr.Token).Scan(&id); err != nil { + return 0, errors.Wrap(err, "error executing password_reset_requests insert statement") + } + return id, nil +} + +func (self *Store) FindPasswordResetRequestWithToken(token string, tx *sqlx.Tx) (*PasswordResetRequest, error) { + prr := &PasswordResetRequest{} + if err := tx.QueryRowx("select * from password_reset_requests where token = $1", token).StructScan(prr); err != nil { + return nil, errors.Wrap(err, "error selecting password_reset_requests by token") + } + return prr, nil +} + +func (self *Store) DeletePasswordResetRequest(id int, tx *sqlx.Tx) error { + stmt, err := tx.Prepare("delete from password_reset_requests where id = $1") + if err != nil { + return errors.Wrap(err, "error preparing password_reset_requests delete statement") + } + _, err = stmt.Exec(id) + if err != nil { + return errors.Wrap(err, "error executing password_reset_requests delete statement") + } + return nil +} diff --git a/controller/store/sql/postgresql/006_v0_3_0_password_reset_requests.sql b/controller/store/sql/postgresql/006_v0_3_0_password_reset_requests.sql new file mode 100644 index 00000000..236741e1 --- /dev/null +++ b/controller/store/sql/postgresql/006_v0_3_0_password_reset_requests.sql @@ -0,0 +1,15 @@ +-- +migrate up + +-- +-- password_reset_requests +--- + +create table password_reset_requests ( + id serial primary key, + token varchar(32) not null unique, + created_at timestamptz not null default(current_timestamp), + updated_at timestamptz not null default(current_timestamp), + account_id integer not null unique constraint fk_accounts_password_reset_requests references accounts on delete cascade, + + constraint chk_token check(token <> '') +); \ No newline at end of file diff --git a/controller/store/sql/sqlite3/006_v0_3_0_password_reset_requests.sql b/controller/store/sql/sqlite3/006_v0_3_0_password_reset_requests.sql new file mode 100644 index 00000000..797b1e51 --- /dev/null +++ b/controller/store/sql/sqlite3/006_v0_3_0_password_reset_requests.sql @@ -0,0 +1,15 @@ +-- +migrate Up + +-- +-- password_reset_requests +--- + +create table password_reset_requests ( + id integer primary key, + token string not null unique, + created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')), + updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')), + account_id integer not null unique constraint fk_accounts_password_reset_requests references accounts on delete cascade, + + constraint chk_token check(token <> '') +); \ No newline at end of file diff --git a/controller/verifyEmail.go b/controller/verifyEmail.go index acaebe80..0334a9dc 100644 --- a/controller/verifyEmail.go +++ b/controller/verifyEmail.go @@ -2,12 +2,13 @@ package controller import ( "bytes" + "html/template" + "github.com/openziti/zrok/build" "github.com/openziti/zrok/controller/emailUi" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/wneessen/go-mail" - "html/template" ) type verificationEmail struct { diff --git a/rest_client_zrok/account/account_client.go b/rest_client_zrok/account/account_client.go index f13b0277..e84f575a 100644 --- a/rest_client_zrok/account/account_client.go +++ b/rest_client_zrok/account/account_client.go @@ -30,17 +30,59 @@ type ClientOption func(*runtime.ClientOperation) // ClientService is the interface for Client methods type ClientService interface { + ForgotPassword(params *ForgotPasswordParams, opts ...ClientOption) (*ForgotPasswordCreated, error) + Invite(params *InviteParams, opts ...ClientOption) (*InviteCreated, error) Login(params *LoginParams, opts ...ClientOption) (*LoginOK, error) Register(params *RegisterParams, opts ...ClientOption) (*RegisterOK, error) + ResetPassword(params *ResetPasswordParams, opts ...ClientOption) (*ResetPasswordOK, error) + Verify(params *VerifyParams, opts ...ClientOption) (*VerifyOK, error) SetTransport(transport runtime.ClientTransport) } +/* +ForgotPassword forgot password API +*/ +func (a *Client) ForgotPassword(params *ForgotPasswordParams, opts ...ClientOption) (*ForgotPasswordCreated, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewForgotPasswordParams() + } + op := &runtime.ClientOperation{ + ID: "forgotPassword", + Method: "POST", + PathPattern: "/forgotPassword", + ProducesMediaTypes: []string{"application/zrok.v1+json"}, + ConsumesMediaTypes: []string{"application/zrok.v1+json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &ForgotPasswordReader{formats: a.formats}, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*ForgotPasswordCreated) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for forgotPassword: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + /* Invite invite API */ @@ -155,6 +197,44 @@ func (a *Client) Register(params *RegisterParams, opts ...ClientOption) (*Regist panic(msg) } +/* +ResetPassword reset password API +*/ +func (a *Client) ResetPassword(params *ResetPasswordParams, opts ...ClientOption) (*ResetPasswordOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewResetPasswordParams() + } + op := &runtime.ClientOperation{ + ID: "resetPassword", + Method: "POST", + PathPattern: "/resetPassword", + ProducesMediaTypes: []string{"application/zrok.v1+json"}, + ConsumesMediaTypes: []string{"application/zrok.v1+json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &ResetPasswordReader{formats: a.formats}, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*ResetPasswordOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for resetPassword: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + /* Verify verify API */ diff --git a/rest_client_zrok/account/forgot_password_parameters.go b/rest_client_zrok/account/forgot_password_parameters.go new file mode 100644 index 00000000..e72f97b2 --- /dev/null +++ b/rest_client_zrok/account/forgot_password_parameters.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// NewForgotPasswordParams creates a new ForgotPasswordParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewForgotPasswordParams() *ForgotPasswordParams { + return &ForgotPasswordParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewForgotPasswordParamsWithTimeout creates a new ForgotPasswordParams object +// with the ability to set a timeout on a request. +func NewForgotPasswordParamsWithTimeout(timeout time.Duration) *ForgotPasswordParams { + return &ForgotPasswordParams{ + timeout: timeout, + } +} + +// NewForgotPasswordParamsWithContext creates a new ForgotPasswordParams object +// with the ability to set a context for a request. +func NewForgotPasswordParamsWithContext(ctx context.Context) *ForgotPasswordParams { + return &ForgotPasswordParams{ + Context: ctx, + } +} + +// NewForgotPasswordParamsWithHTTPClient creates a new ForgotPasswordParams object +// with the ability to set a custom HTTPClient for a request. +func NewForgotPasswordParamsWithHTTPClient(client *http.Client) *ForgotPasswordParams { + return &ForgotPasswordParams{ + HTTPClient: client, + } +} + +/* +ForgotPasswordParams contains all the parameters to send to the API endpoint + + for the forgot password operation. + + Typically these are written to a http.Request. +*/ +type ForgotPasswordParams struct { + + // Body. + Body *rest_model_zrok.ForgotPasswordRequest + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the forgot password params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *ForgotPasswordParams) WithDefaults() *ForgotPasswordParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the forgot password params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *ForgotPasswordParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the forgot password params +func (o *ForgotPasswordParams) WithTimeout(timeout time.Duration) *ForgotPasswordParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the forgot password params +func (o *ForgotPasswordParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the forgot password params +func (o *ForgotPasswordParams) WithContext(ctx context.Context) *ForgotPasswordParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the forgot password params +func (o *ForgotPasswordParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the forgot password params +func (o *ForgotPasswordParams) WithHTTPClient(client *http.Client) *ForgotPasswordParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the forgot password params +func (o *ForgotPasswordParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithBody adds the body to the forgot password params +func (o *ForgotPasswordParams) WithBody(body *rest_model_zrok.ForgotPasswordRequest) *ForgotPasswordParams { + o.SetBody(body) + return o +} + +// SetBody adds the body to the forgot password params +func (o *ForgotPasswordParams) SetBody(body *rest_model_zrok.ForgotPasswordRequest) { + o.Body = body +} + +// WriteToRequest writes these params to a swagger request +func (o *ForgotPasswordParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + if o.Body != nil { + if err := r.SetBodyParam(o.Body); err != nil { + return err + } + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/rest_client_zrok/account/forgot_password_responses.go b/rest_client_zrok/account/forgot_password_responses.go new file mode 100644 index 00000000..5466b428 --- /dev/null +++ b/rest_client_zrok/account/forgot_password_responses.go @@ -0,0 +1,140 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +// ForgotPasswordReader is a Reader for the ForgotPassword structure. +type ForgotPasswordReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *ForgotPasswordReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 201: + result := NewForgotPasswordCreated() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 500: + result := NewForgotPasswordInternalServerError() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + default: + return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + } +} + +// NewForgotPasswordCreated creates a ForgotPasswordCreated with default headers values +func NewForgotPasswordCreated() *ForgotPasswordCreated { + return &ForgotPasswordCreated{} +} + +/* +ForgotPasswordCreated describes a response with status code 201, with default header values. + +forgot password request created +*/ +type ForgotPasswordCreated struct { +} + +// IsSuccess returns true when this forgot password created response has a 2xx status code +func (o *ForgotPasswordCreated) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this forgot password created response has a 3xx status code +func (o *ForgotPasswordCreated) IsRedirect() bool { + return false +} + +// IsClientError returns true when this forgot password created response has a 4xx status code +func (o *ForgotPasswordCreated) IsClientError() bool { + return false +} + +// IsServerError returns true when this forgot password created response has a 5xx status code +func (o *ForgotPasswordCreated) IsServerError() bool { + return false +} + +// IsCode returns true when this forgot password created response a status code equal to that given +func (o *ForgotPasswordCreated) IsCode(code int) bool { + return code == 201 +} + +func (o *ForgotPasswordCreated) Error() string { + return fmt.Sprintf("[POST /forgotPassword][%d] forgotPasswordCreated ", 201) +} + +func (o *ForgotPasswordCreated) String() string { + return fmt.Sprintf("[POST /forgotPassword][%d] forgotPasswordCreated ", 201) +} + +func (o *ForgotPasswordCreated) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + return nil +} + +// NewForgotPasswordInternalServerError creates a ForgotPasswordInternalServerError with default headers values +func NewForgotPasswordInternalServerError() *ForgotPasswordInternalServerError { + return &ForgotPasswordInternalServerError{} +} + +/* +ForgotPasswordInternalServerError describes a response with status code 500, with default header values. + +internal server error +*/ +type ForgotPasswordInternalServerError struct { +} + +// IsSuccess returns true when this forgot password internal server error response has a 2xx status code +func (o *ForgotPasswordInternalServerError) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this forgot password internal server error response has a 3xx status code +func (o *ForgotPasswordInternalServerError) IsRedirect() bool { + return false +} + +// IsClientError returns true when this forgot password internal server error response has a 4xx status code +func (o *ForgotPasswordInternalServerError) IsClientError() bool { + return false +} + +// IsServerError returns true when this forgot password internal server error response has a 5xx status code +func (o *ForgotPasswordInternalServerError) IsServerError() bool { + return true +} + +// IsCode returns true when this forgot password internal server error response a status code equal to that given +func (o *ForgotPasswordInternalServerError) IsCode(code int) bool { + return code == 500 +} + +func (o *ForgotPasswordInternalServerError) Error() string { + return fmt.Sprintf("[POST /forgotPassword][%d] forgotPasswordInternalServerError ", 500) +} + +func (o *ForgotPasswordInternalServerError) String() string { + return fmt.Sprintf("[POST /forgotPassword][%d] forgotPasswordInternalServerError ", 500) +} + +func (o *ForgotPasswordInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + return nil +} diff --git a/rest_client_zrok/account/reset_password_parameters.go b/rest_client_zrok/account/reset_password_parameters.go new file mode 100644 index 00000000..7df57d20 --- /dev/null +++ b/rest_client_zrok/account/reset_password_parameters.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// NewResetPasswordParams creates a new ResetPasswordParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewResetPasswordParams() *ResetPasswordParams { + return &ResetPasswordParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewResetPasswordParamsWithTimeout creates a new ResetPasswordParams object +// with the ability to set a timeout on a request. +func NewResetPasswordParamsWithTimeout(timeout time.Duration) *ResetPasswordParams { + return &ResetPasswordParams{ + timeout: timeout, + } +} + +// NewResetPasswordParamsWithContext creates a new ResetPasswordParams object +// with the ability to set a context for a request. +func NewResetPasswordParamsWithContext(ctx context.Context) *ResetPasswordParams { + return &ResetPasswordParams{ + Context: ctx, + } +} + +// NewResetPasswordParamsWithHTTPClient creates a new ResetPasswordParams object +// with the ability to set a custom HTTPClient for a request. +func NewResetPasswordParamsWithHTTPClient(client *http.Client) *ResetPasswordParams { + return &ResetPasswordParams{ + HTTPClient: client, + } +} + +/* +ResetPasswordParams contains all the parameters to send to the API endpoint + + for the reset password operation. + + Typically these are written to a http.Request. +*/ +type ResetPasswordParams struct { + + // Body. + Body *rest_model_zrok.ResetPasswordRequest + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the reset password params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *ResetPasswordParams) WithDefaults() *ResetPasswordParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the reset password params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *ResetPasswordParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the reset password params +func (o *ResetPasswordParams) WithTimeout(timeout time.Duration) *ResetPasswordParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the reset password params +func (o *ResetPasswordParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the reset password params +func (o *ResetPasswordParams) WithContext(ctx context.Context) *ResetPasswordParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the reset password params +func (o *ResetPasswordParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the reset password params +func (o *ResetPasswordParams) WithHTTPClient(client *http.Client) *ResetPasswordParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the reset password params +func (o *ResetPasswordParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithBody adds the body to the reset password params +func (o *ResetPasswordParams) WithBody(body *rest_model_zrok.ResetPasswordRequest) *ResetPasswordParams { + o.SetBody(body) + return o +} + +// SetBody adds the body to the reset password params +func (o *ResetPasswordParams) SetBody(body *rest_model_zrok.ResetPasswordRequest) { + o.Body = body +} + +// WriteToRequest writes these params to a swagger request +func (o *ResetPasswordParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + if o.Body != nil { + if err := r.SetBodyParam(o.Body); err != nil { + return err + } + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/rest_client_zrok/account/reset_password_responses.go b/rest_client_zrok/account/reset_password_responses.go new file mode 100644 index 00000000..84cbdf90 --- /dev/null +++ b/rest_client_zrok/account/reset_password_responses.go @@ -0,0 +1,197 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +// ResetPasswordReader is a Reader for the ResetPassword structure. +type ResetPasswordReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *ResetPasswordReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewResetPasswordOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 404: + result := NewResetPasswordNotFound() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + case 500: + result := NewResetPasswordInternalServerError() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + default: + return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + } +} + +// NewResetPasswordOK creates a ResetPasswordOK with default headers values +func NewResetPasswordOK() *ResetPasswordOK { + return &ResetPasswordOK{} +} + +/* +ResetPasswordOK describes a response with status code 200, with default header values. + +password reset +*/ +type ResetPasswordOK struct { +} + +// IsSuccess returns true when this reset password o k response has a 2xx status code +func (o *ResetPasswordOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this reset password o k response has a 3xx status code +func (o *ResetPasswordOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this reset password o k response has a 4xx status code +func (o *ResetPasswordOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this reset password o k response has a 5xx status code +func (o *ResetPasswordOK) IsServerError() bool { + return false +} + +// IsCode returns true when this reset password o k response a status code equal to that given +func (o *ResetPasswordOK) IsCode(code int) bool { + return code == 200 +} + +func (o *ResetPasswordOK) Error() string { + return fmt.Sprintf("[POST /resetPassword][%d] resetPasswordOK ", 200) +} + +func (o *ResetPasswordOK) String() string { + return fmt.Sprintf("[POST /resetPassword][%d] resetPasswordOK ", 200) +} + +func (o *ResetPasswordOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + return nil +} + +// NewResetPasswordNotFound creates a ResetPasswordNotFound with default headers values +func NewResetPasswordNotFound() *ResetPasswordNotFound { + return &ResetPasswordNotFound{} +} + +/* +ResetPasswordNotFound describes a response with status code 404, with default header values. + +request not found +*/ +type ResetPasswordNotFound struct { +} + +// IsSuccess returns true when this reset password not found response has a 2xx status code +func (o *ResetPasswordNotFound) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this reset password not found response has a 3xx status code +func (o *ResetPasswordNotFound) IsRedirect() bool { + return false +} + +// IsClientError returns true when this reset password not found response has a 4xx status code +func (o *ResetPasswordNotFound) IsClientError() bool { + return true +} + +// IsServerError returns true when this reset password not found response has a 5xx status code +func (o *ResetPasswordNotFound) IsServerError() bool { + return false +} + +// IsCode returns true when this reset password not found response a status code equal to that given +func (o *ResetPasswordNotFound) IsCode(code int) bool { + return code == 404 +} + +func (o *ResetPasswordNotFound) Error() string { + return fmt.Sprintf("[POST /resetPassword][%d] resetPasswordNotFound ", 404) +} + +func (o *ResetPasswordNotFound) String() string { + return fmt.Sprintf("[POST /resetPassword][%d] resetPasswordNotFound ", 404) +} + +func (o *ResetPasswordNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + return nil +} + +// NewResetPasswordInternalServerError creates a ResetPasswordInternalServerError with default headers values +func NewResetPasswordInternalServerError() *ResetPasswordInternalServerError { + return &ResetPasswordInternalServerError{} +} + +/* +ResetPasswordInternalServerError describes a response with status code 500, with default header values. + +internal server error +*/ +type ResetPasswordInternalServerError struct { +} + +// IsSuccess returns true when this reset password internal server error response has a 2xx status code +func (o *ResetPasswordInternalServerError) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this reset password internal server error response has a 3xx status code +func (o *ResetPasswordInternalServerError) IsRedirect() bool { + return false +} + +// IsClientError returns true when this reset password internal server error response has a 4xx status code +func (o *ResetPasswordInternalServerError) IsClientError() bool { + return false +} + +// IsServerError returns true when this reset password internal server error response has a 5xx status code +func (o *ResetPasswordInternalServerError) IsServerError() bool { + return true +} + +// IsCode returns true when this reset password internal server error response a status code equal to that given +func (o *ResetPasswordInternalServerError) IsCode(code int) bool { + return code == 500 +} + +func (o *ResetPasswordInternalServerError) Error() string { + return fmt.Sprintf("[POST /resetPassword][%d] resetPasswordInternalServerError ", 500) +} + +func (o *ResetPasswordInternalServerError) String() string { + return fmt.Sprintf("[POST /resetPassword][%d] resetPasswordInternalServerError ", 500) +} + +func (o *ResetPasswordInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + return nil +} diff --git a/rest_model_zrok/forgot_password_request.go b/rest_model_zrok/forgot_password_request.go new file mode 100644 index 00000000..b2077e95 --- /dev/null +++ b/rest_model_zrok/forgot_password_request.go @@ -0,0 +1,50 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rest_model_zrok + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ForgotPasswordRequest forgot password request +// +// swagger:model forgotPasswordRequest +type ForgotPasswordRequest struct { + + // email + Email string `json:"email,omitempty"` +} + +// Validate validates this forgot password request +func (m *ForgotPasswordRequest) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this forgot password request based on context it is used +func (m *ForgotPasswordRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ForgotPasswordRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ForgotPasswordRequest) UnmarshalBinary(b []byte) error { + var res ForgotPasswordRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/rest_model_zrok/reset_password_request.go b/rest_model_zrok/reset_password_request.go new file mode 100644 index 00000000..bafb93ca --- /dev/null +++ b/rest_model_zrok/reset_password_request.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rest_model_zrok + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ResetPasswordRequest reset password request +// +// swagger:model resetPasswordRequest +type ResetPasswordRequest struct { + + // password + Password string `json:"password,omitempty"` + + // token + Token string `json:"token,omitempty"` +} + +// Validate validates this reset password request +func (m *ResetPasswordRequest) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this reset password request based on context it is used +func (m *ResetPasswordRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ResetPasswordRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ResetPasswordRequest) UnmarshalBinary(b []byte) error { + var res ResetPasswordRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/rest_server_zrok/embedded_spec.go b/rest_server_zrok/embedded_spec.go index 38df9433..f99f0a8e 100644 --- a/rest_server_zrok/embedded_spec.go +++ b/rest_server_zrok/embedded_spec.go @@ -222,6 +222,31 @@ func init() { } } }, + "/forgotPassword": { + "post": { + "tags": [ + "account" + ], + "operationId": "forgotPassword", + "parameters": [ + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/forgotPasswordRequest" + } + } + ], + "responses": { + "201": { + "description": "forgot password request created" + }, + "500": { + "description": "internal server error" + } + } + } + }, "/frontend": { "post": { "security": [ @@ -553,6 +578,34 @@ func init() { } } }, + "/resetPassword": { + "post": { + "tags": [ + "account" + ], + "operationId": "resetPassword", + "parameters": [ + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/resetPasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "password reset" + }, + "404": { + "description": "request not found" + }, + "500": { + "description": "internal server error" + } + } + } + }, "/share": { "post": { "security": [ @@ -895,6 +948,14 @@ func init() { "errorMessage": { "type": "string" }, + "forgotPasswordRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + } + } + }, "inviteRequest": { "type": "object", "properties": { @@ -999,6 +1060,17 @@ func init() { } } }, + "resetPasswordRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "token": { + "type": "string" + } + } + }, "share": { "type": "object", "properties": { @@ -1393,6 +1465,31 @@ func init() { } } }, + "/forgotPassword": { + "post": { + "tags": [ + "account" + ], + "operationId": "forgotPassword", + "parameters": [ + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/forgotPasswordRequest" + } + } + ], + "responses": { + "201": { + "description": "forgot password request created" + }, + "500": { + "description": "internal server error" + } + } + } + }, "/frontend": { "post": { "security": [ @@ -1724,6 +1821,34 @@ func init() { } } }, + "/resetPassword": { + "post": { + "tags": [ + "account" + ], + "operationId": "resetPassword", + "parameters": [ + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/resetPasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "password reset" + }, + "404": { + "description": "request not found" + }, + "500": { + "description": "internal server error" + } + } + } + }, "/share": { "post": { "security": [ @@ -2066,6 +2191,14 @@ func init() { "errorMessage": { "type": "string" }, + "forgotPasswordRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + } + } + }, "inviteRequest": { "type": "object", "properties": { @@ -2170,6 +2303,17 @@ func init() { } } }, + "resetPasswordRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "token": { + "type": "string" + } + } + }, "share": { "type": "object", "properties": { diff --git a/rest_server_zrok/operations/account/forgot_password.go b/rest_server_zrok/operations/account/forgot_password.go new file mode 100644 index 00000000..a20f7942 --- /dev/null +++ b/rest_server_zrok/operations/account/forgot_password.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// ForgotPasswordHandlerFunc turns a function with the right signature into a forgot password handler +type ForgotPasswordHandlerFunc func(ForgotPasswordParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn ForgotPasswordHandlerFunc) Handle(params ForgotPasswordParams) middleware.Responder { + return fn(params) +} + +// ForgotPasswordHandler interface for that can handle valid forgot password params +type ForgotPasswordHandler interface { + Handle(ForgotPasswordParams) middleware.Responder +} + +// NewForgotPassword creates a new http.Handler for the forgot password operation +func NewForgotPassword(ctx *middleware.Context, handler ForgotPasswordHandler) *ForgotPassword { + return &ForgotPassword{Context: ctx, Handler: handler} +} + +/* + ForgotPassword swagger:route POST /forgotPassword account forgotPassword + +ForgotPassword forgot password API +*/ +type ForgotPassword struct { + Context *middleware.Context + Handler ForgotPasswordHandler +} + +func (o *ForgotPassword) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewForgotPasswordParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/rest_server_zrok/operations/account/forgot_password_parameters.go b/rest_server_zrok/operations/account/forgot_password_parameters.go new file mode 100644 index 00000000..f8aa948f --- /dev/null +++ b/rest_server_zrok/operations/account/forgot_password_parameters.go @@ -0,0 +1,76 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/validate" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// NewForgotPasswordParams creates a new ForgotPasswordParams object +// +// There are no default values defined in the spec. +func NewForgotPasswordParams() ForgotPasswordParams { + + return ForgotPasswordParams{} +} + +// ForgotPasswordParams contains all the bound params for the forgot password operation +// typically these are obtained from a http.Request +// +// swagger:parameters forgotPassword +type ForgotPasswordParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: body + */ + Body *rest_model_zrok.ForgotPasswordRequest +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewForgotPasswordParams() beforehand. +func (o *ForgotPasswordParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body rest_model_zrok.ForgotPasswordRequest + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("body", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/rest_server_zrok/operations/account/forgot_password_responses.go b/rest_server_zrok/operations/account/forgot_password_responses.go new file mode 100644 index 00000000..fbbb2edb --- /dev/null +++ b/rest_server_zrok/operations/account/forgot_password_responses.go @@ -0,0 +1,62 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// ForgotPasswordCreatedCode is the HTTP code returned for type ForgotPasswordCreated +const ForgotPasswordCreatedCode int = 201 + +/* +ForgotPasswordCreated forgot password request created + +swagger:response forgotPasswordCreated +*/ +type ForgotPasswordCreated struct { +} + +// NewForgotPasswordCreated creates ForgotPasswordCreated with default headers values +func NewForgotPasswordCreated() *ForgotPasswordCreated { + + return &ForgotPasswordCreated{} +} + +// WriteResponse to the client +func (o *ForgotPasswordCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(201) +} + +// ForgotPasswordInternalServerErrorCode is the HTTP code returned for type ForgotPasswordInternalServerError +const ForgotPasswordInternalServerErrorCode int = 500 + +/* +ForgotPasswordInternalServerError internal server error + +swagger:response forgotPasswordInternalServerError +*/ +type ForgotPasswordInternalServerError struct { +} + +// NewForgotPasswordInternalServerError creates ForgotPasswordInternalServerError with default headers values +func NewForgotPasswordInternalServerError() *ForgotPasswordInternalServerError { + + return &ForgotPasswordInternalServerError{} +} + +// WriteResponse to the client +func (o *ForgotPasswordInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(500) +} diff --git a/rest_server_zrok/operations/account/forgot_password_urlbuilder.go b/rest_server_zrok/operations/account/forgot_password_urlbuilder.go new file mode 100644 index 00000000..29621c98 --- /dev/null +++ b/rest_server_zrok/operations/account/forgot_password_urlbuilder.go @@ -0,0 +1,87 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" +) + +// ForgotPasswordURL generates an URL for the forgot password operation +type ForgotPasswordURL struct { + _basePath string +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *ForgotPasswordURL) WithBasePath(bp string) *ForgotPasswordURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *ForgotPasswordURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *ForgotPasswordURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/forgotPassword" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *ForgotPasswordURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *ForgotPasswordURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *ForgotPasswordURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on ForgotPasswordURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on ForgotPasswordURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *ForgotPasswordURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/rest_server_zrok/operations/account/reset_password.go b/rest_server_zrok/operations/account/reset_password.go new file mode 100644 index 00000000..41d4b57e --- /dev/null +++ b/rest_server_zrok/operations/account/reset_password.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// ResetPasswordHandlerFunc turns a function with the right signature into a reset password handler +type ResetPasswordHandlerFunc func(ResetPasswordParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn ResetPasswordHandlerFunc) Handle(params ResetPasswordParams) middleware.Responder { + return fn(params) +} + +// ResetPasswordHandler interface for that can handle valid reset password params +type ResetPasswordHandler interface { + Handle(ResetPasswordParams) middleware.Responder +} + +// NewResetPassword creates a new http.Handler for the reset password operation +func NewResetPassword(ctx *middleware.Context, handler ResetPasswordHandler) *ResetPassword { + return &ResetPassword{Context: ctx, Handler: handler} +} + +/* + ResetPassword swagger:route POST /resetPassword account resetPassword + +ResetPassword reset password API +*/ +type ResetPassword struct { + Context *middleware.Context + Handler ResetPasswordHandler +} + +func (o *ResetPassword) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewResetPasswordParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/rest_server_zrok/operations/account/reset_password_parameters.go b/rest_server_zrok/operations/account/reset_password_parameters.go new file mode 100644 index 00000000..71e4137b --- /dev/null +++ b/rest_server_zrok/operations/account/reset_password_parameters.go @@ -0,0 +1,76 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/validate" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// NewResetPasswordParams creates a new ResetPasswordParams object +// +// There are no default values defined in the spec. +func NewResetPasswordParams() ResetPasswordParams { + + return ResetPasswordParams{} +} + +// ResetPasswordParams contains all the bound params for the reset password operation +// typically these are obtained from a http.Request +// +// swagger:parameters resetPassword +type ResetPasswordParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: body + */ + Body *rest_model_zrok.ResetPasswordRequest +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewResetPasswordParams() beforehand. +func (o *ResetPasswordParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body rest_model_zrok.ResetPasswordRequest + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("body", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/rest_server_zrok/operations/account/reset_password_responses.go b/rest_server_zrok/operations/account/reset_password_responses.go new file mode 100644 index 00000000..a23e4181 --- /dev/null +++ b/rest_server_zrok/operations/account/reset_password_responses.go @@ -0,0 +1,87 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// ResetPasswordOKCode is the HTTP code returned for type ResetPasswordOK +const ResetPasswordOKCode int = 200 + +/* +ResetPasswordOK password reset + +swagger:response resetPasswordOK +*/ +type ResetPasswordOK struct { +} + +// NewResetPasswordOK creates ResetPasswordOK with default headers values +func NewResetPasswordOK() *ResetPasswordOK { + + return &ResetPasswordOK{} +} + +// WriteResponse to the client +func (o *ResetPasswordOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// ResetPasswordNotFoundCode is the HTTP code returned for type ResetPasswordNotFound +const ResetPasswordNotFoundCode int = 404 + +/* +ResetPasswordNotFound request not found + +swagger:response resetPasswordNotFound +*/ +type ResetPasswordNotFound struct { +} + +// NewResetPasswordNotFound creates ResetPasswordNotFound with default headers values +func NewResetPasswordNotFound() *ResetPasswordNotFound { + + return &ResetPasswordNotFound{} +} + +// WriteResponse to the client +func (o *ResetPasswordNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(404) +} + +// ResetPasswordInternalServerErrorCode is the HTTP code returned for type ResetPasswordInternalServerError +const ResetPasswordInternalServerErrorCode int = 500 + +/* +ResetPasswordInternalServerError internal server error + +swagger:response resetPasswordInternalServerError +*/ +type ResetPasswordInternalServerError struct { +} + +// NewResetPasswordInternalServerError creates ResetPasswordInternalServerError with default headers values +func NewResetPasswordInternalServerError() *ResetPasswordInternalServerError { + + return &ResetPasswordInternalServerError{} +} + +// WriteResponse to the client +func (o *ResetPasswordInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(500) +} diff --git a/rest_server_zrok/operations/account/reset_password_urlbuilder.go b/rest_server_zrok/operations/account/reset_password_urlbuilder.go new file mode 100644 index 00000000..85214a77 --- /dev/null +++ b/rest_server_zrok/operations/account/reset_password_urlbuilder.go @@ -0,0 +1,87 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package account + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" +) + +// ResetPasswordURL generates an URL for the reset password operation +type ResetPasswordURL struct { + _basePath string +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *ResetPasswordURL) WithBasePath(bp string) *ResetPasswordURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *ResetPasswordURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *ResetPasswordURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/resetPassword" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *ResetPasswordURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *ResetPasswordURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *ResetPasswordURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on ResetPasswordURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on ResetPasswordURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *ResetPasswordURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/rest_server_zrok/operations/zrok_api.go b/rest_server_zrok/operations/zrok_api.go index 92ecc1cf..41e23e7b 100644 --- a/rest_server_zrok/operations/zrok_api.go +++ b/rest_server_zrok/operations/zrok_api.go @@ -67,6 +67,9 @@ func NewZrokAPI(spec *loads.Document) *ZrokAPI { EnvironmentEnableHandler: environment.EnableHandlerFunc(func(params environment.EnableParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation environment.Enable has not yet been implemented") }), + AccountForgotPasswordHandler: account.ForgotPasswordHandlerFunc(func(params account.ForgotPasswordParams) middleware.Responder { + return middleware.NotImplemented("operation account.ForgotPassword has not yet been implemented") + }), MetadataGetEnvironmentDetailHandler: metadata.GetEnvironmentDetailHandlerFunc(func(params metadata.GetEnvironmentDetailParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation metadata.GetEnvironmentDetail has not yet been implemented") }), @@ -91,6 +94,9 @@ func NewZrokAPI(spec *loads.Document) *ZrokAPI { AccountRegisterHandler: account.RegisterHandlerFunc(func(params account.RegisterParams) middleware.Responder { return middleware.NotImplemented("operation account.Register has not yet been implemented") }), + AccountResetPasswordHandler: account.ResetPasswordHandlerFunc(func(params account.ResetPasswordParams) middleware.Responder { + return middleware.NotImplemented("operation account.ResetPassword has not yet been implemented") + }), ShareShareHandler: share.ShareHandlerFunc(func(params share.ShareParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation share.Share has not yet been implemented") }), @@ -174,6 +180,8 @@ type ZrokAPI struct { EnvironmentDisableHandler environment.DisableHandler // EnvironmentEnableHandler sets the operation handler for the enable operation EnvironmentEnableHandler environment.EnableHandler + // AccountForgotPasswordHandler sets the operation handler for the forgot password operation + AccountForgotPasswordHandler account.ForgotPasswordHandler // MetadataGetEnvironmentDetailHandler sets the operation handler for the get environment detail operation MetadataGetEnvironmentDetailHandler metadata.GetEnvironmentDetailHandler // MetadataGetShareDetailHandler sets the operation handler for the get share detail operation @@ -190,6 +198,8 @@ type ZrokAPI struct { MetadataOverviewHandler metadata.OverviewHandler // AccountRegisterHandler sets the operation handler for the register operation AccountRegisterHandler account.RegisterHandler + // AccountResetPasswordHandler sets the operation handler for the reset password operation + AccountResetPasswordHandler account.ResetPasswordHandler // ShareShareHandler sets the operation handler for the share operation ShareShareHandler share.ShareHandler // ShareUnaccessHandler sets the operation handler for the unaccess operation @@ -303,6 +313,9 @@ func (o *ZrokAPI) Validate() error { if o.EnvironmentEnableHandler == nil { unregistered = append(unregistered, "environment.EnableHandler") } + if o.AccountForgotPasswordHandler == nil { + unregistered = append(unregistered, "account.ForgotPasswordHandler") + } if o.MetadataGetEnvironmentDetailHandler == nil { unregistered = append(unregistered, "metadata.GetEnvironmentDetailHandler") } @@ -327,6 +340,9 @@ func (o *ZrokAPI) Validate() error { if o.AccountRegisterHandler == nil { unregistered = append(unregistered, "account.RegisterHandler") } + if o.AccountResetPasswordHandler == nil { + unregistered = append(unregistered, "account.ResetPasswordHandler") + } if o.ShareShareHandler == nil { unregistered = append(unregistered, "share.ShareHandler") } @@ -471,6 +487,10 @@ func (o *ZrokAPI) initHandlerCache() { o.handlers["POST"] = make(map[string]http.Handler) } o.handlers["POST"]["/enable"] = environment.NewEnable(o.context, o.EnvironmentEnableHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/forgotPassword"] = account.NewForgotPassword(o.context, o.AccountForgotPasswordHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } @@ -506,6 +526,10 @@ func (o *ZrokAPI) initHandlerCache() { if o.handlers["POST"] == nil { o.handlers["POST"] = make(map[string]http.Handler) } + o.handlers["POST"]["/resetPassword"] = account.NewResetPassword(o.context, o.AccountResetPasswordHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } o.handlers["POST"]["/share"] = share.NewShare(o.context, o.ShareShareHandler) if o.handlers["DELETE"] == nil { o.handlers["DELETE"] = make(map[string]http.Handler) diff --git a/specs/zrok.yml b/specs/zrok.yml index d24e24cb..417cbb09 100644 --- a/specs/zrok.yml +++ b/specs/zrok.yml @@ -15,6 +15,22 @@ paths: # # account # + /forgotPassword: + post: + tags: + - account + operationId: forgotPassword + parameters: + - name: body + in: body + schema: + $ref: "#/definitions/forgotPasswordRequest" + responses: + 201: + description: forgot password request created + 500: + description: internal server error + /invite: post: tags: @@ -71,6 +87,24 @@ paths: 500: description: internal server error + /resetPassword: + post: + tags: + - account + operationId: resetPassword + parameters: + - name: body + in: body + schema: + $ref: "#/definitions/resetPasswordRequest" + responses: + 200: + description: password reset + 404: + description: request not found + 500: + description: internal server error + /verify: post: tags: @@ -574,6 +608,12 @@ definitions: errorMessage: type: string + forgotPasswordRequest: + type: object + properties: + email: + type: string + inviteTokenGenerateRequest: type: object properties: @@ -650,6 +690,14 @@ definitions: token: type: string + resetPasswordRequest: + type: object + properties: + token: + type: string + password: + type: string + share: type: object properties: diff --git a/ui/src/App.js b/ui/src/App.js index ae54d158..66fe3289 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -3,6 +3,7 @@ import Register from "./register/Register"; import Console from "./console/Console"; import {useEffect, useState} from "react"; import Login from "./console/login/Login"; +import ForgotPassword from "./console/forgotPassword/ForgotPassword" const App = () => { const [user, setUser] = useState(); @@ -27,6 +28,7 @@ const App = () => { } /> + }/> ); diff --git a/ui/src/api/account.js b/ui/src/api/account.js index 18d604d4..7fe1c386 100644 --- a/ui/src/api/account.js +++ b/ui/src/api/account.js @@ -2,6 +2,21 @@ // Auto-generated, edits will be overwritten import * as gateway from './gateway' +/** + * @param {object} options Optional options + * @param {module:types.forgotPasswordRequest} [options.body] + * @return {Promise} forgot password request created + */ +export function forgotPassword(options) { + if (!options) options = {} + const parameters = { + body: { + body: options.body + } + } + return gateway.request(forgotPasswordOperation, parameters) +} + /** * @param {object} options Optional options * @param {module:types.inviteRequest} [options.body] @@ -47,6 +62,21 @@ export function register(options) { return gateway.request(registerOperation, parameters) } +/** + * @param {object} options Optional options + * @param {module:types.resetPasswordRequest} [options.body] + * @return {Promise} password reset + */ +export function resetPassword(options) { + if (!options) options = {} + const parameters = { + body: { + body: options.body + } + } + return gateway.request(resetPasswordOperation, parameters) +} + /** * @param {object} options Optional options * @param {module:types.verifyRequest} [options.body] @@ -62,6 +92,12 @@ export function verify(options) { return gateway.request(verifyOperation, parameters) } +const forgotPasswordOperation = { + path: '/forgotPassword', + contentTypes: ['application/zrok.v1+json'], + method: 'post' +} + const inviteOperation = { path: '/invite', contentTypes: ['application/zrok.v1+json'], @@ -80,6 +116,12 @@ const registerOperation = { method: 'post' } +const resetPasswordOperation = { + path: '/resetPassword', + contentTypes: ['application/zrok.v1+json'], + method: 'post' +} + const verifyOperation = { path: '/verify', contentTypes: ['application/zrok.v1+json'], diff --git a/ui/src/api/types.js b/ui/src/api/types.js index 6a4c15f0..853724fc 100644 --- a/ui/src/api/types.js +++ b/ui/src/api/types.js @@ -91,6 +91,13 @@ * @property {module:types.shares} shares */ +/** + * @typedef forgotPasswordRequest + * @memberof module:types + * + * @property {string} email + */ + /** * @typedef inviteTokenGenerateRequest * @memberof module:types @@ -152,6 +159,14 @@ * @property {string} token */ +/** + * @typedef resetPasswordRequest + * @memberof module:types + * + * @property {string} token + * @property {string} password + */ + /** * @typedef share * @memberof module:types diff --git a/ui/src/console/forgotPassword/ForgotPassword.js b/ui/src/console/forgotPassword/ForgotPassword.js new file mode 100644 index 00000000..d71c9ce4 --- /dev/null +++ b/ui/src/console/forgotPassword/ForgotPassword.js @@ -0,0 +1,24 @@ +import {useState} from "react"; +import * as account from '../../api/account'; +import {Button, Container, Form, Row} from "react-bootstrap"; +import { useLocation } from "react-router-dom"; +import SendRequest from "./SendRequest" +import ResetPassword from "./ResetPassword"; + +const ForgotPassword = (props) => { + const { search } = useLocation(); + const token = new URLSearchParams(search).get("token") + console.log(token) + let forgetPasswordComponent = undefined + if (token) { + forgetPasswordComponent = + } else { + forgetPasswordComponent = + } + + return ( +
{forgetPasswordComponent}
+ ) +} + +export default ForgotPassword; \ No newline at end of file diff --git a/ui/src/console/forgotPassword/ResetPassword.js b/ui/src/console/forgotPassword/ResetPassword.js new file mode 100644 index 00000000..d99b3b0e --- /dev/null +++ b/ui/src/console/forgotPassword/ResetPassword.js @@ -0,0 +1,90 @@ +import {useState} from "react"; +import * as account from '../../api/account'; +import {Button, Container, Form, Row} from "react-bootstrap"; +import { Navigate } from "react-router-dom"; + +const ResetPassword = (props) => { + const [password, setPassword] = useState(''); + const [confirm, setConfirm] = useState(''); + const [message, setMessage] = useState(); + const [complete, setComplete] = useState(false); + + const passwordMismatchMessage =

Entered passwords do not match!

+ const passwordTooShortMessage =

Entered password too short! (4 characters, minimum)

+ + const errorMessage =

Reset Password Failed!

; + + const handleSubmit = async e => { + e.preventDefault(); + if(confirm.length < 4) { + setMessage(passwordTooShortMessage); + return; + } + if(confirm !== password) { + setMessage(passwordMismatchMessage); + return; + } + account.resetPassword({body: {"token": props.token, "password": password}}) + .then(resp => { + if(!resp.error) { + setMessage(undefined); + setComplete(true); + } else { + setMessage(errorMessage) + } + }) + .catch(resp => { + console.log("reset password failed", resp); + setMessage(errorMessage); + }) + } + + if(!complete) { + return ( + + + ziggy + + +

Reset Password

+
+ + + +
+ + { setMessage(null); setPassword(t.target.value); }} + value={password} + /> + + + + { setMessage(null); setConfirm(t.target.value); }} + value={confirm} + /> + + + +
+
+ + {message} + +
+
+
+ ) + } + + return ( + + ) +} + +export default ResetPassword; diff --git a/ui/src/console/forgotPassword/SendRequest.js b/ui/src/console/forgotPassword/SendRequest.js new file mode 100644 index 00000000..b6e44d16 --- /dev/null +++ b/ui/src/console/forgotPassword/SendRequest.js @@ -0,0 +1,74 @@ +import { useState } from "react"; +import * as account from '../../api/account'; +import { Button, Container, Form, Row } from "react-bootstrap"; + +const SendRequest = (props) => { + const [email, setEmail] = useState(''); + const [message, setMessage] = useState(); + const [complete, setComplete] = useState(false); + + + const errorMessage =

Forgot Password Failed!

; + + const handleSubmit = async e => { + e.preventDefault(); + console.log(email); + + account.forgotPassword({ body: { "email": email } }) + .then(resp => { + if (!resp.error) { + console.log("Make landing page to expect and email or something similar") + setComplete(true) + } else { + console.log('forgot password failed') + setMessage(errorMessage); + } + }) + .catch((resp) => { + console.log('forgot password failed', resp) + setMessage(errorMessage) + }) + }; + + if (!complete) { + return ( + + + ziggy + + +

zrok

+
+ +

Forgot Password

+
+ + + +
+ + { setMessage(null); setEmail(t.target.value); }} + value={email} + /> + + + +
+
+ + {message} + +
+
+
+ ) + } + return ( +
Make landing page to expect an email or something similar
+ ) +} + +export default SendRequest; \ No newline at end of file diff --git a/ui/src/console/login/Login.js b/ui/src/console/login/Login.js index 08ffd522..385033f4 100644 --- a/ui/src/console/login/Login.js +++ b/ui/src/console/login/Login.js @@ -1,6 +1,7 @@ import {useState} from "react"; import * as account from '../../api/account'; import {Button, Container, Form, Row} from "react-bootstrap"; +import { Link } from "react-router-dom"; const Login = (props) => { const [email, setEmail] = useState(''); @@ -65,6 +66,12 @@ const Login = (props) => { /> +
+ + Forgot Password? + +
+