package model import ( "fmt" "time" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/model" mduration "github.com/tech/sendico/pkg/mutil/duration" "github.com/tech/sendico/server/interface/middleware" "go.mongodb.org/mongo-driver/bson/primitive" ) type AccountToken struct { AccountRef primitive.ObjectID Login string Name string Locale string Expiration time.Time Pending bool } func createAccountToken(a *model.Account, expiration int) AccountToken { return AccountToken{ AccountRef: *a.GetID(), Login: a.Login, Name: a.Name, Locale: a.Locale, 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" 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 = primitive.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 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 Account2Claims(a *model.Account, expiration int) middleware.MapClaims { t := createAccountToken(a, expiration) return middleware.MapClaims{ paramNameID: t.AccountRef.Hex(), paramNameLogin: t.Login, paramNameName: t.Name, paramNameLocale: t.Locale, paramNameExpiration: int64(t.Expiration.Unix()), paramNamePending: t.Pending, } } func PendingAccount2Claims(a *model.Account, expirationMinutes int) middleware.MapClaims { t := createAccountToken(a, expirationMinutes/60) 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, } }