package main import ( "github.com/go-openapi/runtime/middleware" "src.dualinventive.com/go/authentication-service/internal/authtokens" "src.dualinventive.com/go/authentication-service/internal/domain" "src.dualinventive.com/go/authentication-service/internal/pwreset" "src.dualinventive.com/go/authentication-service/rest/models" "src.dualinventive.com/go/authentication-service/rest/server/operations" "src.dualinventive.com/go/authentication-service/rest/server/operations/authentication" ) func initHandlers( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.TokenAuthAuth = func(token string) (interface{}, error) { return token, nil } registerLoginHandler(api, tokenService) registerLogoutHandler(api, tokenService) registerVerifyHandler(api, tokenService) registerPasswordResetRequestHandler(api, tokenService) registerPasswordResetRedeemHandler(api, tokenService) registerMeHandler(api, tokenService) registerListTokensHandler(api, tokenService) registerDeleteTokenHandler(api, tokenService) } func registerLoginHandler( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationPostLoginHandler = authentication.PostLoginHandlerFunc( func(params authentication.PostLoginParams) middleware.Responder { credentials := domain.Credentials{ User: params.Body.User, CompanyCode: params.Body.CompanyCode, Password: params.Body.Password, } token, err := tokenService.CreateToken(credentials, params.HTTPRequest.UserAgent()) if err != nil { switch err.(type) { case *authtokens.ErrInvalidCredentials: resp := authentication.NewPostLoginUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: resp := authentication.NewPostLoginInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp } } return authentication.NewPostLoginOK().WithPayload(&models.SecurityToken{ Token: token.Secret, }) }) } func registerLogoutHandler( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationLogoutHandler = authentication.LogoutHandlerFunc( func(params authentication.LogoutParams, secret interface{}) middleware.Responder { token := &domain.Token{Secret: secret.(string)} err := tokenService.DeleteToken(token) if err != nil { switch err.(type) { case *authtokens.ErrNilToken: resp := authentication.NewLogoutUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *authtokens.ErrTokenNotFound: resp := authentication.NewLogoutUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: return authentication.NewLogoutInternalServerError() } } return authentication.NewLogoutNoContent() }) } func registerVerifyHandler( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationVerifyHandler = authentication.VerifyHandlerFunc( func(params authentication.VerifyParams, secret interface{}) middleware.Responder { token := &domain.Token{Secret: secret.(string)} var rights []string if params.Body != nil { rights = params.Body.Rights } else { rights = []string{} } _, err := tokenService.VerifyToken(token, rights...) if err != nil { switch err.(type) { case *authtokens.ErrTokenNotFound: return &authentication.VerifyOK{Payload: false} case *authtokens.ErrInvalidToken: return &authentication.VerifyOK{Payload: false} case *authtokens.ErrUnauthorized: return &authentication.VerifyOK{Payload: false} default: return &authentication.VerifyInternalServerError{ Payload: &models.ErrResponse{ErrMsg: err.Error()}} } } return &authentication.VerifyOK{Payload: true} }) } func registerMeHandler( //nolint:dupl api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationGetMeHandler = authentication.GetMeHandlerFunc( func(params authentication.GetMeParams, secret interface{}) middleware.Responder { token := &domain.Token{Secret: secret.(string)} user, err := tokenService.GetUserByToken(token) if err != nil { switch err.(type) { case *authtokens.ErrTokenNotFound: resp := authentication.NewGetMeUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *authtokens.ErrUserNotFound: resp := authentication.NewGetMeUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: resp := authentication.NewGetMeInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp } } resp := authentication.NewGetMeOK() resp.SetPayload(mapUser(user)) return resp }) } func registerPasswordResetRequestHandler( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationPostPasswordResetRequestHandler = authentication.PostPasswordResetRequestHandlerFunc( func(params authentication.PostPasswordResetRequestParams) middleware.Responder { err := pwreset.RequestPasswordReset( tokenService.CredentialsRepository, tokenService.EmailSender, tokenService.TemplateRepository, tokenService.ResetCodeRepository, params.Body.User, ) // dupl: Preferred to keep this autonomous for future use. if err != nil { //nolint:dupl switch err.(type) { case *pwreset.ErrFailedToCreateResetCode: resp := authentication.NewPostPasswordResetRequestInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *pwreset.ErrUserFetchFailed: resp := authentication.NewPostPasswordResetRequestInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *pwreset.ErrFailedToSendEmail: resp := authentication.NewPostPasswordResetRequestInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: resp := authentication.NewPostPasswordResetRequestBadRequest() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp } } else { return authentication.NewPostPasswordResetRequestCreated() } }) } func registerPasswordResetRedeemHandler( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationPostPasswordResetRedeemHandler = authentication.PostPasswordResetRedeemHandlerFunc( func(params authentication.PostPasswordResetRedeemParams) middleware.Responder { err := pwreset.RedeemPasswordReset( tokenService.CredentialsRepository, tokenService.ResetCodeRepository, params.Body.User, params.Body.ResetCode, params.Body.Password, params.Body.PasswordVerify, ) if err != nil { switch err.(type) { case *pwreset.ErrFailedToGetResetCode: resp := authentication.NewPostPasswordResetRedeemInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *pwreset.ErrChangePasswordFailed: resp := authentication.NewPostPasswordResetRedeemInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: resp := authentication.NewPostPasswordResetRedeemBadRequest() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp } } else { return authentication.NewPostPasswordResetRedeemCreated() } }) } func registerListTokensHandler( //nolint:dupl api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationListTokensHandler = authentication.ListTokensHandlerFunc( func(params authentication.ListTokensParams, secret interface{}) middleware.Responder { token := &domain.Token{Secret: secret.(string)} opaqueTokens, err := tokenService.GetOpaqueTokensByToken(token) if err != nil { switch err.(type) { case *authtokens.ErrNilToken: resp := authentication.NewListTokensUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *authtokens.ErrInvalidToken: resp := authentication.NewListTokensUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: resp := authentication.NewListTokensInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp } } resp := authentication.NewListTokensOK() resp.SetPayload(mapTokenList(opaqueTokens)) return resp }) } func registerDeleteTokenHandler( api *operations.AuthenticationAPI, tokenService *authtokens.Service, ) { api.AuthenticationDeleteTokenHandler = authentication.DeleteTokenHandlerFunc( func(params authentication.DeleteTokenParams, secret interface{}) middleware.Responder { token := &domain.Token{Secret: secret.(string)} // dupl: Preferred to keep this autonomous for future use. err := tokenService.DeleteTokenByOpaqueID(token, params.OpaqueTokenID) //nolint:dupl if err != nil { //nolint:dupl switch err.(type) { case *authtokens.ErrNilToken: resp := authentication.NewDeleteTokenUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *authtokens.ErrInvalidToken: resp := authentication.NewDeleteTokenUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp case *authtokens.ErrTokenNotFound: resp := authentication.NewDeleteTokenUnauthorized() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp default: resp := authentication.NewDeleteTokenInternalServerError() resp.SetPayload(&models.ErrResponse{ErrMsg: err.Error()}) return resp } } return authentication.NewDeleteTokenOK() }) }