mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 02:54:20 +00:00
fix: translation (#647)
* fix: translation * fix: translation * fix: translation * fix: remove unused code * fix: log err
This commit is contained in:
parent
34ec2508d3
commit
7295383621
@ -43,7 +43,7 @@ func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t *Tok
|
||||
}
|
||||
}
|
||||
|
||||
userID, clientID, agentID, err := verifyAccessToken(ctx, token, t, method)
|
||||
userID, clientID, agentID, prefLang, err := verifyAccessToken(ctx, token, t, method)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -54,7 +54,7 @@ func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t *Tok
|
||||
if err := checkOrigin(ctx, origins); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return context.WithValue(ctx, dataKey, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil
|
||||
return context.WithValue(ctx, dataKey, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID, PreferredLanguage: prefLang}), nil
|
||||
}
|
||||
|
||||
func SetCtxData(ctx context.Context, ctxData CtxData) context.Context {
|
||||
|
@ -15,8 +15,8 @@ type testVerifier struct {
|
||||
grant *Grant
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, error) {
|
||||
return "userID", "agentID", nil
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, error) {
|
||||
return "userID", "agentID", "de", nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ResolveGrants(ctx context.Context) (*Grant, error) {
|
||||
|
@ -19,7 +19,7 @@ type TokenVerifier struct {
|
||||
}
|
||||
|
||||
type authZRepo interface {
|
||||
VerifyAccessToken(ctx context.Context, token, clientID string) (userID, agentID string, err error)
|
||||
VerifyAccessToken(ctx context.Context, token, clientID string) (userID, agentID, prefLang string, err error)
|
||||
VerifierClientID(ctx context.Context, name string) (clientID string, err error)
|
||||
ResolveGrants(ctx context.Context) (grant *Grant, err error)
|
||||
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
|
||||
@ -30,13 +30,13 @@ func Start(authZRepo authZRepo) (v *TokenVerifier) {
|
||||
return &TokenVerifier{authZRepo: authZRepo}
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string, method string) (userID, clientID, agentID string, err error) {
|
||||
func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string, method string) (userID, clientID, agentID, prefLang string, err error) {
|
||||
clientID, err = v.clientIDFromMethod(ctx, method)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
userID, agentID, err = v.authZRepo.VerifyAccessToken(ctx, token, clientID)
|
||||
return userID, clientID, agentID, err
|
||||
userID, agentID, prefLang, err = v.authZRepo.VerifyAccessToken(ctx, token, clientID)
|
||||
return userID, clientID, agentID, prefLang, err
|
||||
}
|
||||
|
||||
type client struct {
|
||||
@ -101,10 +101,10 @@ func (v *TokenVerifier) CheckAuthMethod(method string) (Option, bool) {
|
||||
return authOpt, ok
|
||||
}
|
||||
|
||||
func verifyAccessToken(ctx context.Context, token string, t *TokenVerifier, method string) (userID, clientID, agentID string, err error) {
|
||||
func verifyAccessToken(ctx context.Context, token string, t *TokenVerifier, method string) (userID, clientID, agentID, prefLang string, err error) {
|
||||
parts := strings.Split(token, BearerPrefix)
|
||||
if len(parts) != 2 {
|
||||
return "", "", "", caos_errs.ThrowUnauthenticated(nil, "AUTH-7fs1e", "invalid auth header")
|
||||
return "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "AUTH-7fs1e", "invalid auth header")
|
||||
}
|
||||
return t.VerifyAccessToken(ctx, parts[1], method)
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func Test_VerifyAccessToken(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, _, _, err := verifyAccessToken(tt.args.ctx, tt.args.token, tt.args.verifier, tt.args.method)
|
||||
_, _, _, _, err := verifyAccessToken(tt.args.ctx, tt.args.token, tt.args.verifier, tt.args.method)
|
||||
if tt.wantErr && err == nil {
|
||||
t.Errorf("got wrong result, should get err: actual: %v ", err)
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
package grpc
|
||||
package errors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/pkg/grpc/message"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func CaosToGRPCError(ctx context.Context, err error, translator *i18n.Translator) error {
|
||||
func CaosToGRPCError(ctx context.Context, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
@ -19,10 +18,8 @@ func CaosToGRPCError(ctx context.Context, err error, translator *i18n.Translator
|
||||
return status.Convert(err).Err()
|
||||
}
|
||||
msg := key
|
||||
if translator != nil {
|
||||
msg = translator.LocalizeFromCtx(ctx, key, nil)
|
||||
msg += " (" + id + ")"
|
||||
}
|
||||
msg += " (" + id + ")"
|
||||
|
||||
s, err := status.New(code, msg).WithDetails(&message.ErrorDetail{Id: id, Message: key})
|
||||
if err != nil {
|
||||
logging.Log("GRPC-gIeRw").WithError(err).Debug("unable to add detail")
|
@ -1,4 +1,4 @@
|
||||
package grpc
|
||||
package errors
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -8,13 +8,11 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
)
|
||||
|
||||
func TestCaosToGRPCError(t *testing.T) {
|
||||
type args struct {
|
||||
err error
|
||||
translator *i18n.Translator
|
||||
err error
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -28,18 +26,18 @@ func TestCaosToGRPCError(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"unknown error",
|
||||
args{errors.New("unknown"), nil},
|
||||
args{errors.New("unknown")},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"caos error",
|
||||
args{caos_errs.ThrowInternal(nil, "", "message"), nil},
|
||||
args{caos_errs.ThrowInternal(nil, "", "message")},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CaosToGRPCError(context.Background(), tt.args.err, tt.args.translator); (err != nil) != tt.wantErr {
|
||||
if err := CaosToGRPCError(context.Background(), tt.args.err); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CaosToGRPCError() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
@ -21,8 +21,8 @@ var (
|
||||
|
||||
type verifierMock struct{}
|
||||
|
||||
func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, error) {
|
||||
return "", "", nil
|
||||
func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, error) {
|
||||
return "", "", "", nil
|
||||
}
|
||||
func (v *verifierMock) ResolveGrants(ctx context.Context) (*authz.Grant, error) {
|
||||
return nil, nil
|
||||
|
@ -2,24 +2,20 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/grpc/errors"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
grpc_util "github.com/caos/zitadel/internal/api/grpc"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
_ "github.com/caos/zitadel/internal/statik"
|
||||
)
|
||||
|
||||
func ErrorHandler(defaultLanguage language.Tag) grpc.UnaryServerInterceptor {
|
||||
translator := newZitadelTranslator(defaultLanguage)
|
||||
|
||||
func ErrorHandler() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
return toGRPCError(ctx, req, handler, translator)
|
||||
return toGRPCError(ctx, req, handler)
|
||||
}
|
||||
}
|
||||
|
||||
func toGRPCError(ctx context.Context, req interface{}, handler grpc.UnaryHandler, translator *i18n.Translator) (interface{}, error) {
|
||||
func toGRPCError(ctx context.Context, req interface{}, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
resp, err := handler(ctx, req)
|
||||
return resp, grpc_util.CaosToGRPCError(ctx, err, translator)
|
||||
return resp, errors.CaosToGRPCError(ctx, err)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func Test_toGRPCError(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := toGRPCError(tt.args.ctx, tt.args.req, tt.args.handler, nil)
|
||||
got, err := toGRPCError(tt.args.ctx, tt.args.req, tt.args.handler)
|
||||
if (err != nil) != tt.res.wantErr {
|
||||
t.Errorf("toGRPCError() error = %v, wantErr %v", err, tt.res.wantErr)
|
||||
return
|
||||
|
@ -18,6 +18,9 @@ func TranslationHandler(defaultLanguage language.Tag) func(ctx context.Context,
|
||||
if loc, ok := resp.(localizers); ok && resp != nil {
|
||||
translateFields(ctx, loc, translator)
|
||||
}
|
||||
if err != nil {
|
||||
err = translateError(ctx, err, translator)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
@ -26,6 +28,17 @@ func translateFields(ctx context.Context, object localizers, translator *i18n.Tr
|
||||
}
|
||||
}
|
||||
|
||||
func translateError(ctx context.Context, err error, translator *i18n.Translator) error {
|
||||
if translator == nil || err == nil {
|
||||
return err
|
||||
}
|
||||
caosErr := new(caos_errs.CaosError)
|
||||
if errors.As(err, &caosErr) {
|
||||
caosErr.SetMessage(translator.LocalizeFromCtx(ctx, caosErr.GetMessage(), nil))
|
||||
}
|
||||
return caosErr
|
||||
}
|
||||
|
||||
func newZitadelTranslator(defaultLanguage language.Tag) *i18n.Translator {
|
||||
return translatorFromNamespace("zitadel", defaultLanguage)
|
||||
}
|
||||
|
@ -30,14 +30,13 @@ func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang l
|
||||
middleware.TracingStatsServer(http.Healthz, http.Readiness, http.Validation),
|
||||
grpc.UnaryInterceptor(
|
||||
grpc_middleware.ChainUnaryServer(
|
||||
middleware.ErrorHandler(lang),
|
||||
middleware.ErrorHandler(),
|
||||
middleware.AuthorizationInterceptor(verifier, authConfig),
|
||||
middleware.TranslationHandler(lang),
|
||||
grpc_middleware.ChainUnaryServer(
|
||||
middleware.AuthorizationInterceptor(verifier, authConfig),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func Serve(ctx context.Context, server *grpc.Server, port string) {
|
||||
|
@ -2,6 +2,8 @@ package oidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
@ -78,6 +80,8 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc
|
||||
userInfo.PreferredUsername = user.PreferredLoginName
|
||||
userInfo.UpdatedAt = user.ChangeDate
|
||||
userInfo.Gender = oidc.Gender(getGender(user.Gender))
|
||||
userInfo.Locale, err = language.Parse(user.PreferredLanguage)
|
||||
logging.Log("OIDC-4ks9F").OnError(err).Debug("unable to parse locale")
|
||||
case scopePhone:
|
||||
userInfo.PhoneNumber = user.Phone
|
||||
userInfo.PhoneNumberVerified = user.IsPhoneVerified
|
||||
|
@ -14,7 +14,12 @@ type TokenRepo struct {
|
||||
}
|
||||
|
||||
func (repo *TokenRepo) CreateToken(ctx context.Context, agentID, applicationID, userID string, audience, scopes []string, lifetime time.Duration) (*token_model.Token, error) {
|
||||
token, err := repo.View.CreateToken(agentID, applicationID, userID, audience, scopes, lifetime)
|
||||
preferredLanguage := ""
|
||||
user, _ := repo.View.UserByID(userID)
|
||||
if user != nil {
|
||||
preferredLanguage = user.PreferredLanguage
|
||||
}
|
||||
token, err := repo.View.CreateToken(agentID, applicationID, userID, preferredLanguage, audience, scopes, lifetime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
@ -43,6 +44,17 @@ func (u *Token) EventQuery() (*models.SearchQuery, error) {
|
||||
|
||||
func (u *Token) Reduce(event *models.Event) (err error) {
|
||||
switch event.Type {
|
||||
case user_es_model.UserProfileChanged:
|
||||
user := new(view_model.UserView)
|
||||
user.AppendEvent(event)
|
||||
tokens, err := u.view.TokensByUserID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, token := range tokens {
|
||||
token.PreferredLanguage = user.PreferredLanguage
|
||||
}
|
||||
return u.view.PutTokens(tokens, event.Sequence)
|
||||
case user_es_model.SignedOut:
|
||||
id, err := agentIDFromSession(event)
|
||||
if err != nil {
|
||||
|
@ -16,25 +16,30 @@ func (v *View) TokenByID(tokenID string) (*model.Token, error) {
|
||||
return view.TokenByID(v.Db, tokenTable, tokenID)
|
||||
}
|
||||
|
||||
func (v *View) TokensByUserID(userID string) ([]*model.Token, error) {
|
||||
return view.TokensByUserID(v.Db, tokenTable, userID)
|
||||
}
|
||||
|
||||
func (v *View) IsTokenValid(tokenID string) (bool, error) {
|
||||
return view.IsTokenValid(v.Db, tokenTable, tokenID)
|
||||
}
|
||||
|
||||
func (v *View) CreateToken(agentID, applicationID, userID string, audience, scopes []string, lifetime time.Duration) (*model.Token, error) {
|
||||
func (v *View) CreateToken(agentID, applicationID, userID, preferredLanguage string, audience, scopes []string, lifetime time.Duration) (*model.Token, error) {
|
||||
id, err := v.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
token := &model.Token{
|
||||
ID: id,
|
||||
CreationDate: now,
|
||||
UserID: userID,
|
||||
ApplicationID: applicationID,
|
||||
UserAgentID: agentID,
|
||||
Scopes: scopes,
|
||||
Audience: audience,
|
||||
Expiration: now.Add(lifetime),
|
||||
ID: id,
|
||||
CreationDate: now,
|
||||
UserID: userID,
|
||||
ApplicationID: applicationID,
|
||||
UserAgentID: agentID,
|
||||
Scopes: scopes,
|
||||
Audience: audience,
|
||||
Expiration: now.Add(lifetime),
|
||||
PreferredLanguage: preferredLanguage,
|
||||
}
|
||||
if err := view.PutToken(v.Db, tokenTable, token); err != nil {
|
||||
return nil, err
|
||||
@ -50,6 +55,14 @@ func (v *View) PutToken(token *model.Token) error {
|
||||
return v.ProcessedTokenSequence(token.Sequence)
|
||||
}
|
||||
|
||||
func (v *View) PutTokens(token []*model.Token, sequence uint64) error {
|
||||
err := view.PutTokens(v.Db, tokenTable, token...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedTokenSequence(sequence)
|
||||
}
|
||||
|
||||
func (v *View) DeleteToken(tokenID string, eventSequence uint64) error {
|
||||
err := view.DeleteToken(v.Db, tokenTable, tokenID)
|
||||
if err != nil {
|
||||
|
@ -19,26 +19,26 @@ type TokenVerifierRepo struct {
|
||||
View *view.View
|
||||
}
|
||||
|
||||
func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenString, clientID string) (userID string, agentID string, err error) {
|
||||
func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenString, clientID string) (userID string, agentID string, prefLang string, err error) {
|
||||
//TODO: use real key
|
||||
tokenID, err := crypto.DecryptAESString(tokenString, string(repo.TokenVerificationKey[:32]))
|
||||
if err != nil {
|
||||
return "", "", caos_errs.ThrowUnauthenticated(nil, "APP-8EF0zZ", "invalid token")
|
||||
return "", "", "", caos_errs.ThrowUnauthenticated(nil, "APP-8EF0zZ", "invalid token")
|
||||
}
|
||||
token, err := repo.View.TokenByID(tokenID)
|
||||
if err != nil {
|
||||
return "", "", caos_errs.ThrowUnauthenticated(err, "APP-BxUSiL", "invalid token")
|
||||
return "", "", "", caos_errs.ThrowUnauthenticated(err, "APP-BxUSiL", "invalid token")
|
||||
}
|
||||
if !token.Expiration.After(time.Now().UTC()) {
|
||||
return "", "", caos_errs.ThrowUnauthenticated(err, "APP-k9KS0", "invalid token")
|
||||
return "", "", "", caos_errs.ThrowUnauthenticated(err, "APP-k9KS0", "invalid token")
|
||||
}
|
||||
|
||||
for _, aud := range token.Audience {
|
||||
if clientID == aud {
|
||||
return token.UserID, token.UserAgentID, nil
|
||||
return token.UserID, token.UserAgentID, token.PreferredLanguage, nil
|
||||
}
|
||||
}
|
||||
return "", "", caos_errs.ThrowUnauthenticated(nil, "APP-Zxfako", "invalid audience")
|
||||
return "", "", "", caos_errs.ThrowUnauthenticated(nil, "APP-Zxfako", "invalid audience")
|
||||
}
|
||||
|
||||
func (repo *TokenVerifierRepo) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error) {
|
||||
|
@ -44,6 +44,10 @@ func (err *CaosError) GetMessage() string {
|
||||
return err.Message
|
||||
}
|
||||
|
||||
func (err *CaosError) SetMessage(msg string) {
|
||||
err.Message = msg
|
||||
}
|
||||
|
||||
func (err *CaosError) GetID() string {
|
||||
return err.ID
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
type Error interface {
|
||||
GetParent() error
|
||||
GetMessage() string
|
||||
SetMessage(string)
|
||||
GetID() string
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@ -130,6 +131,10 @@ func (t *Translator) langsFromRequest(r *http.Request) []string {
|
||||
func (t *Translator) langsFromCtx(ctx context.Context) []string {
|
||||
langs := make([]string, 0)
|
||||
if ctx != nil {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
if ctxData.PreferredLanguage != "" {
|
||||
langs = append(langs, authz.GetCtxData(ctx).PreferredLanguage)
|
||||
}
|
||||
langs = append(langs, getAcceptLanguageHeader(ctx))
|
||||
}
|
||||
return langs
|
||||
|
@ -7,17 +7,18 @@ import (
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
ID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
ApplicationID string
|
||||
UserAgentID string
|
||||
Audience []string
|
||||
Expiration time.Time
|
||||
Scopes []string
|
||||
Sequence uint64
|
||||
ID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
ApplicationID string
|
||||
UserAgentID string
|
||||
Audience []string
|
||||
Expiration time.Time
|
||||
Scopes []string
|
||||
Sequence uint64
|
||||
PreferredLanguage string
|
||||
}
|
||||
|
||||
type TokenSearchRequest struct {
|
||||
|
@ -18,47 +18,50 @@ const (
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
ID string `json:"-" gorm:"column:id;primary_key"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
|
||||
UserID string `json:"-" gorm:"column:user_id"`
|
||||
ApplicationID string `json:"-" gorm:"column:application_id"`
|
||||
UserAgentID string `json:"-" gorm:"column:user_agent_id"`
|
||||
Audience pq.StringArray `json:"-" gorm:"column:audience"`
|
||||
Scopes pq.StringArray `json:"-" gorm:"column:scopes"`
|
||||
Expiration time.Time `json:"-" gorm:"column:expiration"`
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
ID string `json:"-" gorm:"column:id;primary_key"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
|
||||
UserID string `json:"-" gorm:"column:user_id"`
|
||||
ApplicationID string `json:"-" gorm:"column:application_id"`
|
||||
UserAgentID string `json:"-" gorm:"column:user_agent_id"`
|
||||
Audience pq.StringArray `json:"-" gorm:"column:audience"`
|
||||
Scopes pq.StringArray `json:"-" gorm:"column:scopes"`
|
||||
Expiration time.Time `json:"-" gorm:"column:expiration"`
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
PreferredLanguage string `json:"-" gorm:"column:preferred_language"`
|
||||
}
|
||||
|
||||
func TokenFromModel(token *model.Token) *Token {
|
||||
return &Token{
|
||||
ID: token.ID,
|
||||
CreationDate: token.CreationDate,
|
||||
ChangeDate: token.ChangeDate,
|
||||
ResourceOwner: token.ResourceOwner,
|
||||
UserID: token.UserID,
|
||||
ApplicationID: token.ApplicationID,
|
||||
UserAgentID: token.UserAgentID,
|
||||
Audience: token.Audience,
|
||||
Scopes: token.Scopes,
|
||||
Expiration: token.Expiration,
|
||||
Sequence: token.Sequence,
|
||||
ID: token.ID,
|
||||
CreationDate: token.CreationDate,
|
||||
ChangeDate: token.ChangeDate,
|
||||
ResourceOwner: token.ResourceOwner,
|
||||
UserID: token.UserID,
|
||||
ApplicationID: token.ApplicationID,
|
||||
UserAgentID: token.UserAgentID,
|
||||
Audience: token.Audience,
|
||||
Scopes: token.Scopes,
|
||||
Expiration: token.Expiration,
|
||||
Sequence: token.Sequence,
|
||||
PreferredLanguage: token.PreferredLanguage,
|
||||
}
|
||||
}
|
||||
|
||||
func TokenToModel(token *Token) *model.Token {
|
||||
return &model.Token{
|
||||
ID: token.ID,
|
||||
CreationDate: token.CreationDate,
|
||||
ChangeDate: token.ChangeDate,
|
||||
ResourceOwner: token.ResourceOwner,
|
||||
UserID: token.UserID,
|
||||
ApplicationID: token.ApplicationID,
|
||||
UserAgentID: token.UserAgentID,
|
||||
Audience: token.Audience,
|
||||
Scopes: token.Scopes,
|
||||
Expiration: token.Expiration,
|
||||
Sequence: token.Sequence,
|
||||
ID: token.ID,
|
||||
CreationDate: token.CreationDate,
|
||||
ChangeDate: token.ChangeDate,
|
||||
ResourceOwner: token.ResourceOwner,
|
||||
UserID: token.UserID,
|
||||
ApplicationID: token.ApplicationID,
|
||||
UserAgentID: token.UserAgentID,
|
||||
Audience: token.Audience,
|
||||
Scopes: token.Scopes,
|
||||
Expiration: token.Expiration,
|
||||
Sequence: token.Sequence,
|
||||
PreferredLanguage: token.PreferredLanguage,
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
@ -22,6 +23,20 @@ func TokenByID(db *gorm.DB, table, tokenID string) (*model.Token, error) {
|
||||
return token, err
|
||||
}
|
||||
|
||||
func TokensByUserID(db *gorm.DB, table, userID string) ([]*model.Token, error) {
|
||||
tokens := make([]*model.Token, 0)
|
||||
userIDQuery := &token_model.TokenSearchQuery{
|
||||
Key: token_model.TokenSearchKeyUserID,
|
||||
Method: global_model.SearchMethodEquals,
|
||||
Value: userID,
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.TokenSearchRequest{
|
||||
Queries: []*token_model.TokenSearchQuery{userIDQuery},
|
||||
})
|
||||
_, err := query(db, &tokens)
|
||||
return tokens, err
|
||||
}
|
||||
|
||||
func IsTokenValid(db *gorm.DB, table, tokenID string) (bool, error) {
|
||||
token, err := TokenByID(db, table, tokenID)
|
||||
if err == nil {
|
||||
@ -38,6 +53,15 @@ func PutToken(db *gorm.DB, table string, token *model.Token) error {
|
||||
return save(db, token)
|
||||
}
|
||||
|
||||
func PutTokens(db *gorm.DB, table string, tokens ...*model.Token) error {
|
||||
save := repository.PrepareBulkSave(table)
|
||||
t := make([]interface{}, len(tokens))
|
||||
for i, token := range tokens {
|
||||
t[i] = token
|
||||
}
|
||||
return save(db, t...)
|
||||
}
|
||||
|
||||
func DeleteToken(db *gorm.DB, table, tokenID string) error {
|
||||
delete := repository.PrepareDeleteByKey(table, model.TokenSearchKey(token_model.TokenSearchKeyTokenID), tokenID)
|
||||
return delete(db)
|
||||
|
@ -2,11 +2,11 @@ package tracing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
errors2 "github.com/caos/zitadel/internal/api/grpc/errors"
|
||||
"strconv"
|
||||
|
||||
"go.opencensus.io/trace"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/grpc"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
@ -40,7 +40,7 @@ func (s *Span) SetStatusByError(err error) {
|
||||
}
|
||||
|
||||
func statusFromError(err error) trace.Status {
|
||||
code, msg, _, _ := grpc.ExtractCaosError(err)
|
||||
code, msg, _, _ := errors2.ExtractCaosError(err)
|
||||
return trace.Status{Code: int32(code), Message: msg}
|
||||
}
|
||||
|
||||
|
2
migrations/cockroach/V1.8__token.sql
Normal file
2
migrations/cockroach/V1.8__token.sql
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE auth.tokens ADD COLUMN preferred_language TEXT;
|
Loading…
Reference in New Issue
Block a user