3
0
Files
corteza/system/rest/auth_internal.go
2020-11-04 14:18:33 +01:00

153 lines
4.6 KiB
Go

package rest
import (
"context"
"github.com/cortezaproject/corteza-server/pkg/auth"
"github.com/cortezaproject/corteza-server/pkg/payload"
"github.com/cortezaproject/corteza-server/pkg/payload/outgoing"
"github.com/cortezaproject/corteza-server/system/rest/request"
"github.com/cortezaproject/corteza-server/system/service"
"github.com/cortezaproject/corteza-server/system/types"
"github.com/pkg/errors"
)
var _ = errors.Wrap
type (
authInternalValidUserResponse struct {
JWT string `json:"jwt"`
User *authUserPayload `json:"user"`
}
authPasswordResetTokenExchangeResponse struct {
Token string `json:"token"`
User *outgoing.User `json:"user"`
}
AuthInternal struct {
tokenEncoder auth.TokenEncoder
authSvc authInternalAuthService
}
authInternalAuthService interface {
InternalSignUp(ctx context.Context, input *types.User, password string) (*types.User, error)
InternalLogin(ctx context.Context, email string, password string) (*types.User, error)
SetPassword(ctx context.Context, userID uint64, AuthActionPassword string) error
ChangePassword(ctx context.Context, userID uint64, oldPassword, AuthActionPassword string) error
LoadRoleMemberships(ctx context.Context, user *types.User) error
ValidateEmailConfirmationToken(ctx context.Context, token string) (user *types.User, err error)
ExchangePasswordResetToken(ctx context.Context, token string) (user *types.User, exchangedToken string, err error)
ValidatePasswordResetToken(ctx context.Context, token string) (user *types.User, err error)
SendPasswordResetToken(ctx context.Context, email string) (err error)
}
)
func (AuthInternal) New() *AuthInternal {
return &AuthInternal{
tokenEncoder: auth.DefaultJwtHandler,
authSvc: service.DefaultAuth,
}
}
func (ctrl *AuthInternal) Login(ctx context.Context, r *request.AuthInternalLogin) (interface{}, error) {
u, err := ctrl.authSvc.InternalLogin(ctx, r.Email, r.Password)
if err != nil {
return nil, err
}
return ctrl.authInternalValidUserResponse(ctx, u)
}
func (ctrl *AuthInternal) Signup(ctx context.Context, r *request.AuthInternalSignup) (interface{}, error) {
newUser := &types.User{
Email: r.Email,
Handle: r.Handle,
Username: r.Username,
Name: r.Name,
}
u, err := ctrl.authSvc.InternalSignUp(ctx, newUser, r.Password)
if err != nil {
return nil, err
}
if !u.EmailConfirmed {
// When email is not confirmed, do not send back JWT
return authInternalValidUserResponse{User: &authUserPayload{User: payload.User(u)}}, nil
}
if err = ctrl.authSvc.LoadRoleMemberships(ctx, u); err != nil {
return nil, err
}
return ctrl.authInternalValidUserResponse(ctx, u)
}
func (ctrl *AuthInternal) RequestPasswordReset(ctx context.Context, r *request.AuthInternalRequestPasswordReset) (interface{}, error) {
return true, ctrl.authSvc.SendPasswordResetToken(ctx, r.Email)
}
func (ctrl *AuthInternal) ExchangePasswordResetToken(ctx context.Context, r *request.AuthInternalExchangePasswordResetToken) (interface{}, error) {
u, token, err := ctrl.authSvc.ExchangePasswordResetToken(ctx, r.Token)
if err != nil {
return nil, err
}
return authPasswordResetTokenExchangeResponse{
Token: token,
User: payload.User(u),
}, nil
}
func (ctrl *AuthInternal) ResetPassword(ctx context.Context, r *request.AuthInternalResetPassword) (interface{}, error) {
var u, err = ctrl.authSvc.ValidatePasswordResetToken(ctx, r.Token)
if err != nil {
return nil, err
}
err = ctrl.authSvc.SetPassword(ctx, u.ID, r.Password)
if err != nil {
return nil, err
}
return ctrl.authInternalValidUserResponse(ctx, u)
}
func (ctrl *AuthInternal) ConfirmEmail(ctx context.Context, r *request.AuthInternalConfirmEmail) (interface{}, error) {
var u, err = ctrl.authSvc.ValidateEmailConfirmationToken(ctx, r.Token)
if err != nil {
return nil, err
}
return ctrl.authInternalValidUserResponse(ctx, u)
}
func (ctrl *AuthInternal) ChangePassword(ctx context.Context, r *request.AuthInternalChangePassword) (interface{}, error) {
var identity = auth.GetIdentityFromContext(ctx)
if !identity.Valid() {
return nil, errors.New("invalid user (not authenticated)")
}
err := ctrl.authSvc.ChangePassword(ctx, identity.Identity(), r.OldPassword, r.NewPassword)
if err != nil {
return nil, err
} else {
return true, nil
}
}
func (ctrl AuthInternal) authInternalValidUserResponse(ctx context.Context, u *types.User) (*authInternalValidUserResponse, error) {
if err := ctrl.authSvc.LoadRoleMemberships(ctx, u); err != nil {
return nil, err
}
return &authInternalValidUserResponse{
JWT: ctrl.tokenEncoder.Encode(u),
User: &authUserPayload{
User: payload.User(u),
Roles: payload.Uint64stoa(u.Roles()),
},
}, nil
}