fixes
This commit is contained in:
@@ -2,14 +2,31 @@ package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (s SilvermobiGRPCService) SetPhoneNumber(ctx context.Context, req *grpcproto.SetPhoneNumberRequest) (res *grpcproto.SetPhoneNumberResponse, err error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
|
||||
}
|
||||
|
||||
authHeader, ok := md["authorization"]
|
||||
if !ok || len(authHeader) == 0 {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
|
||||
}
|
||||
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
|
||||
id := ExtractIdFromToken(tokenString)
|
||||
if err = s.Handler.UpdatePhoneNumber(
|
||||
context.Background(),
|
||||
req.Email,
|
||||
id,
|
||||
req.PhoneNumber,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -19,10 +36,20 @@ func (s SilvermobiGRPCService) SetPhoneNumber(ctx context.Context, req *grpcprot
|
||||
}
|
||||
|
||||
func (s SilvermobiGRPCService) VerifyPhoneNumber(ctx context.Context, req *grpcproto.VerifyPhoneNumberRequest) (res *grpcproto.VerifyPhoneNumberResponse, err error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
|
||||
}
|
||||
|
||||
authHeader, ok := md["authorization"]
|
||||
if !ok || len(authHeader) == 0 {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
|
||||
}
|
||||
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
|
||||
id := ExtractIdFromToken(tokenString)
|
||||
if err = s.Handler.VerifyPhoneNumber(
|
||||
context.Background(),
|
||||
req.Email,
|
||||
id,
|
||||
req.PhoneNumber,
|
||||
req.VerificationCode,
|
||||
); err != nil {
|
||||
@@ -33,23 +60,126 @@ func (s SilvermobiGRPCService) VerifyPhoneNumber(ctx context.Context, req *grpcp
|
||||
}
|
||||
|
||||
func (s SilvermobiGRPCService) SetBirthDate(ctx context.Context, req *grpcproto.BirthDateRequest) (res *grpcproto.BirthDateResponse, err error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
|
||||
}
|
||||
|
||||
authHeader, ok := md["authorization"]
|
||||
if !ok || len(authHeader) == 0 {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
|
||||
}
|
||||
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
|
||||
id := ExtractIdFromToken(tokenString)
|
||||
birthdate := time.Unix(req.Birthdate.Seconds, int64(req.Birthdate.Nanos)).UTC()
|
||||
birthdateString := birthdate.Format("2006-01-02T15:04:05Z")
|
||||
if err = s.Handler.UpdateBirthDate(ctx, req.Email, birthdateString); err != nil {
|
||||
if err = s.Handler.UpdateBirthDate(ctx, id, birthdateString); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &grpcproto.BirthDateResponse{
|
||||
Ok: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s SilvermobiGRPCService) SetAccountType(ctx context.Context, req *grpcproto.AccountTypeRequest) (res *grpcproto.AccountTypeResponse, err error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
|
||||
}
|
||||
authHeader, ok := md["authorization"]
|
||||
if !ok || len(authHeader) == 0 {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
|
||||
}
|
||||
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
|
||||
id := ExtractIdFromToken(tokenString)
|
||||
if req.GetType() != grpcproto.AccountTypeRequest_PASSENGER && req.GetType() != grpcproto.AccountTypeRequest_DRIVER {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Type should be PASSENGER or DRIVER")
|
||||
}
|
||||
if err = s.Handler.SetAccountType(ctx, id, req.GetType().String()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &grpcproto.AccountTypeResponse{
|
||||
Ok: true,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (s SilvermobiGRPCService) GetAccountType(ctx context.Context, req *grpcproto.AccountTypeRequest) (res *grpcproto.AccountTypeResponse, err error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
|
||||
}
|
||||
authHeader, ok := md["authorization"]
|
||||
if !ok || len(authHeader) == 0 {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
|
||||
}
|
||||
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
|
||||
id := ExtractIdFromToken(tokenString)
|
||||
if req.Request == nil || !*req.Request {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "request arg should be true")
|
||||
}
|
||||
account_type, err := s.Handler.GetAccountType(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var responseType grpcproto.AccountTypeResponse_AccountType
|
||||
switch account_type {
|
||||
case "PASSENGER":
|
||||
responseType = grpcproto.AccountTypeResponse_PASSENGER
|
||||
case "DRIVER":
|
||||
responseType = grpcproto.AccountTypeResponse_DRIVER
|
||||
default:
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Invalid account type")
|
||||
}
|
||||
|
||||
response := &grpcproto.AccountTypeResponse{
|
||||
Type: &responseType,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
|
||||
}
|
||||
|
||||
func (s SilvermobiGRPCService) GetValidation(ctx context.Context, req *grpcproto.ValidationRequest) (res *grpcproto.ValidationResponse, err error) {
|
||||
phone_validation, birth_validation, err := s.Handler.CheckValidation(ctx, req.Email)
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
|
||||
}
|
||||
|
||||
authHeader, ok := md["authorization"]
|
||||
if !ok || len(authHeader) == 0 {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
|
||||
}
|
||||
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
|
||||
id := ExtractIdFromToken(tokenString)
|
||||
phone_validation, birth_validation, type_validation, err := s.Handler.CheckValidation(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &grpcproto.ValidationResponse{
|
||||
Phone: phone_validation,
|
||||
Birthdate: birth_validation,
|
||||
Type: type_validation,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ExtractIdFromToken(tokenString string) string {
|
||||
parts := strings.Split(tokenString, ".")
|
||||
if len(parts) != 3 {
|
||||
return ""
|
||||
}
|
||||
payloadBytes, err := base64.RawStdEncoding.DecodeString(parts[1])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var payloadMap map[string]interface{}
|
||||
if err := json.Unmarshal(payloadBytes, &payloadMap); err != nil {
|
||||
return ""
|
||||
}
|
||||
id, ok := payloadMap["sub"].(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@ package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"git.coopgo.io/coopgo-apps/silvermobi/handler"
|
||||
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
@@ -14,6 +11,9 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"net"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
@@ -22,53 +22,25 @@ var (
|
||||
contextKeyUser = contextKey("user")
|
||||
)
|
||||
|
||||
type SilvermobiGRPCService struct {
|
||||
Config *viper.Viper
|
||||
Handler *handler.SilvermobiHandler
|
||||
|
||||
grpcproto.UnimplementedSilvermobiGRPCServer
|
||||
}
|
||||
|
||||
func NewSilvermobiGRPCService(cfg *viper.Viper, handler *handler.SilvermobiHandler) SilvermobiGRPCService {
|
||||
return SilvermobiGRPCService{
|
||||
Config: cfg,
|
||||
Handler: handler,
|
||||
}
|
||||
}
|
||||
|
||||
func Run(done chan error, cfg *viper.Viper, handler *handler.SilvermobiHandler) {
|
||||
var (
|
||||
address = "127.0.0.1:" + cfg.GetString("services.external.grpc.port")
|
||||
jwt_secret = cfg.GetString("identification.local.jwt_secret")
|
||||
)
|
||||
|
||||
log.Info().Msg("GRPC server on " + address)
|
||||
|
||||
server := grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||
grpc_ctxtags.StreamServerInterceptor(),
|
||||
StreamAuthServerInterceptor(GRPCAuthFunc(jwt_secret)),
|
||||
)),
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
|
||||
grpc_ctxtags.UnaryServerInterceptor(),
|
||||
UnaryAuthServerInterceptor(GRPCAuthFunc(jwt_secret)),
|
||||
)),
|
||||
)
|
||||
|
||||
grpcproto.RegisterSilvermobiGRPCServer(server, NewSilvermobiGRPCService(cfg, handler))
|
||||
l, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err)
|
||||
func NoAuth(method string) bool {
|
||||
noAuthMethods := []string{
|
||||
"/SilvermobiGRPC/ForgetAccount",
|
||||
"/SilvermobiGRPC/UpdatePassword",
|
||||
"/SilvermobiGRPC/AuthRegister",
|
||||
"/SilvermobiGRPC/AuthLogin",
|
||||
}
|
||||
|
||||
if err := server.Serve(l); err != nil {
|
||||
log.Error().Err(err).Msg("gRPC service ended")
|
||||
done <- err
|
||||
for _, m := range noAuthMethods {
|
||||
if method == m {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func UnaryAuthServerInterceptor(authFunc grpc_auth.AuthFunc) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
print(info.FullMethod)
|
||||
if NoAuth(info.FullMethod) {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
@@ -81,7 +53,6 @@ func UnaryAuthServerInterceptor(authFunc grpc_auth.AuthFunc) grpc.UnaryServerInt
|
||||
return handler(newCtx, req)
|
||||
}
|
||||
}
|
||||
|
||||
func StreamAuthServerInterceptor(authFunc grpc_auth.AuthFunc) grpc.StreamServerInterceptor {
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
if NoAuth(info.FullMethod) {
|
||||
@@ -101,25 +72,65 @@ func StreamAuthServerInterceptor(authFunc grpc_auth.AuthFunc) grpc.StreamServerI
|
||||
}
|
||||
}
|
||||
|
||||
type SilvermobiGRPCService struct {
|
||||
Config *viper.Viper
|
||||
Handler *handler.SilvermobiHandler
|
||||
grpcproto.UnimplementedSilvermobiGRPCServer
|
||||
}
|
||||
|
||||
func NewSilvermobiGRPCService(cfg *viper.Viper, handler *handler.SilvermobiHandler) SilvermobiGRPCService {
|
||||
return SilvermobiGRPCService{
|
||||
Config: cfg,
|
||||
Handler: handler,
|
||||
}
|
||||
}
|
||||
|
||||
func Run(done chan error, cfg *viper.Viper, handler *handler.SilvermobiHandler) {
|
||||
var (
|
||||
address = "0.0.0.0:" + cfg.GetString("services.external.grpc.port")
|
||||
jwt_secret = cfg.GetString("identification.local.jwt_secret")
|
||||
)
|
||||
|
||||
log.Info().Msg("GRPC server on " + address)
|
||||
|
||||
server := grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||
grpc_ctxtags.StreamServerInterceptor(),
|
||||
StreamAuthServerInterceptor(GRPCAuthFunc(jwt_secret)),
|
||||
)),
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
|
||||
grpc_ctxtags.UnaryServerInterceptor(),
|
||||
UnaryAuthServerInterceptor(GRPCAuthFunc(jwt_secret)),
|
||||
)),
|
||||
)
|
||||
|
||||
service := NewSilvermobiGRPCService(cfg, handler)
|
||||
grpcproto.RegisterSilvermobiGRPCServer(server, service)
|
||||
l, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err)
|
||||
}
|
||||
|
||||
if err := server.Serve(l); err != nil {
|
||||
log.Error().Err(err).Msg("gRPC service ended")
|
||||
done <- err
|
||||
}
|
||||
}
|
||||
|
||||
func GRPCAuthFunc(jwtKey string) grpc_auth.AuthFunc {
|
||||
return func(ctx context.Context) (context.Context, error) {
|
||||
tokenString, err := grpc_auth.AuthFromMD(ctx, "bearer")
|
||||
if err != nil {
|
||||
log.Error().Err(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims := jwt.MapClaims{}
|
||||
jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(jwtKey), nil
|
||||
})
|
||||
|
||||
if err != nil || !token.Valid {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "Invalid or expired token")
|
||||
}
|
||||
ctx = context.WithValue(ctx, contextKeyUser, claims["sub"].(string))
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
}
|
||||
|
||||
func NoAuth(method string) bool {
|
||||
return strings.Contains(method, "Auth")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user