AuthN: Cleanup authn package (#63456)
* AuthN: Update comments for ClientParams * AuthN: Update flag name from SyncTeamMembers to SyncTeams * UserSync: rename function and fix order of parameters so it is correct * UserSync: Fix so we skip check if no authModule or authID is passed * UserSync: move quota check to create user function * UserSync: Move FetchSyncedUserHook to UserSync * UserSync: Move last seen user hook to user sync service * ApiKey: Implement last seen hook as a client hook instead
This commit is contained in:
+10
-16
@@ -37,16 +37,16 @@ const (
|
|||||||
// ClientParams are hints to the auth service about how to handle the identity management
|
// ClientParams are hints to the auth service about how to handle the identity management
|
||||||
// from the authenticating client.
|
// from the authenticating client.
|
||||||
type ClientParams struct {
|
type ClientParams struct {
|
||||||
// Update the internal representation of the entity from the identity provided
|
// SyncUser updates the internal representation of the identity from the identity provided
|
||||||
SyncUser bool
|
SyncUser bool
|
||||||
// Add entity to teams
|
// AllowSignUp Adds identity to DB if it doesn't exist when, only work if SyncUser is enabled
|
||||||
SyncTeamMembers bool
|
|
||||||
// Create entity in the DB if it doesn't exist
|
|
||||||
AllowSignUp bool
|
AllowSignUp bool
|
||||||
// EnableDisabledUsers is a hint to the auth service that it should re-enable disabled users
|
// EnableDisabledUsers will enable disabled user, only work if SyncUser is enabled
|
||||||
EnableDisabledUsers bool
|
EnableDisabledUsers bool
|
||||||
// FetchSyncedUser ensure that all required information is added to the identity
|
// FetchSyncedUser ensure that all required information is added to the identity
|
||||||
FetchSyncedUser bool
|
FetchSyncedUser bool
|
||||||
|
// SyncTeams will sync the groups from identity to teams in grafana, enterprise only feature
|
||||||
|
SyncTeams bool
|
||||||
// CacheAuthProxyKey if this key is set we will try to cache the user id for proxy client
|
// CacheAuthProxyKey if this key is set we will try to cache the user id for proxy client
|
||||||
CacheAuthProxyKey string
|
CacheAuthProxyKey string
|
||||||
// LookUpParams are the arguments used to look up the entity in the DB.
|
// LookUpParams are the arguments used to look up the entity in the DB.
|
||||||
@@ -222,26 +222,20 @@ func (i *Identity) Role() org.RoleType {
|
|||||||
return i.OrgRoles[i.OrgID]
|
return i.OrgRoles[i.OrgID]
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: improve error handling
|
// NamespacedID returns the namespace, e.g. "user" and the id for that namespace
|
||||||
func (i *Identity) NamespacedID() (string, int64) {
|
func (i *Identity) NamespacedID() (string, int64) {
|
||||||
var (
|
|
||||||
id int64
|
|
||||||
namespace string
|
|
||||||
)
|
|
||||||
|
|
||||||
split := strings.Split(i.ID, ":")
|
split := strings.Split(i.ID, ":")
|
||||||
if len(split) != 2 {
|
if len(split) != 2 {
|
||||||
return "", -1
|
return "", -1
|
||||||
}
|
}
|
||||||
|
|
||||||
id, errI := strconv.ParseInt(split[1], 10, 64)
|
id, err := strconv.ParseInt(split[1], 10, 64)
|
||||||
if errI != nil {
|
if err != nil {
|
||||||
|
// FIXME (kalleep): Improve error handling
|
||||||
return "", -1
|
return "", -1
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace = split[0]
|
return split[0], id
|
||||||
|
|
||||||
return namespace, id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespacedID builds a namespaced ID from a namespace and an ID.
|
// NamespacedID builds a namespaced ID from a namespace and an ID.
|
||||||
|
|||||||
@@ -143,16 +143,15 @@ func ProvideService(
|
|||||||
// FIXME (jguer): move to User package
|
// FIXME (jguer): move to User package
|
||||||
userSyncService := sync.ProvideUserSync(userService, userProtectionService, authInfoService, quotaService)
|
userSyncService := sync.ProvideUserSync(userService, userProtectionService, authInfoService, quotaService)
|
||||||
orgUserSyncService := sync.ProvideOrgSync(userService, orgService, accessControlService)
|
orgUserSyncService := sync.ProvideOrgSync(userService, orgService, accessControlService)
|
||||||
s.RegisterPostAuthHook(userSyncService.SyncUser, 10)
|
s.RegisterPostAuthHook(userSyncService.SyncUserHook, 10)
|
||||||
s.RegisterPostAuthHook(orgUserSyncService.SyncOrgUser, 30)
|
s.RegisterPostAuthHook(orgUserSyncService.SyncOrgRolesHook, 30)
|
||||||
s.RegisterPostAuthHook(sync.ProvideUserLastSeenSync(userService).SyncLastSeen, 40)
|
s.RegisterPostAuthHook(userSyncService.SyncLastSeenHook, 40)
|
||||||
s.RegisterPostAuthHook(sync.ProvideAPIKeyLastSeenSync(apikeyService).SyncLastSeen, 50)
|
|
||||||
|
|
||||||
if features.IsEnabled(featuremgmt.FlagAccessTokenExpirationCheck) {
|
if features.IsEnabled(featuremgmt.FlagAccessTokenExpirationCheck) {
|
||||||
s.RegisterPostAuthHook(sync.ProvideOauthTokenSync(oauthTokenService, sessionService).SyncOauthToken, 60)
|
s.RegisterPostAuthHook(sync.ProvideOauthTokenSync(oauthTokenService, sessionService).SyncOauthTokenHook, 60)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.RegisterPostAuthHook(sync.ProvideFetchUserSync(userService).FetchSyncedUserHook, 100)
|
s.RegisterPostAuthHook(userSyncService.FetchSyncedUserHook, 100)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
package sync
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
|
||||||
"github.com/grafana/grafana/pkg/services/apikey"
|
|
||||||
"github.com/grafana/grafana/pkg/services/authn"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ProvideAPIKeyLastSeenSync(service apikey.Service) *APIKeyLastSeenSync {
|
|
||||||
return &APIKeyLastSeenSync{log.New("apikeylastseen.sync"), service}
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIKeyLastSeenSync struct {
|
|
||||||
log log.Logger
|
|
||||||
service apikey.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIKeyLastSeenSync) SyncLastSeen(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
|
||||||
namespace, id := identity.NamespacedID()
|
|
||||||
if namespace != authn.NamespaceAPIKey {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(apikeyID int64) {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
s.log.Error("panic during user last seen sync", "err", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err := s.service.UpdateAPIKeyLastUsedDate(context.Background(), apikeyID); err != nil {
|
|
||||||
s.log.Warn("failed to update last use date for api key", "id", apikeyID)
|
|
||||||
}
|
|
||||||
}(id)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package sync
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/authn"
|
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
|
||||||
"github.com/grafana/grafana/pkg/util/errutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errFetchingSignedInUser = errutil.NewBase(errutil.StatusInternal, "user.sync.fetch", errutil.WithPublicMessage("Insufficient information to authenticate user"))
|
|
||||||
|
|
||||||
func ProvideFetchUserSync(service user.Service) *FetchUserSync {
|
|
||||||
return &FetchUserSync{service}
|
|
||||||
}
|
|
||||||
|
|
||||||
type FetchUserSync struct {
|
|
||||||
userService user.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *FetchUserSync) FetchSyncedUserHook(ctx context.Context, identity *authn.Identity, r *authn.Request) error {
|
|
||||||
if !identity.ClientParams.FetchSyncedUser {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
namespace, id := identity.NamespacedID()
|
|
||||||
if namespace != authn.NamespaceUser {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
usr, err := s.userService.GetSignedInUserWithCacheCtx(ctx, &user.GetSignedInUserQuery{
|
|
||||||
UserID: id,
|
|
||||||
OrgID: r.OrgID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errFetchingSignedInUser.Errorf("failed to resolve user: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
syncSignedInUserToIdentity(usr, identity)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func syncSignedInUserToIdentity(usr *user.SignedInUser, identity *authn.Identity) {
|
|
||||||
identity.Name = usr.Name
|
|
||||||
identity.Login = usr.Login
|
|
||||||
identity.Email = usr.Email
|
|
||||||
identity.OrgID = usr.OrgID
|
|
||||||
identity.OrgName = usr.OrgName
|
|
||||||
identity.OrgCount = usr.OrgCount
|
|
||||||
identity.OrgRoles = map[int64]org.RoleType{identity.OrgID: usr.OrgRole}
|
|
||||||
identity.HelpFlags1 = usr.HelpFlags1
|
|
||||||
identity.Teams = usr.Teams
|
|
||||||
identity.LastSeenAt = usr.LastSeenAt
|
|
||||||
identity.IsDisabled = usr.IsDisabled
|
|
||||||
identity.IsGrafanaAdmin = &usr.IsGrafanaAdmin
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package sync
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/authn"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFetchUserSync_FetchSyncedUserHook(t *testing.T) {
|
|
||||||
type testCase struct {
|
|
||||||
desc string
|
|
||||||
req *authn.Request
|
|
||||||
identity *authn.Identity
|
|
||||||
expectedErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []testCase{
|
|
||||||
{
|
|
||||||
desc: "should skip hook when flag is not enabled",
|
|
||||||
req: &authn.Request{},
|
|
||||||
identity: &authn.Identity{ClientParams: authn.ClientParams{FetchSyncedUser: false}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "should skip hook when identity is not a user",
|
|
||||||
req: &authn.Request{},
|
|
||||||
identity: &authn.Identity{ID: "apikey:1", ClientParams: authn.ClientParams{FetchSyncedUser: true}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.desc, func(t *testing.T) {
|
|
||||||
s := ProvideFetchUserSync(nil)
|
|
||||||
err := s.FetchSyncedUserHook(context.Background(), tt.identity, tt.req)
|
|
||||||
require.ErrorIs(t, err, tt.expectedErr)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@ type OauthTokenSync struct {
|
|||||||
sessionService auth.UserTokenService
|
sessionService auth.UserTokenService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OauthTokenSync) SyncOauthToken(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
func (s *OauthTokenSync) SyncOauthTokenHook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
||||||
namespace, id := identity.NamespacedID()
|
namespace, id := identity.NamespacedID()
|
||||||
// only perform oauth token check if identity is a user
|
// only perform oauth token check if identity is a user
|
||||||
if namespace != authn.NamespaceUser {
|
if namespace != authn.NamespaceUser {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOauthTokenSync_SyncOauthToken(t *testing.T) {
|
func TestOauthTokenSync_SyncOauthTokenHook(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
desc string
|
desc string
|
||||||
identity *authn.Identity
|
identity *authn.Identity
|
||||||
@@ -123,7 +123,7 @@ func TestOauthTokenSync_SyncOauthToken(t *testing.T) {
|
|||||||
sessionService: sessionService,
|
sessionService: sessionService,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := sync.SyncOauthToken(context.Background(), tt.identity, nil)
|
err := sync.SyncOauthTokenHook(context.Background(), tt.identity, nil)
|
||||||
assert.ErrorIs(t, err, tt.expectedErr)
|
assert.ErrorIs(t, err, tt.expectedErr)
|
||||||
assert.Equal(t, tt.expectHasEntryCalled, hasEntryCalled)
|
assert.Equal(t, tt.expectHasEntryCalled, hasEntryCalled)
|
||||||
assert.Equal(t, tt.expectTryRefreshTokenCalled, tryRefreshCalled)
|
assert.Equal(t, tt.expectTryRefreshTokenCalled, tryRefreshCalled)
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ type OrgSync struct {
|
|||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrgSync) SyncOrgUser(ctx context.Context, id *authn.Identity, _ *authn.Request) error {
|
func (s *OrgSync) SyncOrgRolesHook(ctx context.Context, id *authn.Identity, _ *authn.Request) error {
|
||||||
if !id.ClientParams.SyncUser {
|
if !id.ClientParams.SyncUser {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, userID := id.NamespacedID()
|
namespace, userID := id.NamespacedID()
|
||||||
if namespace != "user" || userID <= 0 {
|
if namespace != authn.NamespaceUser || userID <= 0 {
|
||||||
s.log.Warn("invalid namespace %q for user ID %q", namespace, userID)
|
s.log.Warn("invalid namespace %q for user ID %q", namespace, userID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/user/usertest"
|
"github.com/grafana/grafana/pkg/services/user/usertest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOrgSync_SyncOrgUser(t *testing.T) {
|
func TestOrgSync_SyncOrgRolesHook(t *testing.T) {
|
||||||
orgService := &orgtest.FakeOrgService{ExpectedUserOrgDTO: []*org.UserOrgDTO{
|
orgService := &orgtest.FakeOrgService{ExpectedUserOrgDTO: []*org.UserOrgDTO{
|
||||||
{
|
{
|
||||||
OrgID: 1,
|
OrgID: 1,
|
||||||
@@ -116,8 +116,8 @@ func TestOrgSync_SyncOrgUser(t *testing.T) {
|
|||||||
accessControl: tt.fields.accessControl,
|
accessControl: tt.fields.accessControl,
|
||||||
log: tt.fields.log,
|
log: tt.fields.log,
|
||||||
}
|
}
|
||||||
if err := s.SyncOrgUser(tt.args.ctx, tt.args.id, nil); (err != nil) != tt.wantErr {
|
if err := s.SyncOrgRolesHook(tt.args.ctx, tt.args.id, nil); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("OrgSync.SyncOrgUser() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("OrgSync.SyncOrgRolesHook() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.EqualValues(t, tt.wantID, tt.args.id)
|
assert.EqualValues(t, tt.wantID, tt.args.id)
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package sync
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
|
||||||
"github.com/grafana/grafana/pkg/services/authn"
|
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ProvideUserLastSeenSync(service user.Service) *UserLastSeenSync {
|
|
||||||
return &UserLastSeenSync{log.New("userlastseen.sync"), service}
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserLastSeenSync struct {
|
|
||||||
log log.Logger
|
|
||||||
service user.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *UserLastSeenSync) SyncLastSeen(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
|
||||||
namespace, id := identity.NamespacedID()
|
|
||||||
|
|
||||||
if namespace != authn.NamespaceUser && namespace != authn.NamespaceServiceAccount {
|
|
||||||
// skip sync
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !shouldUpdateLastSeen(identity.LastSeenAt) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(userID int64) {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
s.log.Error("panic during user last seen sync", "err", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := s.service.UpdateLastSeenAt(context.Background(), &user.UpdateUserLastSeenAtCommand{UserID: userID}); err != nil {
|
|
||||||
s.log.Error("failed to update last_seen_at", "err", err, "userId", userID)
|
|
||||||
}
|
|
||||||
}(id)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldUpdateLastSeen(t time.Time) bool {
|
|
||||||
return time.Since(t) > time.Minute*5
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/services/authn"
|
"github.com/grafana/grafana/pkg/services/authn"
|
||||||
@@ -15,12 +16,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errSyncUserForbidden = errutil.NewBase(errutil.StatusForbidden,
|
errSyncUserForbidden = errutil.NewBase(
|
||||||
"user.sync.forbidden", errutil.WithPublicMessage("User sync forbidden"))
|
errutil.StatusForbidden,
|
||||||
errSyncUserInternal = errutil.NewBase(errutil.StatusInternal,
|
"user.sync.forbidden",
|
||||||
"user.sync.forbidden", errutil.WithPublicMessage("User sync failed"))
|
errutil.WithPublicMessage("User sync forbidden"),
|
||||||
errUserProtection = errutil.NewBase(errutil.StatusForbidden,
|
)
|
||||||
"user.sync.protectedrole", errutil.WithPublicMessage("Unable to sync due to protected role"))
|
errSyncUserInternal = errutil.NewBase(
|
||||||
|
errutil.StatusInternal,
|
||||||
|
"user.sync.forbidden",
|
||||||
|
errutil.WithPublicMessage("User sync failed"),
|
||||||
|
)
|
||||||
|
errUserProtection = errutil.NewBase(
|
||||||
|
errutil.StatusForbidden,
|
||||||
|
"user.sync.protected-role",
|
||||||
|
errutil.WithPublicMessage("Unable to sync due to protected role"),
|
||||||
|
)
|
||||||
|
errFetchingSignedInUser = errutil.NewBase(
|
||||||
|
errutil.StatusInternal,
|
||||||
|
"user.sync.fetch",
|
||||||
|
errutil.WithPublicMessage("Insufficient information to authenticate user"),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideUserSync(userService user.Service,
|
func ProvideUserSync(userService user.Service,
|
||||||
@@ -43,14 +58,14 @@ type UserSync struct {
|
|||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncUser syncs a user with the database
|
// SyncUserHook syncs a user with the database
|
||||||
func (s *UserSync) SyncUser(ctx context.Context, id *authn.Identity, _ *authn.Request) error {
|
func (s *UserSync) SyncUserHook(ctx context.Context, id *authn.Identity, _ *authn.Request) error {
|
||||||
if !id.ClientParams.SyncUser {
|
if !id.ClientParams.SyncUser {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does user exist in the database?
|
// Does user exist in the database?
|
||||||
usr, errUserInDB := s.UserInDB(ctx, &id.AuthModule, &id.AuthID, id.ClientParams.LookUpParams)
|
usr, errUserInDB := s.getUser(ctx, id.AuthModule, id.AuthID, id.ClientParams.LookUpParams)
|
||||||
if errUserInDB != nil && !errors.Is(errUserInDB, user.ErrUserNotFound) {
|
if errUserInDB != nil && !errors.Is(errUserInDB, user.ErrUserNotFound) {
|
||||||
s.log.Error("error retrieving user", "error", errUserInDB,
|
s.log.Error("error retrieving user", "error", errUserInDB,
|
||||||
"auth_module", id.AuthModule, "auth_id", id.AuthID,
|
"auth_module", id.AuthModule, "auth_id", id.AuthID,
|
||||||
@@ -66,20 +81,6 @@ func (s *UserSync) SyncUser(ctx context.Context, id *authn.Identity, _ *authn.Re
|
|||||||
return errSyncUserForbidden.Errorf("%w", login.ErrSignupNotAllowed)
|
return errSyncUserForbidden.Errorf("%w", login.ErrSignupNotAllowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// quota check (FIXME: (jguer) this should be done in the user service)
|
|
||||||
// we may insert in both user and org_user tables
|
|
||||||
// therefore we need to query check quota for both user and org services
|
|
||||||
for _, srv := range []string{user.QuotaTargetSrv, org.QuotaTargetSrv} {
|
|
||||||
limitReached, errLimit := s.quotaService.CheckQuotaReached(ctx, quota.TargetSrv(srv), nil)
|
|
||||||
if errLimit != nil {
|
|
||||||
s.log.Error("error getting user quota", "error", errLimit)
|
|
||||||
return errSyncUserInternal.Errorf("%w", login.ErrGettingUserQuota)
|
|
||||||
}
|
|
||||||
if limitReached {
|
|
||||||
return errSyncUserForbidden.Errorf("%w", login.ErrUsersQuotaReached)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create user
|
// create user
|
||||||
var errCreate error
|
var errCreate error
|
||||||
usr, errCreate = s.createUser(ctx, id)
|
usr, errCreate = s.createUser(ctx, id)
|
||||||
@@ -108,7 +109,7 @@ func (s *UserSync) SyncUser(ctx context.Context, id *authn.Identity, _ *authn.Re
|
|||||||
|
|
||||||
syncUserToIdentity(usr, id)
|
syncUserToIdentity(usr, id)
|
||||||
|
|
||||||
// persist latest auth info token
|
// persist the latest auth info token
|
||||||
if errAuthInfo := s.updateAuthInfo(ctx, id); errAuthInfo != nil {
|
if errAuthInfo := s.updateAuthInfo(ctx, id); errAuthInfo != nil {
|
||||||
s.log.Error("error creating user", "error", errAuthInfo,
|
s.log.Error("error creating user", "error", errAuthInfo,
|
||||||
"auth_module", id.AuthModule, "auth_id", id.AuthID,
|
"auth_module", id.AuthModule, "auth_id", id.AuthID,
|
||||||
@@ -119,14 +120,52 @@ func (s *UserSync) SyncUser(ctx context.Context, id *authn.Identity, _ *authn.Re
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncUserToIdentity syncs a user to an identity.
|
func (s *UserSync) FetchSyncedUserHook(ctx context.Context, identity *authn.Identity, r *authn.Request) error {
|
||||||
// This is used to update the identity with the latest user information.
|
if !identity.ClientParams.FetchSyncedUser {
|
||||||
func syncUserToIdentity(usr *user.User, id *authn.Identity) {
|
return nil
|
||||||
id.ID = fmt.Sprintf("user:%d", usr.ID)
|
}
|
||||||
id.Login = usr.Login
|
namespace, id := identity.NamespacedID()
|
||||||
id.Email = usr.Email
|
if namespace != authn.NamespaceUser {
|
||||||
id.Name = usr.Name
|
return nil
|
||||||
id.IsGrafanaAdmin = &usr.IsAdmin
|
}
|
||||||
|
|
||||||
|
usr, err := s.userService.GetSignedInUserWithCacheCtx(ctx, &user.GetSignedInUserQuery{
|
||||||
|
UserID: id,
|
||||||
|
OrgID: r.OrgID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errFetchingSignedInUser.Errorf("failed to resolve user: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
syncSignedInUserToIdentity(usr, identity)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserSync) SyncLastSeenHook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
||||||
|
namespace, id := identity.NamespacedID()
|
||||||
|
|
||||||
|
if namespace != authn.NamespaceUser && namespace != authn.NamespaceServiceAccount {
|
||||||
|
// skip sync
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shouldUpdateLastSeen(identity.LastSeenAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
go func(userID int64) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
s.log.Error("panic during user last seen sync", "err", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := s.userService.UpdateLastSeenAt(context.Background(), &user.UpdateUserLastSeenAtCommand{UserID: userID}); err != nil {
|
||||||
|
s.log.Error("failed to update last_seen_at", "err", err, "userId", userID)
|
||||||
|
}
|
||||||
|
}(id)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *UserSync) updateAuthInfo(ctx context.Context, id *authn.Identity) error {
|
func (s *UserSync) updateAuthInfo(ctx context.Context, id *authn.Identity) error {
|
||||||
@@ -135,7 +174,7 @@ func (s *UserSync) updateAuthInfo(ctx context.Context, id *authn.Identity) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace, userID := id.NamespacedID()
|
namespace, userID := id.NamespacedID()
|
||||||
if namespace != "user" && userID <= 0 { // FIXME: constant namespace
|
if namespace != authn.NamespaceUser && userID <= 0 {
|
||||||
return fmt.Errorf("invalid namespace %q for user ID %q", namespace, userID)
|
return fmt.Errorf("invalid namespace %q for user ID %q", namespace, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,12 +242,25 @@ func (s *UserSync) updateUserAttributes(ctx context.Context, usr *user.User, id
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *UserSync) createUser(ctx context.Context, id *authn.Identity) (*user.User, error) {
|
func (s *UserSync) createUser(ctx context.Context, id *authn.Identity) (*user.User, error) {
|
||||||
|
// quota check (FIXME: (jguer) this should be done in the user service)
|
||||||
|
// we may insert in both user and org_user tables
|
||||||
|
// therefore we need to query check quota for both user and org services
|
||||||
|
for _, srv := range []string{user.QuotaTargetSrv, org.QuotaTargetSrv} {
|
||||||
|
limitReached, errLimit := s.quotaService.CheckQuotaReached(ctx, quota.TargetSrv(srv), nil)
|
||||||
|
if errLimit != nil {
|
||||||
|
s.log.Error("error getting user quota", "error", errLimit)
|
||||||
|
return nil, errSyncUserInternal.Errorf("%w", login.ErrGettingUserQuota)
|
||||||
|
}
|
||||||
|
if limitReached {
|
||||||
|
return nil, errSyncUserForbidden.Errorf("%w", login.ErrUsersQuotaReached)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isAdmin := false
|
isAdmin := false
|
||||||
if id.IsGrafanaAdmin != nil {
|
if id.IsGrafanaAdmin != nil {
|
||||||
isAdmin = *id.IsGrafanaAdmin
|
isAdmin = *id.IsGrafanaAdmin
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add quota check
|
|
||||||
usr, errCreateUser := s.userService.Create(ctx, &user.CreateUserCommand{
|
usr, errCreateUser := s.userService.Create(ctx, &user.CreateUserCommand{
|
||||||
Login: id.Login,
|
Login: id.Login,
|
||||||
Email: id.Email,
|
Email: id.Email,
|
||||||
@@ -234,18 +286,12 @@ func (s *UserSync) createUser(ctx context.Context, id *authn.Identity) (*user.Us
|
|||||||
return usr, nil
|
return usr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does user exist in the database?
|
func (s *UserSync) getUser(ctx context.Context, authModule, authID string, params login.UserLookupParams) (*user.User, error) {
|
||||||
// Check first authinfo table, then user table
|
// Check auth info fist
|
||||||
// return user id if found, 0 if not found
|
if authID != "" && authModule != "" {
|
||||||
func (s *UserSync) UserInDB(ctx context.Context,
|
|
||||||
authID *string,
|
|
||||||
authModule *string,
|
|
||||||
params login.UserLookupParams) (*user.User, error) {
|
|
||||||
// Check authinfo table
|
|
||||||
if authID != nil && authModule != nil {
|
|
||||||
query := &login.GetAuthInfoQuery{
|
query := &login.GetAuthInfoQuery{
|
||||||
AuthModule: *authModule,
|
AuthModule: authModule,
|
||||||
AuthId: *authID,
|
AuthId: authID,
|
||||||
}
|
}
|
||||||
errGetAuthInfo := s.authInfoService.GetAuthInfo(ctx, query)
|
errGetAuthInfo := s.authInfoService.GetAuthInfo(ctx, query)
|
||||||
if errGetAuthInfo == nil {
|
if errGetAuthInfo == nil {
|
||||||
@@ -265,10 +311,10 @@ func (s *UserSync) UserInDB(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check user table to grab existing user
|
// Check user table to grab existing user
|
||||||
return s.LookupByOneOf(ctx, ¶ms)
|
return s.lookupByOneOf(ctx, ¶ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *UserSync) LookupByOneOf(ctx context.Context, params *login.UserLookupParams) (*user.User, error) {
|
func (s *UserSync) lookupByOneOf(ctx context.Context, params *login.UserLookupParams) (*user.User, error) {
|
||||||
var usr *user.User
|
var usr *user.User
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -302,3 +348,33 @@ func (s *UserSync) LookupByOneOf(ctx context.Context, params *login.UserLookupPa
|
|||||||
|
|
||||||
return usr, nil
|
return usr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// syncUserToIdentity syncs a user to an identity.
|
||||||
|
// This is used to update the identity with the latest user information.
|
||||||
|
func syncUserToIdentity(usr *user.User, id *authn.Identity) {
|
||||||
|
id.ID = fmt.Sprintf("user:%d", usr.ID)
|
||||||
|
id.Login = usr.Login
|
||||||
|
id.Email = usr.Email
|
||||||
|
id.Name = usr.Name
|
||||||
|
id.IsGrafanaAdmin = &usr.IsAdmin
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncSignedInUserToIdentity syncs a user to an identity.
|
||||||
|
func syncSignedInUserToIdentity(usr *user.SignedInUser, identity *authn.Identity) {
|
||||||
|
identity.Name = usr.Name
|
||||||
|
identity.Login = usr.Login
|
||||||
|
identity.Email = usr.Email
|
||||||
|
identity.OrgID = usr.OrgID
|
||||||
|
identity.OrgName = usr.OrgName
|
||||||
|
identity.OrgCount = usr.OrgCount
|
||||||
|
identity.OrgRoles = map[int64]org.RoleType{identity.OrgID: usr.OrgRole}
|
||||||
|
identity.HelpFlags1 = usr.HelpFlags1
|
||||||
|
identity.Teams = usr.Teams
|
||||||
|
identity.LastSeenAt = usr.LastSeenAt
|
||||||
|
identity.IsDisabled = usr.IsDisabled
|
||||||
|
identity.IsGrafanaAdmin = &usr.IsGrafanaAdmin
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldUpdateLastSeen(t time.Time) bool {
|
||||||
|
return time.Since(t) > time.Minute*5
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func ptrInt64(i int64) *int64 {
|
|||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserSync_SyncUser(t *testing.T) {
|
func TestUserSync_SyncUserHook(t *testing.T) {
|
||||||
userProtection := &authinfoservice.OSSUserProtectionImpl{}
|
userProtection := &authinfoservice.OSSUserProtectionImpl{}
|
||||||
|
|
||||||
authFakeNil := &logintest.AuthInfoServiceFake{
|
authFakeNil := &logintest.AuthInfoServiceFake{
|
||||||
@@ -266,12 +266,13 @@ func TestUserSync_SyncUser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
|
|
||||||
id: &authn.Identity{
|
id: &authn.Identity{
|
||||||
ID: "",
|
ID: "",
|
||||||
Login: "test",
|
AuthID: "2032",
|
||||||
Name: "test",
|
AuthModule: "oauth",
|
||||||
Email: "test",
|
Login: "test",
|
||||||
|
Name: "test",
|
||||||
|
Email: "test",
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
LookUpParams: login.UserLookupParams{
|
LookUpParams: login.UserLookupParams{
|
||||||
@@ -285,6 +286,8 @@ func TestUserSync_SyncUser(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
wantID: &authn.Identity{
|
wantID: &authn.Identity{
|
||||||
ID: "user:1",
|
ID: "user:1",
|
||||||
|
AuthID: "2032",
|
||||||
|
AuthModule: "oauth",
|
||||||
Login: "test",
|
Login: "test",
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Email: "test",
|
Email: "test",
|
||||||
@@ -427,7 +430,7 @@ func TestUserSync_SyncUser(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
s := ProvideUserSync(tt.fields.userService, userProtection, tt.fields.authInfoService, tt.fields.quotaService)
|
s := ProvideUserSync(tt.fields.userService, userProtection, tt.fields.authInfoService, tt.fields.quotaService)
|
||||||
err := s.SyncUser(tt.args.ctx, tt.args.id, nil)
|
err := s.SyncUserHook(tt.args.ctx, tt.args.id, nil)
|
||||||
if tt.wantErr {
|
if tt.wantErr {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
return
|
return
|
||||||
@@ -438,3 +441,33 @@ func TestUserSync_SyncUser(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserSync_FetchSyncedUserHook(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
desc string
|
||||||
|
req *authn.Request
|
||||||
|
identity *authn.Identity
|
||||||
|
expectedErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []testCase{
|
||||||
|
{
|
||||||
|
desc: "should skip hook when flag is not enabled",
|
||||||
|
req: &authn.Request{},
|
||||||
|
identity: &authn.Identity{ClientParams: authn.ClientParams{FetchSyncedUser: false}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should skip hook when identity is not a user",
|
||||||
|
req: &authn.Request{},
|
||||||
|
identity: &authn.Identity{ID: "apikey:1", ClientParams: authn.ClientParams{FetchSyncedUser: true}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.desc, func(t *testing.T) {
|
||||||
|
s := UserSync{}
|
||||||
|
err := s.FetchSyncedUserHook(context.Background(), tt.identity, tt.req)
|
||||||
|
require.ErrorIs(t, err, tt.expectedErr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ var (
|
|||||||
errAPIKeyRevoked = errutil.NewBase(errutil.StatusUnauthorized, "api-key.revoked", errutil.WithPublicMessage("Revoked API key"))
|
errAPIKeyRevoked = errutil.NewBase(errutil.StatusUnauthorized, "api-key.revoked", errutil.WithPublicMessage("Revoked API key"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ authn.HookClient = new(APIKey)
|
||||||
var _ authn.ContextAwareClient = new(APIKey)
|
var _ authn.ContextAwareClient = new(APIKey)
|
||||||
|
|
||||||
func ProvideAPIKey(apiKeyService apikey.Service, userService user.Service) *APIKey {
|
func ProvideAPIKey(apiKeyService apikey.Service, userService user.Service) *APIKey {
|
||||||
@@ -141,6 +142,26 @@ func (s *APIKey) Priority() uint {
|
|||||||
return 30
|
return 30
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *APIKey) Hook(ctx context.Context, identity *authn.Identity, r *authn.Request) error {
|
||||||
|
namespace, id := identity.NamespacedID()
|
||||||
|
if namespace != authn.NamespaceAPIKey {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
go func(apikeyID int64) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
s.log.Error("panic during user last seen sync", "err", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err := s.apiKeyService.UpdateAPIKeyLastUsedDate(context.Background(), apikeyID); err != nil {
|
||||||
|
s.log.Warn("failed to update last use date for api key", "id", apikeyID)
|
||||||
|
}
|
||||||
|
}(id)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func looksLikeApiKey(token string) bool {
|
func looksLikeApiKey(token string) bool {
|
||||||
return token != ""
|
return token != ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func (c *Grafana) AuthenticateProxy(ctx context.Context, r *authn.Request, usern
|
|||||||
AuthID: username,
|
AuthID: username,
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
AllowSignUp: c.cfg.AuthProxyAutoSignUp,
|
AllowSignUp: c.cfg.AuthProxyAutoSignUp,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func TestGrafana_AuthenticateProxy(t *testing.T) {
|
|||||||
Groups: []string{"grp1", "grp2"},
|
Groups: []string{"grp1", "grp2"},
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
AllowSignUp: true,
|
AllowSignUp: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
LookUpParams: login.UserLookupParams{
|
LookUpParams: login.UserLookupParams{
|
||||||
@@ -71,9 +71,9 @@ func TestGrafana_AuthenticateProxy(t *testing.T) {
|
|||||||
AuthModule: "authproxy",
|
AuthModule: "authproxy",
|
||||||
AuthID: "test@test.com",
|
AuthID: "test@test.com",
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
AllowSignUp: true,
|
AllowSignUp: true,
|
||||||
LookUpParams: login.UserLookupParams{
|
LookUpParams: login.UserLookupParams{
|
||||||
Email: strPtr("test@test.com"),
|
Email: strPtr("test@test.com"),
|
||||||
Login: strPtr("test@test.com"),
|
Login: strPtr("test@test.com"),
|
||||||
@@ -110,7 +110,7 @@ func TestGrafana_AuthenticateProxy(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncUser, identity.ClientParams.SyncUser)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncUser, identity.ClientParams.SyncUser)
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.AllowSignUp, identity.ClientParams.AllowSignUp)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.AllowSignUp, identity.ClientParams.AllowSignUp)
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncTeamMembers, identity.ClientParams.SyncTeamMembers)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncTeams, identity.ClientParams.SyncTeams)
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.EnableDisabledUsers, identity.ClientParams.EnableDisabledUsers)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.EnableDisabledUsers, identity.ClientParams.EnableDisabledUsers)
|
||||||
|
|
||||||
assert.EqualValues(t, tt.expectedIdentity.ClientParams.LookUpParams.Email, identity.ClientParams.LookUpParams.Email)
|
assert.EqualValues(t, tt.expectedIdentity.ClientParams.LookUpParams.Email, identity.ClientParams.LookUpParams.Email)
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func identityFromLDAPInfo(orgID int64, info *login.ExternalUserInfo, allowSignup
|
|||||||
Groups: info.Groups,
|
Groups: info.Groups,
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
EnableDisabledUsers: true,
|
EnableDisabledUsers: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
AllowSignUp: allowSignup,
|
AllowSignUp: allowSignup,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func TestLDAP_AuthenticateProxy(t *testing.T) {
|
|||||||
Groups: []string{"1", "2"},
|
Groups: []string{"1", "2"},
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
EnableDisabledUsers: true,
|
EnableDisabledUsers: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
LookUpParams: login.UserLookupParams{
|
LookUpParams: login.UserLookupParams{
|
||||||
@@ -113,7 +113,7 @@ func TestLDAP_AuthenticatePassword(t *testing.T) {
|
|||||||
Groups: []string{"1", "2"},
|
Groups: []string{"1", "2"},
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
EnableDisabledUsers: true,
|
EnableDisabledUsers: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
LookUpParams: login.UserLookupParams{
|
LookUpParams: login.UserLookupParams{
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (c *OAuth) Authenticate(ctx context.Context, r *authn.Request) (*authn.Iden
|
|||||||
OrgRoles: getOAuthOrgRole(userInfo, c.cfg),
|
OrgRoles: getOAuthOrgRole(userInfo, c.cfg),
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
AllowSignUp: c.connector.IsSignupAllowed(),
|
AllowSignUp: c.connector.IsSignupAllowed(),
|
||||||
LookUpParams: login.UserLookupParams{Email: &userInfo.Email},
|
LookUpParams: login.UserLookupParams{Email: &userInfo.Email},
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ func TestOAuth_Authenticate(t *testing.T) {
|
|||||||
OrgRoles: map[int64]org.RoleType{1: org.RoleAdmin},
|
OrgRoles: map[int64]org.RoleType{1: org.RoleAdmin},
|
||||||
ClientParams: authn.ClientParams{
|
ClientParams: authn.ClientParams{
|
||||||
SyncUser: true,
|
SyncUser: true,
|
||||||
SyncTeamMembers: true,
|
SyncTeams: true,
|
||||||
AllowSignUp: true,
|
AllowSignUp: true,
|
||||||
FetchSyncedUser: true,
|
FetchSyncedUser: true,
|
||||||
LookUpParams: login.UserLookupParams{Email: strPtr("some@email.com")},
|
LookUpParams: login.UserLookupParams{Email: strPtr("some@email.com")},
|
||||||
@@ -180,7 +180,7 @@ func TestOAuth_Authenticate(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncUser, identity.ClientParams.SyncUser)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncUser, identity.ClientParams.SyncUser)
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.AllowSignUp, identity.ClientParams.AllowSignUp)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.AllowSignUp, identity.ClientParams.AllowSignUp)
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncTeamMembers, identity.ClientParams.SyncTeamMembers)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.SyncTeams, identity.ClientParams.SyncTeams)
|
||||||
assert.Equal(t, tt.expectedIdentity.ClientParams.EnableDisabledUsers, identity.ClientParams.EnableDisabledUsers)
|
assert.Equal(t, tt.expectedIdentity.ClientParams.EnableDisabledUsers, identity.ClientParams.EnableDisabledUsers)
|
||||||
|
|
||||||
assert.EqualValues(t, tt.expectedIdentity.ClientParams.LookUpParams.Email, identity.ClientParams.LookUpParams.Email)
|
assert.EqualValues(t, tt.expectedIdentity.ClientParams.LookUpParams.Email, identity.ClientParams.LookUpParams.Email)
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ func (s *Session) Authenticate(ctx context.Context, r *authn.Request) (*authn.Id
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME (jguer): oauth token refresh not implemented
|
|
||||||
identity := authn.IdentityFromSignedInUser(authn.NamespacedID(authn.NamespaceUser, signedInUser.UserID), signedInUser, authn.ClientParams{})
|
identity := authn.IdentityFromSignedInUser(authn.NamespacedID(authn.NamespaceUser, signedInUser.UserID), signedInUser, authn.ClientParams{})
|
||||||
identity.SessionToken = token
|
identity.SessionToken = token
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user