This commit is contained in:
Salim Amine Bou Aram 2024-10-31 20:32:54 +01:00
parent 5628125ad3
commit ef2768c431
26 changed files with 706 additions and 379 deletions

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
*.cover*
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
vendor/
vendor*/
*.lock
go.sum
# Jetbrain IDE files
.idea/
.idea/*
.idea/**/*
config.yaml
# other
/scripts
/test-*

4
go.mod
View File

@ -1,6 +1,8 @@
module git.coopgo.io/coopgo-apps/silvermobi module git.coopgo.io/coopgo-apps/silvermobi
go 1.19 go 1.21
toolchain go1.23.2
require ( require (
git.coopgo.io/coopgo-platform/geocode v0.0.0-20230329105149-1f31b361814e git.coopgo.io/coopgo-platform/geocode v0.0.0-20230329105149-1f31b361814e

View File

@ -2,15 +2,19 @@ package handler
import ( import (
"context" "context"
"git.coopgo.io/coopgo-apps/silvermobi/models" "git.coopgo.io/coopgo-apps/silvermobi/models"
"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
) )
func (h *SilvermobiHandler) GetAccountInfos(ctx context.Context, id string) (account *models.Account, err error) { func (h *SilverMobiHandler) GetAccountInfos(ctx context.Context, id string) (account *models.Account, err error) {
resp, err := h.Services.MobilityAccounts.Client.GetAccount(ctx, &grpcapi.GetAccountRequest{Id: id}) var resp *grpcapi.GetAccountResponse
if err != nil {
if resp, err = h.Services.MobilityAccounts.Client.GetAccount(ctx, &grpcapi.GetAccountRequest{Id: id}); err != nil {
return nil, err return nil, err
} }
account = h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType()) account = h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType())
return account, nil return account, nil
} }

View File

@ -3,24 +3,39 @@ package handler
import ( import (
"context" "context"
"time" "time"
"git.coopgo.io/coopgo-apps/silvermobi/models"
) )
func (h *SilvermobiHandler) Login(ctx context.Context, username string, password string) (jwt string, err error) { func (h *SilverMobiHandler) Login(ctx context.Context, username string, password string) (jwt string, err error) {
account, err := h.Services.MobilityAccounts.Login(ctx, username, password, "silvermobi") var (
if err != nil { account *models.Account
pTTL time.Duration
)
if account, err = h.Services.MobilityAccounts.Login(ctx, username, password, "silvermobi"); err != nil {
return return
} }
key := h.Config.GetString("identification.local.jwt_secret") key := h.Config.GetString("identification.local.jwt_secret")
ttl := h.Config.GetString("identification.local.ttl") ttl := h.Config.GetString("identification.local.ttl")
parsedttl, err := time.ParseDuration(ttl)
if err != nil { if pTTL, err = time.ParseDuration(ttl); err != nil {
return "", err return "", err
} }
return account.CreateToken(parsedttl, key)
return account.CreateToken(pTTL, key)
} }
func (h *SilvermobiHandler) Register(ctx context.Context, username string, password string, email string, phone_number string, first_name string, last_name string) (jwt string, err error) { func (h *SilverMobiHandler) Register(ctx context.Context, username string, password string, email string,
account, err := h.Services.MobilityAccounts.Register( phone_number string, first_name string, last_name string) (jwt string, err error) {
var (
account *models.Account
pTTL time.Duration
)
if account, err = h.Services.MobilityAccounts.Register(
ctx, ctx,
username, username,
password, password,
@ -33,19 +48,16 @@ func (h *SilvermobiHandler) Register(ctx context.Context, username string, passw
"phone_number": phone_number, "phone_number": phone_number,
}, },
"silvermobi", "silvermobi",
) ); err != nil {
if err != nil {
return "", err return "", err
} }
key := h.Config.GetString("identification.local.jwt_secret") key := h.Config.GetString("identification.local.jwt_secret")
ttl := h.Config.GetString("identification.local.ttl") ttl := h.Config.GetString("identification.local.ttl")
parsedttl, err := time.ParseDuration(ttl) if pTTL, err = time.ParseDuration(ttl); err != nil {
if err != nil {
return "", err return "", err
} }
return account.CreateToken(parsedttl, key) return account.CreateToken(pTTL, key)
} }

View File

@ -3,8 +3,9 @@ package handler
import ( import (
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/tls"
"encoding/base64" "encoding/base64"
"git.coopgo.io/coopgo-apps/silvermobi/models"
gomail "gopkg.in/mail.v2" gomail "gopkg.in/mail.v2"
) )
@ -18,29 +19,50 @@ func generateRandomPassword(length int) (string, error) {
return password, nil return password, nil
} }
func (h *SilvermobiHandler) ForgetAccount(ctx context.Context, username string, namespace string) (response bool, access_Code string) { func (h *SilverMobiHandler) ForgetAccount(ctx context.Context, username string, namespace string) (response bool,
account, err := h.Services.MobilityAccounts.GetAccountUsername(ctx, username, namespace) access_Code string) {
if err == nil {
message := []byte("Hello dear,\nYour new Silvermobi password is: ") var (
password, _ := generateRandomPassword(10) err error
update := h.Services.MobilityAccounts.UpdatePassword(ctx, account.ID, password) account *models.Account
if update == false { )
account, err = h.Services.MobilityAccounts.GetAccountUsername(ctx, username, namespace)
if err != nil {
return false, "" return false, ""
} }
message := []byte("Hello dear,\nYour new Silvermobi password is: ")
password, _ := generateRandomPassword(10)
if update := h.Services.MobilityAccounts.UpdatePassword(ctx, account.ID, password); !update {
return false, ""
}
m := gomail.NewMessage() m := gomail.NewMessage()
m.SetHeader("From", h.Config.GetString("emailing.smtp.username")) m.SetHeader("From", h.Config.GetString("emailing.smtp.username"))
m.SetHeader("To", username) m.SetHeader("To", username)
m.SetHeader("Subject", "Silvermobi Password Recovery") m.SetHeader("Subject", "Silvermobi Password Recovery")
message = append(message, []byte(password)...) message = append(message, []byte(password)...)
m.SetBody("text/plain", string(message)) m.SetBody("text/plain", string(message))
d := gomail.NewDialer(h.Config.GetString("emailing.smtp.host"), h.Config.GetInt("emailing.smtp.port"), h.Config.GetString("emailing.smtp.username"),
h.Config.GetString("emailing.smtp.password")) d := gomail.NewDialer(
d.TLSConfig = &tls.Config{InsecureSkipVerify: true} h.Config.GetString("emailing.smtp.host"),
if err := d.DialAndSend(m); err != nil { h.Config.GetInt("emailing.smtp.port"),
h.Config.GetString("emailing.smtp.username"),
h.Config.GetString("emailing.smtp.password"),
)
d.StartTLSPolicy = gomail.MandatoryStartTLS
if err = d.DialAndSend(m); err != nil {
return false, "" return false, ""
} }
return true, password return true, password
} else {
return false, ""
}
} }

View File

@ -2,12 +2,13 @@ package handler
import ( import (
"fmt" "fmt"
"github.com/paulmach/orb" "github.com/paulmach/orb"
"github.com/paulmach/orb/geojson" "github.com/paulmach/orb/geojson"
"google.golang.org/genproto/googleapis/maps/routing/v2" "google.golang.org/genproto/googleapis/maps/routing/v2"
) )
func (h *SilvermobiHandler) GeoAutocomplete(text string, lat, lon float64) (*geojson.FeatureCollection, error) { func (h *SilverMobiHandler) GeoAutocomplete(text string) (*geojson.FeatureCollection, error) {
result, err := h.Services.Geocoder.Autocomplete(text) result, err := h.Services.Geocoder.Autocomplete(text)
if err != nil { if err != nil {
return nil, err return nil, err
@ -15,25 +16,27 @@ func (h *SilvermobiHandler) GeoAutocomplete(text string, lat, lon float64) (*geo
return result, nil return result, nil
} }
func (h *SilvermobiHandler) GeoRoute(locations geojson.FeatureCollection) (route *routing.Route, err error) { func (h *SilverMobiHandler) GeoRoute(locations geojson.FeatureCollection) (route *routing.Route, err error) {
route_locations := []orb.Point{} var (
routeLocations []orb.Point
features_type := "" featuresType string
)
for _, f := range locations.Features { for _, f := range locations.Features {
ft := f.Geometry.GeoJSONType() ft := f.Geometry.GeoJSONType()
if features_type != "" && ft != features_type { if ft != featuresType {
return nil, fmt.Errorf("mixing different types of geometries in the feature collection is not allowed : %s and %s found", features_type, ft) return nil, fmt.Errorf("mixing different types of geometries in"+
" the feature collection is not allowed : %s and %s found", featuresType, ft)
} }
features_type = ft featuresType = ft
if features_type == "Point" { if featuresType == "Point" {
if point, ok := f.Geometry.(orb.Point); ok { if point, ok := f.Geometry.(orb.Point); ok {
route_locations = append(route_locations, point) routeLocations = append(routeLocations, point)
} }
} else { } else {
return nil, fmt.Errorf("feature type %s not supported", features_type) return nil, fmt.Errorf("feature type %s not supported", featuresType)
} }
return nil, err return nil, err
@ -42,9 +45,10 @@ func (h *SilvermobiHandler) GeoRoute(locations geojson.FeatureCollection) (route
return route, nil return route, nil
} }
func (h *SilvermobiHandler) GeoReturnRoute(locations geojson.FeatureCollection) (route *routing.Route, err error) { func (h *SilverMobiHandler) GeoReturnRoute(locations geojson.FeatureCollection) (route *routing.Route, err error) {
loc := locations loc := locations
route.Polyline.String()
reverse(loc.Features) reverse(loc.Features)
return h.GeoRoute(loc) return h.GeoRoute(loc)

View File

@ -6,14 +6,15 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type SilvermobiHandler struct { type SilverMobiHandler struct {
Config *viper.Viper Config *viper.Viper
Services *services.ServicesHandler Services *services.ServiceHandler
Storage storage.Storage Storage storage.Storage
} }
func NewSilvermobiHandler(cfg *viper.Viper, services *services.ServicesHandler, storage storage.Storage) (*SilvermobiHandler, error) { func NewSilverMobiHandler(cfg *viper.Viper, services *services.ServiceHandler,
return &SilvermobiHandler{ storage storage.Storage) (*SilverMobiHandler, error) {
return &SilverMobiHandler{
Config: cfg, Config: cfg,
Services: services, Services: services,
Storage: storage, Storage: storage,

View File

@ -2,63 +2,69 @@ package handler
import ( import (
"context" "context"
"crypto/tls"
"git.coopgo.io/coopgo-apps/silvermobi/services" "git.coopgo.io/coopgo-apps/silvermobi/services"
"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
gomail "gopkg.in/mail.v2" gomail "gopkg.in/mail.v2"
) )
func (h *SilvermobiHandler) PutFirebase(ctx context.Context, id string, token string, device_platform string) (err error) { func (h *SilverMobiHandler) PutFirebase(ctx context.Context, id string, token string, device_platform string) (err error) {
err = h.Storage.CreateFirebaseToken(id, token, device_platform) err = h.Storage.CreateFirebaseToken(id, token, device_platform)
return err return err
} }
func (h *SilvermobiHandler) SendNotification(id, title, message string) (err error) { func (h *SilverMobiHandler) SendNotification(id, title, message string) error {
firebase_token, platfrom, _ := h.Storage.GetFirebaseToken(id) firebaseToken, platform, err := h.Storage.GetFirebaseToken(id)
if err != nil { if err != nil {
return err return err
} }
if platfrom == "android" {
_ = h.Services.Push.Send( notify := services.Notification{
services.Notification{ Recipients: []string{firebaseToken},
Platform: services.PushToAndroid,
Recipients: []string{firebase_token},
Title: title, Title: title,
Message: message, Message: message,
}, }
) if platform == "android" {
notify.Platform = services.PushToAndroid
err = h.Services.Push.Send(notify)
} else { } else {
_ = h.Services.Push.Send( notify.Platform = services.PushToIos
services.Notification{ err = h.Services.Push.Send(notify)
Platform: services.PushToIos,
Recipients: []string{firebase_token},
Title: title,
Message: message,
},
)
} }
return nil return err
} }
func (h *SilvermobiHandler) SendEmail(id, title, message string) (err error) { func (h *SilverMobiHandler) SendEmail(id, title, message string) (err error) {
resp, err := h.Services.MobilityAccounts.Client.GetAccount(context.Background(), &grpcapi.GetAccountRequest{Id: id}) var resp *grpcapi.GetAccountResponse
if err != nil {
if resp, err = h.Services.MobilityAccounts.Client.GetAccount(context.Background(),
&grpcapi.GetAccountRequest{Id: id}); err != nil {
return err return err
} }
account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType()) account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType())
m := gomail.NewMessage() m := gomail.NewMessage()
m.SetHeader("From", h.Config.GetString("emailing.smtp.username")) m.SetHeader("From", h.Config.GetString("emailing.smtp.username"))
m.SetHeader("To", account.Email) m.SetHeader("To", account.Email)
m.SetHeader("Subject", title) m.SetHeader("Subject", title)
m.SetBody("text/plain", message) m.SetBody("text/plain", message)
d := gomail.NewDialer(h.Config.GetString("emailing.smtp.host"), h.Config.GetInt("emailing.smtp.port"), h.Config.GetString("emailing.smtp.username"),
d := gomail.NewDialer(
h.Config.GetString("emailing.smtp.host"),
h.Config.GetInt("emailing.smtp.port"),
h.Config.GetString("emailing.smtp.username"),
h.Config.GetString("emailing.smtp.password")) h.Config.GetString("emailing.smtp.password"))
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil { d.StartTLSPolicy = gomail.MandatoryStartTLS
if err = d.DialAndSend(m); err != nil {
return err return err
} }
return nil return nil
} }

View File

@ -3,48 +3,53 @@ package handler
import ( import (
"context" "context"
"fmt" "fmt"
"math/rand"
"git.coopgo.io/coopgo-apps/silvermobi/services" "git.coopgo.io/coopgo-apps/silvermobi/services"
"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"math/rand"
) )
func (h *SilvermobiHandler) UpdatePhoneNumber(ctx context.Context, id string, phone_number string) error { func (h *SilverMobiHandler) UpdatePhoneNumber(ctx context.Context, id string, phoneNumber string) (err error) {
code := rand.Intn(9999) code := rand.Intn(9999)
err := h.Services.MobilityAccounts.UpdatePhoneNumber(
if err = h.Services.MobilityAccounts.UpdatePhoneNumber(
ctx, ctx,
id, id,
phone_number, phoneNumber,
false, false,
fmt.Sprintf("%04d", code), fmt.Sprintf("%04d", code),
) ); err != nil {
if err != nil {
log.Error().Err(err).Msg("updating phone number failed") log.Error().Err(err).Msg("updating phone number failed")
return err return err
} }
err = h.Services.Push.Send( if err = h.Services.Push.Send(
services.Notification{ services.Notification{
Platform: services.PushToSMSFactor, Platform: services.PushToSMSFactor,
Recipients: []string{phone_number[1:]}, Recipients: []string{phoneNumber[1:]},
Title: "SILVERMOBI", Title: "SILVERMOBI",
Message: fmt.Sprintf("SILVERMOBI - Votre code de validation : %04d", code), Message: fmt.Sprintf("SILVERMOBI - Votre code de validation : %04d", code),
}, },
) ); err != nil {
if err != nil {
log.Error().Err(err).Msg("issue sending verification code by sms") log.Error().Err(err).Msg("issue sending verification code by sms")
return err
} }
return nil return nil
} }
func (h *SilvermobiHandler) VerifyPhoneNumber(ctx context.Context, id string, phone_number string, verification_code string) error { func (h *SilverMobiHandler) VerifyPhoneNumber(ctx context.Context, id string, phoneNumber string,
verificationCode string) error {
request := &grpcapi.GetAccountRequest{ request := &grpcapi.GetAccountRequest{
Id: id, Id: id,
} }
resp, err := h.Services.MobilityAccounts.Client.GetAccount(ctx, request) resp, err := h.Services.MobilityAccounts.Client.GetAccount(ctx, request)
if err != nil { if err != nil {
return err return err
} }
@ -52,20 +57,21 @@ func (h *SilvermobiHandler) VerifyPhoneNumber(ctx context.Context, id string, ph
account_ := resp.Account account_ := resp.Account
log.Debug(). log.Debug().
Str("phone_number", phone_number). Str("phone_number", phoneNumber).
Str("account.phone_number", account_.Authentication.Local.PhoneNumber). Str("account.phone_number", account_.Authentication.Local.PhoneNumber).
Str("verification_code", verification_code). Str("verification_code", verificationCode).
Str("account.verification_code", account_.Authentication.Local.PhoneNumberValidation.ValidationCode). Str("account.verification_code", account_.Authentication.Local.PhoneNumberValidation.ValidationCode).
Msg("Verify phone number") Msg("Verify phone number")
if account_.Authentication.Local.PhoneNumber != phone_number || account_.Authentication.Local.PhoneNumberValidation.ValidationCode != verification_code { if account_.Authentication.Local.PhoneNumber != phoneNumber ||
return errors.New("cound not validate phone number : verification code mismatch") account_.Authentication.Local.PhoneNumberValidation.ValidationCode != verificationCode {
return errors.New("could not validate phone number : verification code mismatch")
} }
err = h.Services.MobilityAccounts.UpdatePhoneNumber( err = h.Services.MobilityAccounts.UpdatePhoneNumber(
ctx, ctx,
id, id,
phone_number, phoneNumber,
true, true,
"", "",
) )
@ -76,7 +82,7 @@ func (h *SilvermobiHandler) VerifyPhoneNumber(ctx context.Context, id string, ph
return nil return nil
} }
func (h *SilvermobiHandler) UpdateBirthDate(ctx context.Context, id string, birthdate string) error { func (h *SilverMobiHandler) UpdateBirthDate(ctx context.Context, id string, birthdate string) error {
err := h.Services.MobilityAccounts.UpdateAccountBirthDate(ctx, id, "silvermobi", birthdate) err := h.Services.MobilityAccounts.UpdateAccountBirthDate(ctx, id, "silvermobi", birthdate)
if err != nil { if err != nil {
return err return err
@ -84,65 +90,81 @@ func (h *SilvermobiHandler) UpdateBirthDate(ctx context.Context, id string, birt
return nil return nil
} }
func (h *SilvermobiHandler) SetAccountType(ctx context.Context, id string, accountType string) error { func (h *SilverMobiHandler) SetAccountType(ctx context.Context, id string, accountType string) error {
err := h.Services.MobilityAccounts.SetAccountType(ctx, id, accountType) err := h.Services.MobilityAccounts.SetAccountType(ctx, id, accountType)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func (h *SilvermobiHandler) GetAccountType(ctx context.Context, id string) (account_type string, err error) { func (h *SilverMobiHandler) GetAccountType(ctx context.Context, id string) (account_type string, err error) {
var resp *grpcapi.GetAccountResponse
request := &grpcapi.GetAccountRequest{ request := &grpcapi.GetAccountRequest{
Id: id, Id: id,
} }
resp, err := h.Services.MobilityAccounts.Client.GetAccount(ctx, request)
if err != nil { if resp, err = h.Services.MobilityAccounts.Client.GetAccount(ctx, request); err != nil {
return "", err return "", err
log.Error().Err(err).Msg("Failed get account type")
} }
account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType()) account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType())
if account.Type != "" { if account.Type != "" {
return account.Type, nil return account.Type, nil
} }
return "", errors.New("account type not set") return "", errors.New("account type not set")
} }
func (h *SilvermobiHandler) GetAccountPhone(ctx context.Context, id string) (phone_number string, err error) { func (h *SilverMobiHandler) GetAccountPhone(ctx context.Context, id string) (phoneNumber string, err error) {
var resp *grpcapi.GetAccountResponse
request := &grpcapi.GetAccountRequest{ request := &grpcapi.GetAccountRequest{
Id: id, Id: id,
} }
resp, err := h.Services.MobilityAccounts.Client.GetAccount(ctx, request)
if err != nil {
return "", err
log.Error().Err(err).Msg("Failed get account type")
}
account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType())
if account.PhoneNumber != "" {
if resp, err = h.Services.MobilityAccounts.Client.GetAccount(ctx, request); err != nil {
return "", err
}
account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType())
if account.PhoneNumber != "" {
return account.PhoneNumber, nil return account.PhoneNumber, nil
} }
return "", errors.New("invalid request ") return "", errors.New("invalid request ")
} }
func (h *SilvermobiHandler) CheckValidation(ctx context.Context, id string) (phone_validation, birth_validation, type_validation bool, err error) { func (h *SilverMobiHandler) CheckValidation(ctx context.Context, id string) (phone_validation, birth_validation, type_validation bool, err error) {
var resp *grpcapi.GetAccountResponse
request := &grpcapi.GetAccountRequest{ request := &grpcapi.GetAccountRequest{
Id: id, Id: id,
} }
resp, err := h.Services.MobilityAccounts.Client.GetAccount(ctx, request)
if err != nil { if resp, err = h.Services.MobilityAccounts.Client.GetAccount(ctx, request); err != nil {
return false, false, false, err return false, false, false, err
log.Error().Err(err).Msg("Failed get validation response")
} }
account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType()) account := h.Services.MobilityAccounts.ToAccountModel(resp.Account.ToStorageType())
phone_validation = false phone_validation = false
birth_validation = false birth_validation = false
type_validation = false type_validation = false
if account.LocalCredentials.PhoneNumberVerified { if account.LocalCredentials.PhoneNumberVerified {
phone_validation = true phone_validation = true
} }
if account.BirthDate != "" { if account.BirthDate != "" {
birth_validation = true birth_validation = true
} }
if account.Type != "" { if account.Type != "" {
type_validation = true type_validation = true
} }

View File

@ -2,15 +2,17 @@ package handler
import "context" import "context"
func (h *SilvermobiHandler) UpdatePassword(ctx context.Context, username string, password string) (response bool) { func (h *SilverMobiHandler) UpdatePassword(ctx context.Context, username string, password string) (response bool) {
account, err := h.Services.MobilityAccounts.GetAccountUsername(ctx, username, "silvermobi") account, err := h.Services.MobilityAccounts.GetAccountUsername(ctx, username, "silvermobi")
if err != nil { if err != nil {
return false return false
} }
result := h.Services.MobilityAccounts.UpdatePassword(ctx, account.ID, password) result := h.Services.MobilityAccounts.UpdatePassword(ctx, account.ID, password)
if result == true { if result == true {
return true return true
} else {
return false
} }
return false
} }

22
main.go
View File

@ -10,35 +10,39 @@ import (
) )
func main() { func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
cfg, err := ReadConfig() cfg, err := ReadConfig()
if err != nil { if err != nil {
panic(err) panic(err)
} }
var ( var (
grpc_enable = cfg.GetBool("services.external.grpc.enable") grpcEnable = cfg.GetBool("services.external.grpc.enable")
svc *services.ServiceHandler
stg storage.Storage
hdl *handler.SilverMobiHandler
) )
services, err := services.NewServicesHandler(cfg) if svc, err = services.NewServicesHandler(cfg); err != nil {
if err != nil {
log.Fatal().Err(err).Msg("failed starting services handler") log.Fatal().Err(err).Msg("failed starting services handler")
} }
storage, err := storage.NewPostgresqlStorage(cfg)
if err != nil { if stg, err = storage.NewPostgresqlStorage(cfg); err != nil {
log.Fatal().Err(err).Msg("failed starting storage handler") log.Fatal().Err(err).Msg("failed starting storage handler")
} }
handler, err := handler.NewSilvermobiHandler(cfg, services, storage) if hdl, err = handler.NewSilverMobiHandler(cfg, svc, stg); err != nil {
if err != nil {
log.Fatal().Err(err).Msg("failed starting ridygo handler") log.Fatal().Err(err).Msg("failed starting ridygo handler")
} }
failed := make(chan error) failed := make(chan error)
if grpc_enable { if grpcEnable {
log.Info().Msg("Running gRPC server") log.Info().Msg("Running gRPC server")
go grpcserver.Run(failed, cfg, handler) go grpcserver.Run(failed, cfg, hdl)
} }
err = <-failed err = <-failed

View File

@ -1,8 +1,9 @@
package models package models
import ( import (
"github.com/golang-jwt/jwt/v4"
"time" "time"
"github.com/golang-jwt/jwt/v4"
) )
type Account struct { type Account struct {
@ -36,11 +37,11 @@ type UserClaims struct {
} }
func (account Account) CreateToken(ttl time.Duration, key string) (token string, err error) { func (account Account) CreateToken(ttl time.Duration, key string) (token string, err error) {
expires_at := jwt.NewNumericDate(time.Now().Add(ttl)) expiresAt := jwt.NewNumericDate(time.Now().Add(ttl))
claims := UserClaims{ claims := UserClaims{
RegisteredClaims: jwt.RegisteredClaims{ RegisteredClaims: jwt.RegisteredClaims{
Subject: account.ID, Subject: account.ID,
ExpiresAt: expires_at, ExpiresAt: expiresAt,
}, },
} }

View File

@ -2,32 +2,48 @@ package grpcserver
import ( import (
"context" "context"
"strings"
"git.coopgo.io/coopgo-apps/silvermobi/models"
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"strings"
) )
func (s SilvermobiGRPCService) GetAccountInfo(ctx context.Context, req *grpcproto.AccountInfoRequest) (res *grpcproto.AccountInfoResponse, err error) { func (s SilvermobiGRPCService) GetAccountInfo(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.AccountInfoRequest) (res *grpcproto.AccountInfoResponse, err error) {
if !ok {
var (
md metadata.MD
account *models.Account
authHeader []string
ok bool
)
if md, ok = metadata.FromIncomingContext(ctx); !ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"]
authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
account, err := s.Handler.GetAccountInfos(context.Background(), id)
if account, err = s.Handler.GetAccountInfos(context.Background(), id); err != nil {
return nil, err
}
log.Info(). log.Info().
Str("ID", account.ID). Str("ID", account.ID).
Msg("GetAccountInfo") Msg("GetAccountInfo")
if err != nil {
return nil, err
}
return &grpcproto.AccountInfoResponse{ return &grpcproto.AccountInfoResponse{
FirstName: account.FirstName, FirstName: account.FirstName,
LastName: account.LastName, LastName: account.LastName,

View File

@ -8,13 +8,15 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func (s SilvermobiGRPCService) AuthLogin(ctx context.Context, req *grpcproto.AuthLoginRequest) (res *grpcproto.AuthLoginResponse, err error) { func (s SilvermobiGRPCService) AuthLogin(ctx context.Context,
req *grpcproto.AuthLoginRequest) (res *grpcproto.AuthLoginResponse, err error) {
var jwt string
log.Info(). log.Info().
Str("username", req.Username). Str("username", req.Username).
Msg("AuthLogin") Msg("AuthLogin")
jwt, err := s.Handler.Login(ctx, req.Username, req.Password) if jwt, err = s.Handler.Login(ctx, req.Username, req.Password); err != nil {
if err != nil {
log.Error(). log.Error().
Err(err). Err(err).
Str("username", req.Username). Str("username", req.Username).
@ -28,13 +30,16 @@ func (s SilvermobiGRPCService) AuthLogin(ctx context.Context, req *grpcproto.Aut
}, nil }, nil
} }
func (s SilvermobiGRPCService) AuthRegister(ctx context.Context, req *grpcproto.AuthRegisterRequest) (res *grpcproto.AuthRegisterResponse, err error) { func (s SilvermobiGRPCService) AuthRegister(ctx context.Context,
req *grpcproto.AuthRegisterRequest) (res *grpcproto.AuthRegisterResponse, err error) {
var jwt string
log.Info(). log.Info().
Str("username", req.Email). Str("username", req.Email).
Msg("AuthRegister") Msg("AuthRegister")
jwt, err := s.Handler.Register(ctx, req.Email, req.Password, req.Email, req.PhoneNumber, req.FirstName, req.LastName) if jwt, err = s.Handler.Register(ctx, req.Email, req.Password,
if err != nil { req.Email, req.PhoneNumber, req.FirstName, req.LastName); err != nil {
log.Error().Err(err).Msg("AuthRegister failed") log.Error().Err(err).Msg("AuthRegister failed")
return nil, errors.New("could not register user") return nil, errors.New("could not register user")
} }

View File

@ -2,44 +2,57 @@ package grpcserver
import ( import (
"context" "context"
"strings"
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"strings"
) )
func (s SilvermobiGRPCService) PutFirebaseToken(ctx context.Context, req *grpcproto.FirebaseTokenRequest) (resp *grpcproto.FirebaseTokenResponse, err error) { func (s SilvermobiGRPCService) PutFirebaseToken(ctx context.Context,
req *grpcproto.FirebaseTokenRequest) (resp *grpcproto.FirebaseTokenResponse, err error) {
var (
ok bool
md metadata.MD
authHeader []string
)
if req.Token == "" || req.DevicePlatform == "" { if req.Token == "" || req.DevicePlatform == "" {
return &grpcproto.FirebaseTokenResponse{ return &grpcproto.FirebaseTokenResponse{
Result: false, Result: false,
}, nil }, nil
} }
md, ok := metadata.FromIncomingContext(ctx)
if !ok { if md, ok = metadata.FromIncomingContext(ctx); !ok {
return &grpcproto.FirebaseTokenResponse{ return &grpcproto.FirebaseTokenResponse{
Result: false, Result: false,
}, status.Errorf(codes.Unauthenticated, "Missing metadata") }, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"]
authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return &grpcproto.FirebaseTokenResponse{ return &grpcproto.FirebaseTokenResponse{
Result: false, Result: false,
}, status.Errorf(codes.Unauthenticated, "Missing authorization header") }, status.Errorf(codes.Unauthenticated, "Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
log.Info(). log.Info().
Str("User ID", id). Str("User ID", id).
Msg("PutFirebaseToken") Msg("PutFirebaseToken")
err = s.Handler.PutFirebase(context.Background(), id, req.Token, req.DevicePlatform)
if err != nil { if err = s.Handler.PutFirebase(context.Background(), id, req.Token, req.DevicePlatform); err != nil {
return &grpcproto.FirebaseTokenResponse{ return &grpcproto.FirebaseTokenResponse{
Result: false, Result: false,
}, status.Errorf(codes.Unknown, "Database error") }, status.Errorf(codes.Unknown, "Database error")
} }
return &grpcproto.FirebaseTokenResponse{ return &grpcproto.FirebaseTokenResponse{
Result: true, Result: true,
}, nil }, nil

View File

@ -2,26 +2,30 @@ package grpcserver
import ( import (
"context" "context"
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func (s SilvermobiGRPCService) ForgetAccount(ctx context.Context, req *grpcproto.ForgetAccountRequest) (res *grpcproto.ForgetAccountResponse, err error) { func (s SilvermobiGRPCService) ForgetAccount(ctx context.Context,
req *grpcproto.ForgetAccountRequest) (res *grpcproto.ForgetAccountResponse, err error) {
log.Info(). log.Info().
Str("username", req.Username). Str("username", req.Username).
Str("namespace", req.Namespace). Str("namespace", req.Namespace).
Msg("ForgetAccount") Msg("ForgetAccount")
response, access_code := s.Handler.ForgetAccount(ctx, req.Username, req.Namespace)
response, accessCode := s.Handler.ForgetAccount(ctx, req.Username, req.Namespace)
if response == true { if response == true {
return &grpcproto.ForgetAccountResponse{ return &grpcproto.ForgetAccountResponse{
Response: true, Response: true,
AccessCode: access_code, AccessCode: accessCode,
}, nil }, nil
} else { }
return &grpcproto.ForgetAccountResponse{ return &grpcproto.ForgetAccountResponse{
Response: false, Response: false,
AccessCode: "", AccessCode: "",
}, nil }, nil
}
} }

View File

@ -2,41 +2,39 @@ package grpcserver
import ( import (
"context" "context"
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/paulmach/orb/geojson" "github.com/paulmach/orb/geojson"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"io"
) )
func (s SilvermobiGRPCService) GeoAutocomplete(ctx context.Context, in *grpcproto.GeoAutocompleteRequest) (resp *grpcproto.GeoAutocompleteResponse, err error) { func (s SilvermobiGRPCService) GeoAutocomplete(ctx context.Context,
in *grpcproto.GeoAutocompleteRequest) (resp *grpcproto.GeoAutocompleteResponse, err error) {
var (
results *geojson.FeatureCollection
rawfc []byte
)
log.Info(). log.Info().
Str("text", in.Text). Str("text", in.Text).
Msg("GeoAutocompleteRequest") Msg("GeoAutocompleteRequest")
requestid := uuid.NewString()
log.Debug().Str("requestid", requestid).Msg("GRPC GeoAutocomplete start")
if err == io.EOF { requestID := uuid.NewString()
log.Debug().Str("requestid", requestid).Msg("GRPC GeoAutocomplete EOF")
log.Debug().Str("requestID", requestID).Msg("GRPC GeoAutocomplete start")
if results, err = s.Handler.GeoAutocomplete(in.Text); err != nil {
log.Error().Str("requestID", requestID).Err(err).Msg("GRPC GeoAutocomplete geocoding error")
return nil, err return nil, err
} }
if err != nil { if rawfc, err = results.MarshalJSON(); err != nil {
log.Error().Str("requestid", requestid).Err(err).Msg("GRPC GeoAutocomplete other error") log.Error().Str("requestID", requestID).Err(err).Msg("GRPC GeoAutocomplete " +
return nil, err "protocol buffer conversion error")
}
results, err := s.Handler.GeoAutocomplete(in.Text, in.Lat, in.Lon)
if err != nil {
log.Error().Str("requestid", requestid).Err(err).Msg("GRPC GeoAutocomplete geocoding error")
return nil, err
}
rawfc, err := results.MarshalJSON()
if err != nil {
log.Error().Str("requestid", requestid).Err(err).Msg("GRPC GeoAutocomplete protocol buffer conversion error")
return nil, err return nil, err
} }
@ -50,50 +48,58 @@ func (s SilvermobiGRPCService) GeoAutocomplete(ctx context.Context, in *grpcprot
} }
func (s SilvermobiGRPCService) GeoRoute(ctx context.Context, req *grpcproto.GeoRouteRequest) (*grpcproto.GeoRouteResponse, error) { func (s SilvermobiGRPCService) GeoRoute(ctx context.Context,
locations_raw, ok := req.Locations.(*grpcproto.GeoRouteRequest_LocationsRaw) req *grpcproto.GeoRouteRequest) (*grpcproto.GeoRouteResponse, error) {
locationsRaw, ok := req.Locations.(*grpcproto.GeoRouteRequest_LocationsRaw)
if !ok { if !ok {
return nil, status.Errorf(codes.InvalidArgument, "could not read departure") return nil, status.Errorf(codes.InvalidArgument, "could not read departure")
} }
locations, err := geojson.UnmarshalFeatureCollection([]byte(locations_raw.LocationsRaw)) locations, err := geojson.UnmarshalFeatureCollection([]byte(locationsRaw.LocationsRaw))
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
route, err := s.Handler.GeoRoute(*locations) if _, err = s.Handler.GeoRoute(*locations); err != nil {
if err != nil {
return nil, err return nil, err
} }
route, _ := s.Handler.GeoRoute(*locations)
return &grpcproto.GeoRouteResponse{ return &grpcproto.GeoRouteResponse{
Polyline: route.Polyline.String(), Polyline: route.Polyline.String(),
}, nil }, nil
} }
func (s SilvermobiGRPCService) GeoRouteWithReturn(ctx context.Context, req *grpcproto.GeoRouteWithReturnRequest) (*grpcproto.GeoRouteWithReturnResponse, error) { func (s SilvermobiGRPCService) GeoRouteWithReturn(ctx context.Context,
locations_raw, ok := req.Locations.(*grpcproto.GeoRouteWithReturnRequest_LocationsRaw) req *grpcproto.GeoRouteWithReturnRequest) (*grpcproto.GeoRouteWithReturnResponse, error) {
locationsRaw, ok := req.Locations.(*grpcproto.GeoRouteWithReturnRequest_LocationsRaw)
if !ok { if !ok {
return nil, status.Errorf(codes.InvalidArgument, "could not read departure") return nil, status.Errorf(codes.InvalidArgument, "could not read departure")
} }
locations, err := geojson.UnmarshalFeatureCollection([]byte(locations_raw.LocationsRaw)) locations, err := geojson.UnmarshalFeatureCollection([]byte(locationsRaw.LocationsRaw))
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
route, err := s.Handler.GeoRoute(*locations) if _, err = s.Handler.GeoRoute(*locations); err != nil {
if err != nil {
return nil, err return nil, err
} }
return_route, err := s.Handler.GeoReturnRoute(*locations) route, _ := s.Handler.GeoRoute(*locations)
if err != nil {
if _, err = s.Handler.GeoReturnRoute(*locations); err != nil {
return nil, err return nil, err
} }
returnRoute, _ := s.Handler.GeoReturnRoute(*locations)
return &grpcproto.GeoRouteWithReturnResponse{ return &grpcproto.GeoRouteWithReturnResponse{
Polyline: route.Polyline.String(), Polyline: route.Polyline.String(),
ReturnPolyline: return_route.Polyline.String(), ReturnPolyline: returnRoute.Polyline.String(),
}, nil }, nil
} }

View File

@ -4,28 +4,38 @@ import (
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "strings"
"time"
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"strings"
"time"
) )
func (s SilvermobiGRPCService) SetPhoneNumber(ctx context.Context, req *grpcproto.SetPhoneNumberRequest) (res *grpcproto.SetPhoneNumberResponse, err error) { func (s SilvermobiGRPCService) SetPhoneNumber(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.SetPhoneNumberRequest) (res *grpcproto.SetPhoneNumberResponse, err error) {
if !ok {
var (
md metadata.MD
authHeader []string
ok bool
)
if md, ok = metadata.FromIncomingContext(ctx); !ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"] authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
log.Info(). log.Info().
Str("User ID", id). Str("User ID", id).
Msg("SetPhoneNumber") Msg("SetPhoneNumber")
@ -40,20 +50,33 @@ func (s SilvermobiGRPCService) SetPhoneNumber(ctx context.Context, req *grpcprot
return &grpcproto.SetPhoneNumberResponse{Ok: true}, nil return &grpcproto.SetPhoneNumberResponse{Ok: true}, nil
} }
func (s SilvermobiGRPCService) VerifyPhoneNumber(ctx context.Context, req *grpcproto.VerifyPhoneNumberRequest) (res *grpcproto.VerifyPhoneNumberResponse, err error) { func (s SilvermobiGRPCService) VerifyPhoneNumber(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.VerifyPhoneNumberRequest) (res *grpcproto.VerifyPhoneNumberResponse, err error) {
if !ok {
var (
md metadata.MD
authHeader []string
ok bool
)
if md, ok = metadata.FromIncomingContext(ctx); !ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"]
authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated,
"Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
log.Info(). log.Info().
Str("User ID", id). Str("User ID", id).
Msg("VerifyPhoneNumber") Msg("VerifyPhoneNumber")
if err = s.Handler.VerifyPhoneNumber( if err = s.Handler.VerifyPhoneNumber(
context.Background(), context.Background(),
id, id,
@ -66,21 +89,31 @@ func (s SilvermobiGRPCService) VerifyPhoneNumber(ctx context.Context, req *grpcp
return &grpcproto.VerifyPhoneNumberResponse{Ok: true}, nil return &grpcproto.VerifyPhoneNumberResponse{Ok: true}, nil
} }
func (s SilvermobiGRPCService) SetBirthDate(ctx context.Context, req *grpcproto.BirthDateRequest) (res *grpcproto.BirthDateResponse, err error) { func (s SilvermobiGRPCService) SetBirthDate(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.BirthDateRequest) (res *grpcproto.BirthDateResponse, err error) {
if !ok {
var (
md metadata.MD
authHeader []string
ok bool
)
if md, ok = metadata.FromIncomingContext(ctx); !ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"] authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
log.Info(). log.Info().
Str("User ID", id). Str("User ID", id).
Msg("SetBirthDate") Msg("SetBirthDate")
birthdate := time.Unix(req.Birthdate.Seconds, int64(req.Birthdate.Nanos)).UTC() birthdate := time.Unix(req.Birthdate.Seconds, int64(req.Birthdate.Nanos)).UTC()
birthdateString := birthdate.Format("2006-01-02T15:04:05Z") birthdateString := birthdate.Format("2006-01-02T15:04:05Z")
if err = s.Handler.UpdateBirthDate(ctx, id, birthdateString); err != nil { if err = s.Handler.UpdateBirthDate(ctx, id, birthdateString); err != nil {
@ -92,55 +125,85 @@ func (s SilvermobiGRPCService) SetBirthDate(ctx context.Context, req *grpcproto.
}, nil }, nil
} }
func (s SilvermobiGRPCService) SetAccountType(ctx context.Context, req *grpcproto.AccountTypeRequest) (res *grpcproto.AccountTypeResponse, err error) { func (s SilvermobiGRPCService) SetAccountType(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.AccountTypeRequest) (res *grpcproto.AccountTypeResponse, err error) {
if !ok {
var (
md metadata.MD
authHeader []string
ok bool
)
if md, ok = metadata.FromIncomingContext(ctx); !ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"]
authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated,
"Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
log.Info(). log.Info().
Str("User ID", id). Str("User ID", id).
Msg("SetAccountType") Msg("SetAccountType")
if req.GetType() != grpcproto.AccountTypeRequest_PASSENGER && req.GetType() != grpcproto.AccountTypeRequest_DRIVER { if req.GetType() != grpcproto.AccountTypeRequest_PASSENGER && req.GetType() != grpcproto.AccountTypeRequest_DRIVER {
return nil, status.Errorf(codes.InvalidArgument, "Type should be PASSENGER or 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 { if err = s.Handler.SetAccountType(ctx, id, req.GetType().String()); err != nil {
return nil, err return nil, err
} }
return &grpcproto.AccountTypeResponse{ return &grpcproto.AccountTypeResponse{
Ok: true, Ok: true,
}, nil }, nil
} }
func (s SilvermobiGRPCService) GetAccountType(ctx context.Context, req *grpcproto.AccountTypeRequest) (res *grpcproto.AccountTypeResponse, err error) { func (s SilvermobiGRPCService) GetAccountType(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.AccountTypeRequest) (res *grpcproto.AccountTypeResponse, err error) {
if !ok {
var (
md metadata.MD
authHeader []string
ok bool
accountType string
responseType grpcproto.AccountTypeResponse_AccountType
)
if md, ok = metadata.FromIncomingContext(ctx); !ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"]
authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
log.Info(). log.Info().
Str("User ID", id). Str("User ID", id).
Msg("GetAccountType") Msg("GetAccountType")
if req.Request == false || !req.Request { if req.Request == false || !req.Request {
return nil, status.Errorf(codes.InvalidArgument, "request arg should be true") return nil, status.Errorf(codes.InvalidArgument, "request arg should be true")
} }
account_type, err := s.Handler.GetAccountType(ctx, id)
if err != nil { if accountType, err = s.Handler.GetAccountType(ctx, id); err != nil {
return nil, err return nil, err
} }
var responseType grpcproto.AccountTypeResponse_AccountType
switch account_type { switch accountType {
case "PASSENGER": case "PASSENGER":
responseType = grpcproto.AccountTypeResponse_PASSENGER responseType = grpcproto.AccountTypeResponse_PASSENGER
case "DRIVER": case "DRIVER":
@ -157,45 +220,66 @@ func (s SilvermobiGRPCService) GetAccountType(ctx context.Context, req *grpcprot
} }
func (s SilvermobiGRPCService) GetValidation(ctx context.Context, req *grpcproto.ValidationRequest) (res *grpcproto.ValidationResponse, err error) { func (s SilvermobiGRPCService) GetValidation(ctx context.Context,
md, ok := metadata.FromIncomingContext(ctx) req *grpcproto.ValidationRequest) (res *grpcproto.ValidationResponse, err error) {
if !ok {
var (
md metadata.MD
authHeader []string
ok, phoneValidation, birthValidation, typeValidation bool
)
if md, ok = metadata.FromIncomingContext(ctx); ok {
return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") return nil, status.Errorf(codes.Unauthenticated, "Missing metadata")
} }
authHeader, ok := md["authorization"]
authHeader, ok = md["authorization"]
if !ok || len(authHeader) == 0 { if !ok || len(authHeader) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header")
} }
tokenString := strings.TrimPrefix(authHeader[0], "Bearer ") tokenString := strings.TrimPrefix(authHeader[0], "Bearer ")
id := ExtractIdFromToken(tokenString) id := ExtractIdFromToken(tokenString)
fmt.Println(id)
phone_validation, birth_validation, type_validation, err := s.Handler.CheckValidation(ctx, id) if phoneValidation, birthValidation, typeValidation, err = s.Handler.CheckValidation(ctx, id); err != nil {
if err != nil {
return nil, err return nil, err
} }
return &grpcproto.ValidationResponse{ return &grpcproto.ValidationResponse{
Phone: phone_validation, Phone: phoneValidation,
Birthdate: birth_validation, Birthdate: birthValidation,
Type: type_validation, Type: typeValidation,
}, nil }, nil
} }
func ExtractIdFromToken(tokenString string) string { func ExtractIdFromToken(tokenString string) string {
var (
err error
payloadBytes []byte
payloadMap map[string]interface{}
id string
ok bool
)
parts := strings.Split(tokenString, ".") parts := strings.Split(tokenString, ".")
if len(parts) != 3 { if len(parts) != 3 {
return "" return ""
} }
payloadBytes, err := base64.RawStdEncoding.DecodeString(parts[1])
if err != nil { if payloadBytes, err = base64.RawStdEncoding.DecodeString(parts[1]); err != nil {
return "" return ""
} }
var payloadMap map[string]interface{}
if err := json.Unmarshal(payloadBytes, &payloadMap); err != nil { if err = json.Unmarshal(payloadBytes, &payloadMap); err != nil {
return "" return ""
} }
id, ok := payloadMap["sub"].(string)
if !ok { if id, ok = payloadMap["sub"].(string); !ok {
return "" return ""
} }
return id return id
} }

View File

@ -79,18 +79,18 @@ func StreamAuthServerInterceptor(authFunc grpc_auth.AuthFunc) grpc.StreamServerI
type SilvermobiGRPCService struct { type SilvermobiGRPCService struct {
Config *viper.Viper Config *viper.Viper
Handler *handler.SilvermobiHandler Handler *handler.SilverMobiHandler
grpcproto.UnimplementedSilvermobiGRPCServer grpcproto.UnimplementedSilvermobiGRPCServer
} }
type SolidarityService struct { type SolidarityService struct {
Config *viper.Viper Config *viper.Viper
Handler *handler.SilvermobiHandler Handler *handler.SilverMobiHandler
SolidarityClient grpcproto.SolidarityServiceClient SolidarityClient grpcproto.SolidarityServiceClient
grpcproto.UnimplementedSolidarityServiceServer // Add this client grpcproto.UnimplementedSolidarityServiceServer // Add this client
} }
func NewSolidarityService(cfg *viper.Viper, handler *handler.SilvermobiHandler) SolidarityService { func NewSolidarityService(cfg *viper.Viper, handler *handler.SilverMobiHandler) SolidarityService {
solidarityServiceAddress := cfg.GetString("solidarity_service.address") solidarityServiceAddress := cfg.GetString("solidarity_service.address")
conn, err := grpc.Dial(solidarityServiceAddress, grpc.WithInsecure()) conn, err := grpc.Dial(solidarityServiceAddress, grpc.WithInsecure())
if err != nil { if err != nil {
@ -105,14 +105,14 @@ func NewSolidarityService(cfg *viper.Viper, handler *handler.SilvermobiHandler)
} }
} }
func NewSilvermobiGRPCService(cfg *viper.Viper, handler *handler.SilvermobiHandler) SilvermobiGRPCService { func NewSilvermobiGRPCService(cfg *viper.Viper, handler *handler.SilverMobiHandler) SilvermobiGRPCService {
return SilvermobiGRPCService{ return SilvermobiGRPCService{
Config: cfg, Config: cfg,
Handler: handler, Handler: handler,
} }
} }
func Run(done chan error, cfg *viper.Viper, handler *handler.SilvermobiHandler) { func Run(done chan error, cfg *viper.Viper, handler *handler.SilverMobiHandler) {
var ( var (
address = cfg.GetString("services.external.grpc.ip") + ":" + cfg.GetString("services.external.grpc.port") address = cfg.GetString("services.external.grpc.ip") + ":" + cfg.GetString("services.external.grpc.port")
jwt_secret = cfg.GetString("identification.local.jwt_secret") jwt_secret = cfg.GetString("identification.local.jwt_secret")

View File

@ -2,76 +2,106 @@ package grpcserver
import ( import (
"context" "context"
"fmt"
"git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func (s *SolidarityService) SetDriverRegularAvailabilities(ctx context.Context, req *proto.DriverRegularAvailabilities) (resp *proto.DriverAvailabilitiesResponse, err error) { func (s *SolidarityService) SetDriverRegularAvailabilities(ctx context.Context,
req *proto.DriverRegularAvailabilities) (resp *proto.DriverAvailabilitiesResponse, err error) {
log.Info(). log.Info().
Str("Driver ID", req.DriverRequest.Driver.Id). Str("Driver ID", req.DriverRequest.Driver.Id).
Msg("SetDriverRegularAvailabilities") Msg("SetDriverRegularAvailabilities")
resp, err = s.SolidarityClient.SetDriverRegularAvailabilities(ctx, req) resp, err = s.SolidarityClient.SetDriverRegularAvailabilities(ctx, req)
return resp, err return resp, err
} }
func (s *SolidarityService) SetDriverPunctualAvailabilities(ctx context.Context, req *proto.DriverPunctualAvailabilities) (resp *proto.DriverAvailabilitiesResponse, err error) { func (s *SolidarityService) SetDriverPunctualAvailabilities(ctx context.Context,
req *proto.DriverPunctualAvailabilities) (resp *proto.DriverAvailabilitiesResponse, err error) {
log.Info(). log.Info().
Str("Driver ID", req.DriverRequest.Driver.Id). Str("Driver ID", req.DriverRequest.Driver.Id).
Msg("SetDriverRegularAvailabilities") Msg("SetDriverRegularAvailabilities")
resp, err = s.SolidarityClient.SetDriverPunctualAvailabilities(ctx, req) resp, err = s.SolidarityClient.SetDriverPunctualAvailabilities(ctx, req)
return resp, err return resp, err
} }
func (s *SolidarityService) CreateBooking(ctx context.Context, req *proto.CreateBookingRequest) (resp *proto.CreateBookingResponse, err error) { func (s *SolidarityService) CreateBooking(ctx context.Context,
req *proto.CreateBookingRequest) (resp *proto.CreateBookingResponse, err error) {
log.Info(). log.Info().
Str("Booking ID", req.Booking.Id). Str("Booking ID", req.Booking.Id).
Msg("CreateBooking") Msg("CreateBooking")
resp, err = s.SolidarityClient.CreateBooking(ctx, req)
if err == nil { if resp, err = s.SolidarityClient.CreateBooking(ctx, req); err != nil {
_ = s.Handler.SendNotification(req.Booking.DriverId, "Silvermobi", "Vous avez reçu une demande de trajet. \n Pour plus de détails, veuillez consulter l'interface \"Mes Trajets\" dans l'application SilverMobi.") return nil, err
err = s.Handler.SendEmail(req.Booking.DriverId, "Silvermobi", "Vous avez reçu une demande de trajet. \n Pour plus de détails, veuillez consulter l'interface \"Mes Trajets\" dans l'application SilverMobi.")
fmt.Println(err)
} }
if err = s.Handler.SendNotification(req.Booking.DriverId,
"Silvermobi", "Vous avez reçu une demande de trajet. "+
"\n Pour plus de détails, veuillez consulter"+
" l'interface \"Mes Trajets\" dans l'application SilverMobi."); err != nil {
return nil, err
}
if err = s.Handler.SendEmail(req.Booking.DriverId, "Silvermobi",
"Vous avez reçu une demande de trajet. \n Pour plus de détails, "+
"veuillez consulter l'interface \"Mes Trajets\" dans l'application SilverMobi."); err != nil {
return nil, err
}
return resp, err return resp, err
} }
func (s *SolidarityService) UpdateBooking(ctx context.Context, req *proto.UpdateBookingRequest) (resp *proto.UpdateBookingResponse, err error) { func (s *SolidarityService) UpdateBooking(ctx context.Context,
req *proto.UpdateBookingRequest) (resp *proto.UpdateBookingResponse, err error) {
log.Info(). log.Info().
Str("Booking ID", req.BookingId). Str("Booking ID", req.BookingId).
Msg("UpdateBooking") Msg("UpdateBooking")
resp, err = s.SolidarityClient.UpdateBooking(ctx, req) resp, err = s.SolidarityClient.UpdateBooking(ctx, req)
return resp, err return resp, err
} }
func (s *SolidarityService) GetBooking(ctx context.Context, req *proto.GetBookingRequest) (resp *proto.GetBookingResponse, err error) { func (s *SolidarityService) GetBooking(ctx context.Context,
req *proto.GetBookingRequest) (resp *proto.GetBookingResponse, err error) {
log.Info(). log.Info().
Str("Booking ID", req.BookingId). Str("Booking ID", req.BookingId).
Msg("GetBooking") Msg("GetBooking")
resp, err = s.SolidarityClient.GetBooking(ctx, req) resp, err = s.SolidarityClient.GetBooking(ctx, req)
return resp, err return resp, err
} }
func (s *SolidarityService) GetBookingsByStatus(ctx context.Context, req *proto.GetBookingsByStatusRequest) (resp *proto.GetBookingsByStatusResponse, err error) { func (s *SolidarityService) GetBookingsByStatus(ctx context.Context,
req *proto.GetBookingsByStatusRequest) (resp *proto.GetBookingsByStatusResponse, err error) {
log.Info(). log.Info().
Str("User ID", req.UserId). Str("User ID", req.UserId).
Msg("GetBookingByStatus") Msg("GetBookingByStatus")
resp, err = s.SolidarityClient.GetBookingsByStatus(ctx, req) resp, err = s.SolidarityClient.GetBookingsByStatus(ctx, req)
return resp, err return resp, err
} }
func (s *SolidarityService) DriverJourneys(ctx context.Context, req *proto.DriverJourneysRequest) (resp *proto.DriverJourneysResponse, err error) { func (s *SolidarityService) DriverJourneys(ctx context.Context,
req *proto.DriverJourneysRequest) (resp *proto.DriverJourneysResponse, err error) {
log.Info(). log.Info().
Str("Address", req.Departure.Address). Str("Address", req.Departure.Address).
Msg("DriverJourneys") Msg("DriverJourneys")
resp, err = s.SolidarityClient.DriverJourneys(ctx, req) resp, err = s.SolidarityClient.DriverJourneys(ctx, req)
return resp, err return resp, err
} }
func (s *SolidarityService) SetPassengerTrip(ctx context.Context, req *proto.PassengerTripRequest) (resp *proto.PassengerTripResponse, err error) { func (s *SolidarityService) SetPassengerTrip(ctx context.Context,
req *proto.PassengerTripRequest) (resp *proto.PassengerTripResponse, err error) {
log.Info(). log.Info().
Str("Passenger ID", req.Passenger.Id). Str("Passenger ID", req.Passenger.Id).
Msg("SetPassengerTrip") Msg("SetPassengerTrip")
resp, err = s.SolidarityClient.SetPassengerTrip(ctx, req) resp, err = s.SolidarityClient.SetPassengerTrip(ctx, req)
return resp, err return resp, err
} }

View File

@ -2,22 +2,27 @@ package grpcserver
import ( import (
"context" "context"
grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto" grpcproto "git.coopgo.io/coopgo-apps/silvermobi/servers/grpcapi/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func (s SilvermobiGRPCService) UpdatePassword(ctx context.Context, req *grpcproto.UpdatePasswordRequest) (res *grpcproto.UpdatePasswordResponse, err error) { func (s SilvermobiGRPCService) UpdatePassword(ctx context.Context,
req *grpcproto.UpdatePasswordRequest) (res *grpcproto.UpdatePasswordResponse, err error) {
log.Info(). log.Info().
Str("username", req.Email). Str("username", req.Email).
Msg("Update Password") Msg("Update Password")
result := s.Handler.UpdatePassword(ctx, req.Email, req.Password) result := s.Handler.UpdatePassword(ctx, req.Email, req.Password)
if result == true { if result {
return &grpcproto.UpdatePasswordResponse{ return &grpcproto.UpdatePasswordResponse{
Response: true, Response: true,
}, nil }, nil
} else { }
return &grpcproto.UpdatePasswordResponse{ return &grpcproto.UpdatePasswordResponse{
Response: false, Response: false,
}, nil }, nil
}
} }

View File

@ -2,6 +2,7 @@ package services
import ( import (
"context" "context"
"git.coopgo.io/coopgo-apps/silvermobi/models" "git.coopgo.io/coopgo-apps/silvermobi/models"
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
ma "git.coopgo.io/coopgo-platform/mobility-accounts/storage" ma "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
@ -42,6 +43,7 @@ func (s MobilityAccountService) Login(ctx context.Context, username, password, n
func (s MobilityAccountService) UpdateAccountData(ctx context.Context, id string, data map[string]any) error { func (s MobilityAccountService) UpdateAccountData(ctx context.Context, id string, data map[string]any) error {
d, err := structpb.NewStruct(data) d, err := structpb.NewStruct(data)
if err != nil { if err != nil {
return err return err
} }
@ -63,14 +65,17 @@ func (s MobilityAccountService) UpdatePassword(ctx context.Context, id string, p
Id: id, Id: id,
Password: password, Password: password,
}) })
if err == nil {
return true if err != nil {
} else {
return false return false
} }
return true
} }
func (s MobilityAccountService) GetAccountUsername(ctx context.Context, username string, namespace string) (*models.Account, error) { func (s MobilityAccountService) GetAccountUsername(ctx context.Context,
username string, namespace string) (*models.Account, error) {
resp, err := s.Client.GetAccountUsername(ctx, &mobilityaccounts.GetAccountUsernameRequest{ resp, err := s.Client.GetAccountUsername(ctx, &mobilityaccounts.GetAccountUsernameRequest{
Username: username, Username: username,
Namespace: namespace, Namespace: namespace,
@ -78,17 +83,22 @@ func (s MobilityAccountService) GetAccountUsername(ctx context.Context, username
if err != nil { if err != nil {
return nil, err return nil, err
} }
return s.ToAccountModel(resp.Account.ToStorageType()), nil return s.ToAccountModel(resp.Account.ToStorageType()), nil
} }
func (s MobilityAccountService) Register(ctx context.Context, username string, password string, email string, phone_number string, data map[string]any, namespace string) (*models.Account, error) { func (s MobilityAccountService) Register(ctx context.Context, username string, password string,
email string, phoneNumber string, data map[string]any, namespace string) (*models.Account, error) {
var resp *mobilityaccounts.RegisterResponse
account := &ma.Account{ account := &ma.Account{
Authentication: ma.AccountAuth{ Authentication: ma.AccountAuth{
Local: ma.LocalAuth{ Local: ma.LocalAuth{
Username: username, Username: username,
Password: password, Password: password,
Email: email, Email: email,
PhoneNumber: phone_number, PhoneNumber: phoneNumber,
}, },
}, },
Namespace: namespace, Namespace: namespace,
@ -100,28 +110,26 @@ func (s MobilityAccountService) Register(ctx context.Context, username string, p
return nil, err return nil, err
} }
resp, err := s.Client.Register(ctx, &mobilityaccounts.RegisterRequest{ if resp, err = s.Client.Register(ctx, &mobilityaccounts.RegisterRequest{
Account: acc, Account: acc,
}) }); err != nil {
if err != nil {
return nil, err return nil, err
} }
return s.ToAccountModel(resp.Account.ToStorageType()), nil return s.ToAccountModel(resp.Account.ToStorageType()), nil
} }
func (s MobilityAccountService) UpdatePhoneNumber(ctx context.Context, accountid string, phone_number string, verified bool, verification_code string) error { func (s MobilityAccountService) UpdatePhoneNumber(ctx context.Context, accountID string, phoneNumber string,
_, err := s.Client.UpdatePhoneNumber( verified bool, verificationCode string) error {
if _, err := s.Client.UpdatePhoneNumber(
ctx, ctx,
&mobilityaccounts.UpdatePhoneNumberRequest{ &mobilityaccounts.UpdatePhoneNumberRequest{
Id: accountid, Id: accountID,
PhoneNumber: phone_number, PhoneNumber: phoneNumber,
Verified: verified, Verified: verified,
VerificationCode: verification_code, VerificationCode: verificationCode,
}, },
) ); err != nil {
if err != nil {
return err return err
} }
@ -129,20 +137,30 @@ func (s MobilityAccountService) UpdatePhoneNumber(ctx context.Context, accountid
} }
func (s MobilityAccountService) SetAccountType(ctx context.Context, id string, accountType string) error { func (s MobilityAccountService) SetAccountType(ctx context.Context, id string, accountType string) error {
account, err := s.Client.GetAccount(ctx, &mobilityaccounts.GetAccountRequest{
var (
account *mobilityaccounts.GetAccountResponse
err error
)
if account, err = s.Client.GetAccount(ctx, &mobilityaccounts.GetAccountRequest{
Id: id, Id: id,
}) }); err != nil {
if err != nil {
return err return err
} }
data := make(map[string]interface{}) data := make(map[string]interface{})
data["type"] = accountType data["type"] = accountType
dataStruct := &structpb.Struct{ dataStruct := &structpb.Struct{
Fields: make(map[string]*structpb.Value), Fields: make(map[string]*structpb.Value),
} }
for key, value := range data { for key, value := range data {
stringValue, ok := value.(string) stringValue, ok := value.(string)
if !ok { if !ok {
continue continue
} }
@ -153,22 +171,34 @@ func (s MobilityAccountService) SetAccountType(ctx context.Context, id string, a
}, },
} }
} }
account.Account.Data = dataStruct account.Account.Data = dataStruct
_, err = s.Client.UpdateData(ctx, &mobilityaccounts.UpdateDataRequest{
if _, err = s.Client.UpdateData(ctx, &mobilityaccounts.UpdateDataRequest{
Account: account.Account, Account: account.Account,
}) }); err != nil {
if err != nil {
return err return err
} }
return nil return nil
} }
func (s MobilityAccountService) UpdateAccountBirthDate(ctx context.Context, id string, namespace string, birthdate string) error { func (s MobilityAccountService) UpdateAccountBirthDate(ctx context.Context, id string,
account, err := s.Client.GetAccount(ctx, &mobilityaccounts.GetAccountRequest{ namespace string, birthdate string) error {
var (
account *mobilityaccounts.GetAccountResponse
err error
)
if account, err = s.Client.GetAccount(ctx, &mobilityaccounts.GetAccountRequest{
Id: id, Id: id,
}) }); err != nil {
return err
}
data := make(map[string]interface{}) data := make(map[string]interface{})
data["birthdate"] = birthdate data["birthdate"] = birthdate
dataStruct := &structpb.Struct{ dataStruct := &structpb.Struct{
@ -177,6 +207,7 @@ func (s MobilityAccountService) UpdateAccountBirthDate(ctx context.Context, id s
for key, value := range data { for key, value := range data {
stringValue, ok := value.(string) stringValue, ok := value.(string)
if !ok { if !ok {
continue continue
} }
@ -187,47 +218,56 @@ func (s MobilityAccountService) UpdateAccountBirthDate(ctx context.Context, id s
}, },
} }
} }
account.Account.Data = dataStruct account.Account.Data = dataStruct
_, err = s.Client.UpdateData(ctx, &mobilityaccounts.UpdateDataRequest{
if _, err = s.Client.UpdateData(ctx, &mobilityaccounts.UpdateDataRequest{
Account: account.Account, Account: account.Account,
}) }); err != nil {
if err != nil {
return err return err
} }
return nil return nil
} }
func (s MobilityAccountService) ToAccountModel(account ma.Account) *models.Account { func (s MobilityAccountService) ToAccountModel(account ma.Account) *models.Account {
first_name := account.Data["first_name"].(string)
last_name := account.Data["last_name"].(string) var (
birth_date, ok := account.Data["birthdate"].(string) accountType, birthDate, phoneNumber, email string
if !ok { ok bool
birth_date = "" )
firstName := account.Data["first_name"].(string)
lastName := account.Data["last_name"].(string)
if birthDate, ok = account.Data["birthdate"].(string); !ok {
birthDate = ""
} }
accountType, ok := account.Data["type"].(string)
if !ok { if accountType, ok = account.Data["type"].(string); !ok {
accountType = "" accountType = ""
} }
phone_number, ok := account.Data["phone_number"].(string)
if !ok { if phoneNumber, ok = account.Data["phone_number"].(string); !ok {
phone_number = "" phoneNumber = ""
} }
email, ok := account.Data["email"].(string)
if !ok { if email, ok = account.Data["email"].(string); !ok {
email = "" email = ""
} }
return &models.Account{ return &models.Account{
ID: account.ID, ID: account.ID,
FirstName: first_name, FirstName: firstName,
LastName: last_name, LastName: lastName,
Email: email, Email: email,
BirthDate: birth_date, BirthDate: birthDate,
Type: accountType, Type: accountType,
LocalCredentials: models.LocalCredentials{ LocalCredentials: models.LocalCredentials{
Email: account.Authentication.Local.Email, Email: account.Authentication.Local.Email,
EmailVerified: account.Authentication.Local.EmailValidation.Validated, EmailVerified: account.Authentication.Local.EmailValidation.Validated,
EmailValidationCode: account.Authentication.Local.EmailValidation.ValidationCode, EmailValidationCode: account.Authentication.Local.EmailValidation.ValidationCode,
PhoneNumber: phone_number, PhoneNumber: phoneNumber,
PhoneNumberVerified: account.Authentication.Local.PhoneNumberValidation.Validated, PhoneNumberVerified: account.Authentication.Local.PhoneNumberValidation.Validated,
}, },
} }

View File

@ -2,11 +2,11 @@ package services
import ( import (
"context" "context"
"google.golang.org/protobuf/types/known/structpb"
"github.com/appleboy/gorush/rpc/proto" "github.com/appleboy/gorush/rpc/proto"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/protobuf/types/known/structpb"
) )
const ( const (
@ -55,7 +55,7 @@ func (s *PushService) Send(notification Notification) error {
Str("notification_title", notification.Title). Str("notification_title", notification.Title).
Msg("Send notification") Msg("Send notification")
resp, err := s.Client.Send(context.Background(), &proto.NotificationRequest{ if resp, err := s.Client.Send(context.Background(), &proto.NotificationRequest{
Data: notification.Data, Data: notification.Data,
ID: notification.ID, ID: notification.ID,
Platform: notification.Platform, Platform: notification.Platform,
@ -67,9 +67,7 @@ func (s *PushService) Send(notification Notification) error {
Title: notification.Title, Title: notification.Title,
Body: notification.Message, Body: notification.Message,
}, },
}) }); err != nil {
if err != nil {
return err return err
} }

View File

@ -7,48 +7,53 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type ServicesHandler struct { type ServiceHandler struct {
MobilityAccounts MobilityAccountService MobilityAccounts MobilityAccountService
Push *PushService Push *PushService
Geocoder geocode.Geocoder Geocoder geocode.Geocoder
Routing routing.RoutingService Routing routing.RoutingService
} }
func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) { func NewServicesHandler(cfg *viper.Viper) (*ServiceHandler, error) {
var ( var (
mobilityAccountsDial = cfg.GetString("services.internal.mobility_accounts.dial") mobilityAccountsDial = cfg.GetString("services.internal.mobility_accounts.dial")
pushDial = cfg.GetString("services.internal.push.dial") pushDial = cfg.GetString("services.internal.push.dial")
geocoder_type = cfg.GetString("geocoder.type") geocoderType = cfg.GetString("geocoder.type")
pelias_base_url = cfg.GetString("geocoder.pelias.base_url") peliasBaseUrl = cfg.GetString("geocoder.pelias.base_url")
routing_service_type = cfg.GetString("routing.type") routingServiceType = cfg.GetString("routing.type")
valhalla_base_url = cfg.GetString("routing.valhalla.base_url") valhallaBaseUrl = cfg.GetString("routing.valhalla.base_url")
mobilityAccounts MobilityAccountService
push *PushService
geocoder geocode.Geocoder
routingsvc routing.RoutingService
err error
) )
mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial)
if err != nil { if mobilityAccounts, err = NewMobilityAccountService(mobilityAccountsDial); err != nil {
log.Fatal().Err(err).Msg("Could not connect to Mobility Accounts Service") log.Fatal().Err(err).Msg("Could not connect to Mobility Accounts Service")
return nil, err return nil, err
} }
push, err := NewPushService(pushDial)
if err != nil { if push, err = NewPushService(pushDial); err != nil {
log.Fatal().Err(err).Msg("Could not connect to Push Notifications Service") log.Fatal().Err(err).Msg("Could not connect to Push Notifications Service")
return nil, err return nil, err
} }
geocoder, err := geocode.NewGeocoder(geocoder_type, pelias_base_url)
if err != nil { if geocoder, err = geocode.NewGeocoder(geocoderType, peliasBaseUrl); err != nil {
log.Fatal().Err(err).Msg("Could not initiate the Geocoder service") log.Fatal().Err(err).Msg("Could not initiate the Geocoder service")
return nil, err return nil, err
} }
routing, err := routing.NewRoutingService(routing_service_type, valhalla_base_url) if routingsvc, err = routing.NewRoutingService(routingServiceType, valhallaBaseUrl); err != nil {
if err != nil {
log.Fatal().Err(err).Msg("Could not initiate the routing service") log.Fatal().Err(err).Msg("Could not initiate the routing service")
return nil, err return nil, err
} }
return &ServicesHandler{ return &ServiceHandler{
MobilityAccounts: mobilityAccounts, MobilityAccounts: mobilityAccounts,
Push: push, Push: push,
Geocoder: geocoder, Geocoder: geocoder,
Routing: routing, Routing: routingsvc,
}, nil }, nil
} }

View File

@ -3,12 +3,13 @@ package storage
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"strconv"
"strings"
"github.com/google/uuid" "github.com/google/uuid"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/viper" "github.com/spf13/viper"
"strconv"
"strings"
) )
type PostgresqlStorage struct { type PostgresqlStorage struct {
@ -24,65 +25,74 @@ func NewPostgresqlStorage(cfg *viper.Viper) (PostgresqlStorage, error) {
user = cfg.GetString("storage.db.psql.user") user = cfg.GetString("storage.db.psql.user")
password = cfg.GetString("storage.db.psql.password") password = cfg.GetString("storage.db.psql.password")
dbname = cfg.GetString("storage.db.psql.dbname") dbname = cfg.GetString("storage.db.psql.dbname")
sslmode = cfg.GetString("storage.db.psql.sslmode") sslMode = cfg.GetString("storage.db.psql.sslMode")
pg_schema = cfg.GetString("storage.db.psql.schema") pgSchema = cfg.GetString("storage.db.psql.schema")
pgtables_users_firebase = cfg.GetString("storage.db.psql.tables.users_firebase") pgtablesUsersFirebase = cfg.GetString("storage.db.psql.tables.users_firebase")
) )
portInt, _ := strconv.Atoi(port) portInt, _ := strconv.Atoi(port)
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", host, portInt, user, password, dbname, sslmode)
db, err := sql.Open("postgres", psqlconn) psqlConn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslMode=%s",
host, portInt, user, password, dbname, sslMode)
db, err := sql.Open("postgres", psqlConn)
if err != nil { if err != nil {
log.Error().Err(err).Msg("opening connection to postgresql failed") log.Error().Err(err).Msg("opening connection to postgresql failed")
return PostgresqlStorage{}, fmt.Errorf("connection to postgresql failed") return PostgresqlStorage{}, fmt.Errorf("connection to postgresql failed")
} }
err = db.Ping()
if err != nil { if err = db.Ping(); err != nil {
log.Error().Err(err).Msg("ping to postgresql failed") log.Error().Err(err).Msg("ping to postgresql failed")
return PostgresqlStorage{}, fmt.Errorf("connection to postgresql database failed") return PostgresqlStorage{}, fmt.Errorf("connection to postgresql database failed")
} }
return PostgresqlStorage{ return PostgresqlStorage{
DbConnection: db, DbConnection: db,
Schema: pg_schema, Schema: pgSchema,
Tables: map[string]string{ Tables: map[string]string{
"users_firebase": fmt.Sprintf("%s.%s", pg_schema, pgtables_users_firebase), "users_firebase": fmt.Sprintf("%s.%s", pgSchema, pgtablesUsersFirebase),
}, },
}, nil }, nil
} }
func (s PostgresqlStorage) CreateFirebaseToken(user_id string, fcm_token string, device_platform string) (err error) { func (s PostgresqlStorage) CreateFirebaseToken(userId string, fcmToken string, devicePlatform string) (err error) {
_, err = uuid.Parse(user_id)
if err != nil { if _, err = uuid.Parse(userId); err != nil {
log.Error().Err(err).Msg("Postgresql Storage CreateFirebaseToken invalid User ID") log.Error().Err(err).Msg("Postgresql Storage CreateFirebaseToken invalid User ID")
return err return err
} }
_, err = s.DbConnection.Exec(fmt.Sprintf("INSERT INTO %s (user_id , fcm_token , device_platform) VALUES($1,$2,$3)", s.Tables["users_firebase"]), if _, err = s.DbConnection.Exec(fmt.Sprintf("INSERT INTO %s "+
user_id, "(user_id , fcm_token , device_platform) VALUES($1,$2,$3)", s.Tables["users_firebase"]),
fcm_token, userId,
device_platform) fcmToken,
if err != nil { devicePlatform); err != nil {
if strings.Contains(err.Error(), "duplicate key") { if strings.Contains(err.Error(), "duplicate key") {
_ = s.UpdateFirebaseToken(user_id, device_platform, fcm_token) _ = s.UpdateFirebaseToken(userId, devicePlatform, fcmToken)
} }
} }
return nil return nil
} }
func (s PostgresqlStorage) GetFirebaseToken(user_id string) (fcm string, device_platform string, err error) { func (s PostgresqlStorage) GetFirebaseToken(userId string) (fcm string, devicePlatform string, err error) {
err = s.DbConnection.QueryRow(fmt.Sprintf("SELECT fcm_token , device_platform FROM %s WHERE user_id = $1", s.Tables["users_firebase"]), user_id). if err = s.DbConnection.QueryRow(fmt.Sprintf("SELECT fcm_token , "+
"device_platform FROM %s WHERE user_id = $1", s.Tables["users_firebase"]), userId).
Scan( Scan(
&fcm, &fcm,
&device_platform, &devicePlatform,
) ); err != nil {
if err != nil {
return "", "", err return "", "", err
} }
return fcm, device_platform, nil
return fcm, devicePlatform, nil
} }
func (s PostgresqlStorage) UpdateFirebaseToken(user_id string, fcm_token string, device_platform string) error { func (s PostgresqlStorage) UpdateFirebaseToken(userId string, fcmToken string, devicePlatform string) error {
query := fmt.Sprintf("UPDATE %s SET fcm_token = $1 device_platform = $2 WHERE user_id = $3", s.Tables["users_firebase"]) query := fmt.Sprintf("UPDATE %s SET fcm_token ="+
_, err := s.DbConnection.Exec(query, fcm_token, device_platform, user_id) " $1 device_platform = $2 WHERE user_id = $3", s.Tables["users_firebase"])
if err != nil {
if _, err := s.DbConnection.Exec(query, fcmToken, devicePlatform, userId); err != nil {
return err return err
} }
return nil return nil
} }

View File

@ -2,24 +2,25 @@ package storage
import ( import (
"fmt" "fmt"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type Storage interface { type Storage interface {
CreateFirebaseToken(user_id string, fcm_token string, device_platform string) (err error) CreateFirebaseToken(userId string, fcmToken string, devicePlatform string) (err error)
UpdateFirebaseToken(user_id string, fcm_token string, device_platform string) error UpdateFirebaseToken(userId string, fcmToken string, devicePlatform string) error
GetFirebaseToken(user_id string) (fcm string, device_platform string, err error) GetFirebaseToken(userId string) (fcm string, devicePlatform string, err error)
} }
func NewStorage(cfg *viper.Viper) (Storage, error) { func NewStorage(cfg *viper.Viper) (Storage, error) {
var ( var (
storage_type = cfg.GetString("storage.db.type") storageType = cfg.GetString("storage.db.type")
) )
switch storage_type { switch storageType {
case "psql": case "psql":
s, err := NewPostgresqlStorage(cfg) s, err := NewPostgresqlStorage(cfg)
return s, err return s, err
default: default:
return nil, fmt.Errorf("storage type %v is not supported", storage_type) return nil, fmt.Errorf("storage type %v is not supported", storageType)
} }
} }