src.dualinventive.com/go/authentication-service/grpc/server.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]
}