Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JOH-50] Implement forgot password rpc #19

Merged
merged 12 commits into from
Jan 14, 2024
13 changes: 13 additions & 0 deletions cfgldr/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Jwt struct {
ExpiresIn int `mapstructure:"expires_in"`
RefreshTokenTTL int `mapstructure:"refresh_token_ttl"`
Issuer string `mapstructure:"issuer"`
ResetTokenTTL int `mapstructure:"reset_token_ttl"`
}

type Redis struct {
Expand All @@ -33,11 +34,23 @@ type Redis struct {
Password string `mapstructure:"password"`
}

type Auth struct {
ClientURL string `mapstructure:"client_url"`
}

type Sendgrid struct {
ApiKey string `mapstructure:"api_key"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
}

type Config struct {
App App `mapstructure:"app"`
Database Database `mapstructure:"database"`
Jwt Jwt `mapstructure:"jwt"`
Redis Redis `mapstructure:"redis"`
Auth Auth `mapstructure:"auth"`
Sendgrid Sendgrid `mapstructure:"sendgrid"`
}

func LoadConfig() (config *Config, err error) {
Expand Down
7 changes: 5 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
cacheRp "github.com/isd-sgcu/johnjud-auth/internal/repository/cache"
userRp "github.com/isd-sgcu/johnjud-auth/internal/repository/user"
authSvc "github.com/isd-sgcu/johnjud-auth/internal/service/auth"
emailSvc "github.com/isd-sgcu/johnjud-auth/internal/service/email"
jwtSvc "github.com/isd-sgcu/johnjud-auth/internal/service/jwt"
tokenSvc "github.com/isd-sgcu/johnjud-auth/internal/service/token"
userSvc "github.com/isd-sgcu/johnjud-auth/internal/service/user"
Expand Down Expand Up @@ -132,12 +133,14 @@ func main() {

accessTokenCache := cacheRp.NewRepository(cacheDb)
refreshTokenCache := cacheRp.NewRepository(cacheDb)
resetPasswordCache := cacheRp.NewRepository(cacheDb)

jwtStrategy := strategy.NewJwtStrategy(conf.Jwt.Secret)
jwtService := jwtSvc.NewService(conf.Jwt, jwtStrategy, jwtUtil)
tokenService := tokenSvc.NewService(jwtService, accessTokenCache, refreshTokenCache, uuidUtil)
tokenService := tokenSvc.NewService(jwtService, accessTokenCache, refreshTokenCache, resetPasswordCache, uuidUtil)

authService := authSvc.NewService(authRepo, userRepo, tokenService, bcryptUtil)
emailService := emailSvc.NewService(conf.Sendgrid)
authService := authSvc.NewService(authRepo, userRepo, tokenService, emailService, bcryptUtil, conf.Auth)

grpc_health_v1.RegisterHealthServer(grpcServer, health.NewServer())
authPb.RegisterAuthServiceServer(grpcServer, authService)
Expand Down
9 changes: 9 additions & 0 deletions config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,17 @@ jwt:
expires_in: 3600
refresh_token_ttl: 604800
issuer: <issuer>
reset_token_ttl: 900

redis:
host: localhost
port: 6379
password: ""

auth:
client_url: localhost:3000

sendgrid:
api_key: <api_key>
name: johnjud
address: [email protected]
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ require (
github.com/rs/zerolog v1.31.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sendgrid/rest v2.6.9+incompatible // indirect
github.com/sendgrid/sendgrid-go v3.14.0+incompatible // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0=
github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE=
github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fcif2i7P7wzISv1sU6DUA=
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
Expand Down
3 changes: 3 additions & 0 deletions internal/constant/email.constant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package constant

const ResetPasswordSubject = "Reset Password Request"
4 changes: 4 additions & 0 deletions internal/domain/dto/token/token.dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ type RefreshTokenCache struct {
UserID string `json:"user_id"`
Role constant.Role `json:"role"`
}

type ResetPasswordTokenCache struct {
UserID string `json:"user_id"`
}
38 changes: 36 additions & 2 deletions internal/service/auth/auth.service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package auth

import (
"context"

"fmt"
"github.com/isd-sgcu/johnjud-auth/cfgldr"
"github.com/isd-sgcu/johnjud-auth/internal/constant"
"github.com/isd-sgcu/johnjud-auth/internal/domain/model"
"github.com/isd-sgcu/johnjud-auth/internal/utils"
"github.com/isd-sgcu/johnjud-auth/pkg/repository/auth"
"github.com/isd-sgcu/johnjud-auth/pkg/repository/user"
"github.com/isd-sgcu/johnjud-auth/pkg/service/email"
"github.com/isd-sgcu/johnjud-auth/pkg/service/token"
"github.com/rs/zerolog/log"

Expand All @@ -23,15 +25,19 @@ type serviceImpl struct {
authRepo auth.Repository
userRepo user.Repository
tokenService token.Service
emailService email.Service
bcryptUtil utils.IBcryptUtil
config cfgldr.Auth
}

func NewService(authRepo auth.Repository, userRepo user.Repository, tokenService token.Service, bcryptUtil utils.IBcryptUtil) authProto.AuthServiceServer {
func NewService(authRepo auth.Repository, userRepo user.Repository, tokenService token.Service, emailService email.Service, bcryptUtil utils.IBcryptUtil, config cfgldr.Auth) authProto.AuthServiceServer {
return &serviceImpl{
authRepo: authRepo,
userRepo: userRepo,
tokenService: tokenService,
emailService: emailService,
bcryptUtil: bcryptUtil,
config: config,
}
}

Expand Down Expand Up @@ -163,3 +169,31 @@ func (s *serviceImpl) SignOut(_ context.Context, request *authProto.SignOutReque

return &authProto.SignOutResponse{IsSuccess: true}, nil
}

func (s *serviceImpl) ForgotPassword(_ context.Context, request *authProto.ForgotPasswordRequest) (*authProto.ForgotPasswordResponse, error) {
user := &model.User{}
err := s.userRepo.FindByEmail(request.Email, user)
if err != nil {
return nil, status.Error(codes.NotFound, constant.UserNotFoundErrorMessage)
}

resetPasswordToken, err := s.tokenService.CreateResetPasswordToken(user.ID.String())
if err != nil {
return nil, status.Error(codes.Internal, constant.InternalServerErrorMessage)
}

resetPasswordURL := fmt.Sprintf("%s/reset-password/%s", s.config.ClientURL, resetPasswordToken)
emailSubject := constant.ResetPasswordSubject
emailContent := fmt.Sprintf("Please click the following url to reset password %s", resetPasswordURL)
if err := s.emailService.SendEmail(emailSubject, user.Firstname, user.Email, emailContent); err != nil {
return nil, status.Error(codes.Internal, constant.InternalServerErrorMessage)
}

return &authProto.ForgotPasswordResponse{
Url: resetPasswordURL,
}, nil
}

func (s *serviceImpl) ResetPassword(_ context.Context, request *authProto.ResetPasswordRequest) (*authProto.ResetPasswordResponse, error) {
return nil, nil
}
Loading
Loading