Organize backend into product executable and shared Go modules
This commit is contained in:
1 parent
981e84a4b4
commit
f0720ec66b
382 files changed
+1944
-6989
No files matched your search
@@ -0,0 +1,141 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
customermodel "git.sendico.io/tech/sxchnge/product/customers/model"
|
||||
sessionmodel "git.sendico.io/tech/sxchnge/product/sessions/model"
|
||||
"time"
|
||||
|
||||
"git.sendico.io/tech/sxchnge/product/auth/config"
|
||||
mduration "git.sendico.io/tech/sxchnge/shared/duration"
|
||||
"git.sendico.io/tech/sxchnge/shared/errors"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type AccountToken struct {
|
||||
AccountRef bson.ObjectID
|
||||
Login string
|
||||
Name string
|
||||
Locale string
|
||||
sessionmodel.SessionIdentifier
|
||||
Expiration time.Time
|
||||
Pending bool
|
||||
}
|
||||
|
||||
func createAccountToken(a *customermodel.Account, expiration int, session sessionmodel.SessionIdentifier) AccountToken {
|
||||
return AccountToken{
|
||||
AccountRef: *a.GetID(),
|
||||
Login: a.Login,
|
||||
Name: a.Name,
|
||||
Locale: a.Locale,
|
||||
SessionIdentifier: session,
|
||||
Expiration: time.Now().Add(mduration.Param2Duration(expiration, time.Hour)),
|
||||
Pending: false,
|
||||
}
|
||||
}
|
||||
|
||||
func getTokenParam(claims middleware.MapClaims, param string) (string, error) {
|
||||
id, ok := claims[param].(string)
|
||||
if !ok {
|
||||
return "", merrors.NoData(fmt.Sprintf("param '%s' not found", param))
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
const (
|
||||
paramNameID = "id"
|
||||
paramNameName = "name"
|
||||
paramNameLocale = "locale"
|
||||
paramNameLogin = "login"
|
||||
paramNameClientID = "clientId"
|
||||
paramNameDeviceID = "deviceId"
|
||||
paramNameSessionVersion = "sessionVersion"
|
||||
paramNameExpiration = "exp"
|
||||
paramNamePending = "pending"
|
||||
)
|
||||
|
||||
func Claims2Token(claims middleware.MapClaims) (*AccountToken, error) {
|
||||
var at AccountToken
|
||||
var err error
|
||||
var account string
|
||||
if account, err = getTokenParam(claims, paramNameID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if at.AccountRef, err = bson.ObjectIDFromHex(account); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if at.Login, err = getTokenParam(claims, paramNameLogin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if at.Name, err = getTokenParam(claims, paramNameName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if at.Locale, err = getTokenParam(claims, paramNameLocale); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if clientID, ok := claims[paramNameClientID]; ok {
|
||||
if clientIDText, ok := clientID.(string); ok {
|
||||
at.ClientID = clientIDText
|
||||
}
|
||||
}
|
||||
if deviceID, ok := claims[paramNameDeviceID]; ok {
|
||||
if deviceIDText, ok := deviceID.(string); ok {
|
||||
at.DeviceID = deviceIDText
|
||||
}
|
||||
}
|
||||
if version, ok := claims[paramNameSessionVersion]; ok {
|
||||
if versionText, ok := version.(string); ok {
|
||||
at.SessionVersion = versionText
|
||||
}
|
||||
}
|
||||
if pending, ok := claims[paramNamePending]; ok {
|
||||
if pbool, ok := pending.(bool); ok {
|
||||
at.Pending = pbool
|
||||
}
|
||||
}
|
||||
if expValue, ok := claims[paramNameExpiration]; ok {
|
||||
switch exp := expValue.(type) {
|
||||
case time.Time:
|
||||
at.Expiration = exp
|
||||
case float64:
|
||||
at.Expiration = time.Unix(int64(exp), 0)
|
||||
case int64:
|
||||
at.Expiration = time.Unix(exp, 0)
|
||||
default:
|
||||
return nil, merrors.InvalidDataType(fmt.Sprintf("expiration param is of invalid type: %T", expValue))
|
||||
}
|
||||
} else {
|
||||
return nil, merrors.InvalidDataType(fmt.Sprintf("expiration param is of invalid type: %T", expValue))
|
||||
}
|
||||
return &at, nil
|
||||
}
|
||||
|
||||
func Account2ClaimsForSession(a *customermodel.Account, expiration int, session sessionmodel.SessionIdentifier) middleware.MapClaims {
|
||||
t := createAccountToken(a, expiration, session)
|
||||
return middleware.MapClaims{
|
||||
paramNameID: t.AccountRef.Hex(),
|
||||
paramNameLogin: t.Login,
|
||||
paramNameName: t.Name,
|
||||
paramNameLocale: t.Locale,
|
||||
paramNameClientID: t.ClientID,
|
||||
paramNameDeviceID: t.DeviceID,
|
||||
paramNameSessionVersion: t.SessionVersion,
|
||||
paramNameExpiration: t.Expiration.Unix(),
|
||||
paramNamePending: t.Pending,
|
||||
}
|
||||
}
|
||||
|
||||
func PendingAccount2Claims(a *customermodel.Account, expirationMinutes int) middleware.MapClaims {
|
||||
t := createAccountToken(a, expirationMinutes/60, sessionmodel.SessionIdentifier{})
|
||||
t.Expiration = time.Now().Add(time.Duration(expirationMinutes) * time.Minute)
|
||||
t.Pending = true
|
||||
return middleware.MapClaims{
|
||||
paramNameID: t.AccountRef.Hex(),
|
||||
paramNameLogin: t.Login,
|
||||
paramNameName: t.Name,
|
||||
paramNameLocale: t.Locale,
|
||||
paramNameExpiration: t.Expiration.Unix(),
|
||||
paramNamePending: t.Pending,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
customermodel "git.sendico.io/tech/sxchnge/product/customers/model"
|
||||
sessionmodel "git.sendico.io/tech/sxchnge/product/sessions/model"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccountTokenPreservesSessionIdentity(t *testing.T) {
|
||||
account := &customermodel.Account{}
|
||||
account.SetID(bson.NewObjectID())
|
||||
account.Login = "security@example.com"
|
||||
account.Name = "Security"
|
||||
account.Locale = "en"
|
||||
session := sessionmodel.SessionIdentifier{
|
||||
ClientID: "web",
|
||||
DeviceID: "device-a",
|
||||
SessionVersion: "session-version-a",
|
||||
}
|
||||
|
||||
token, err := Claims2Token(Account2ClaimsForSession(account, 1, session))
|
||||
if err != nil {
|
||||
t.Fatalf("decode account claims: %v", err)
|
||||
}
|
||||
if token.SessionIdentifier != session {
|
||||
t.Fatalf("session identity = %#v, want %#v", token.SessionIdentifier, session)
|
||||
}
|
||||
if token.Expiration.IsZero() {
|
||||
t.Fatal("access token expiration is missing")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user