184 lines
5.1 KiB
Go
184 lines
5.1 KiB
Go
package grpc
|
|
|
|
import (
|
|
"golang.org/x/net/context"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/metadata"
|
|
"google.golang.org/grpc/status"
|
|
"src.dualinventive.com/go/authentication-service/internal/authtokens"
|
|
"src.dualinventive.com/go/authentication-service/internal/domain"
|
|
"src.dualinventive.com/go/authentication-service/internal/pwreset"
|
|
)
|
|
|
|
//Server is a structure of server instance
|
|
type Server struct {
|
|
Name string
|
|
TokenService *authtokens.Service
|
|
}
|
|
|
|
//NewServer creates new instance of Server
|
|
func NewServer(
|
|
tokenService *authtokens.Service,
|
|
) (*Server, error) {
|
|
server := &Server{
|
|
Name: "authentication-service-grpc",
|
|
TokenService: tokenService,
|
|
}
|
|
return server, nil
|
|
}
|
|
|
|
//Login is used to create a new token for user
|
|
func (s *Server) Login(ctx context.Context, req *LoginRequest) (*LoginResponse, error) {
|
|
credentials := domain.Credentials{
|
|
User: req.Credentials.Username,
|
|
CompanyCode: req.Credentials.CompanyCode,
|
|
Password: req.Credentials.Password,
|
|
}
|
|
userAgent := getValue(ctx, "userAgent")
|
|
token, err := s.TokenService.CreateToken(credentials, userAgent)
|
|
|
|
if err != nil {
|
|
return nil, mapError(err)
|
|
}
|
|
|
|
return &LoginResponse{Token: &Token{
|
|
Secret: token.Secret}}, nil
|
|
}
|
|
|
|
//Logout is used to remove the token for user
|
|
func (s *Server) Logout(ctx context.Context, empty *Empty) (*Empty, error) {
|
|
token := &domain.Token{Secret: getValue(ctx, "token")}
|
|
err := s.TokenService.DeleteToken(token)
|
|
|
|
if err != nil {
|
|
return nil, mapError(err)
|
|
}
|
|
|
|
return &Empty{}, nil
|
|
}
|
|
|
|
//VerifyToken is used to retrieve user information based on the given token.
|
|
func (s *Server) VerifyToken(ctx context.Context, req *VerifyTokenRequest) (*VerifyTokenResponse, error) {
|
|
token := &domain.Token{Secret: getValue(ctx, "token")}
|
|
|
|
_, err := s.TokenService.VerifyToken(token, req.Rights...)
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case *authtokens.ErrTokenNotFound:
|
|
return &VerifyTokenResponse{Valid: false}, nil
|
|
case *authtokens.ErrInvalidToken:
|
|
return &VerifyTokenResponse{Valid: false}, nil
|
|
case *authtokens.ErrUnauthorized:
|
|
return &VerifyTokenResponse{Valid: false}, nil
|
|
default:
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
}
|
|
}
|
|
|
|
return &VerifyTokenResponse{Valid: true}, nil
|
|
}
|
|
|
|
//Me is used to retrieve user information based on the given token.
|
|
func (s *Server) Me(ctx context.Context, empty *Empty) (*MeResponse, error) {
|
|
token := &domain.Token{Secret: getValue(ctx, "token")}
|
|
|
|
user, err := s.TokenService.GetUserByToken(token)
|
|
if err != nil {
|
|
return nil, mapError(err)
|
|
}
|
|
|
|
return &MeResponse{User: mapUser(user)}, nil
|
|
}
|
|
|
|
//RequestPasswordReset generates a unique password reset code and sends it to the users email address.
|
|
func (s *Server) RequestPasswordReset(ctx context.Context, req *RequestPasswordResetRequest) (*Empty, error) {
|
|
err := pwreset.RequestPasswordReset(
|
|
s.TokenService.CredentialsRepository,
|
|
s.TokenService.EmailSender,
|
|
s.TokenService.TemplateRepository,
|
|
s.TokenService.ResetCodeRepository,
|
|
req.UserName,
|
|
)
|
|
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case *pwreset.ErrFailedToCreateResetCode:
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
case *pwreset.ErrUserFetchFailed:
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
case *pwreset.ErrFailedToSendEmail:
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
default:
|
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
|
}
|
|
}
|
|
|
|
return &Empty{}, nil
|
|
}
|
|
|
|
//RedeemPasswordReset will set a password of a user when the given username and password reset code a valid.
|
|
func (s *Server) RedeemPasswordReset(ctx context.Context, req *RedeemPasswordResetRequest) (*Empty, error) {
|
|
err := pwreset.RedeemPasswordReset(
|
|
s.TokenService.CredentialsRepository,
|
|
s.TokenService.ResetCodeRepository,
|
|
req.UserName,
|
|
req.ResetCode,
|
|
req.Password,
|
|
req.PasswordVerify,
|
|
)
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case *pwreset.ErrFailedToGetResetCode:
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
case *pwreset.ErrChangePasswordFailed:
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
default:
|
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
|
}
|
|
}
|
|
|
|
return &Empty{}, nil
|
|
}
|
|
|
|
//ListTokens returns a list of active shielded tokens for the current user.
|
|
func (s *Server) ListTokens(ctx context.Context, empty *Empty) (*ListTokensResponse, error) {
|
|
token := &domain.Token{Secret: getValue(ctx, "token")}
|
|
|
|
opaqueTokens, err := s.TokenService.GetOpaqueTokensByToken(token)
|
|
if err != nil {
|
|
return nil, mapError(err)
|
|
}
|
|
|
|
return &ListTokensResponse{Tokens: mapTokenList(opaqueTokens)}, nil
|
|
}
|
|
|
|
//DeleteToken removes a token by reference of it's opaque id.
|
|
func (s *Server) DeleteToken(ctx context.Context, req *DeleteTokenRequest) (*Empty, error) {
|
|
token := &domain.Token{Secret: getValue(ctx, "token")}
|
|
|
|
err := s.TokenService.DeleteTokenByOpaqueID(token, req.OpaqueId)
|
|
if err != nil {
|
|
return nil, mapError(err)
|
|
}
|
|
|
|
return &Empty{}, nil
|
|
}
|
|
|
|
func getValue(ctx context.Context, s string) string {
|
|
md, ok := metadata.FromIncomingContext(ctx)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
|
|
raw := md.Get(s)
|
|
if raw == nil {
|
|
return ""
|
|
}
|
|
|
|
if len(raw) == 0 {
|
|
return ""
|
|
}
|
|
|
|
return raw[0]
|
|
}
|