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, } }