Skip to content

Commit 519b51c

Browse files
committed
adds sync org middleware
1 parent 6ff6066 commit 519b51c

4 files changed

Lines changed: 52 additions & 19 deletions

File tree

cmd/devguard/api/api.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,26 @@ func neededScope(neededScopes []string) core.MiddlewareFunc {
253253
}
254254
}
255255

256+
func externalEntityProviderOrgSyncMiddleware(externalEntityProviderService core.ExternalEntityProviderService) core.MiddlewareFunc {
257+
limiter := map[string]time.Time{}
258+
return func(next echo.HandlerFunc) echo.HandlerFunc {
259+
return func(ctx core.Context) error {
260+
261+
key := core.GetSession(ctx).GetUserID()
262+
if _, ok := limiter[key]; !ok || time.Now().After(limiter[key]) {
263+
slog.Info("syncing external entity provider orgs", "userID", key)
264+
limiter[key] = time.Now().Add(15 * time.Minute)
265+
go func() {
266+
if err := externalEntityProviderService.SyncOrgs(ctx); err != nil {
267+
slog.Error("could not sync external entity provider orgs", "err", err, "userID", key)
268+
}
269+
}()
270+
}
271+
return next(ctx)
272+
}
273+
}
274+
}
275+
256276
func externalEntityProviderRefreshMiddleware(externalEntityProviderService core.ExternalEntityProviderService) core.MiddlewareFunc {
257277
limiter := map[string]time.Time{}
258278

@@ -521,7 +541,7 @@ func BuildRouter(db core.DB) *echo.Echo {
521541
apiV1Router.GET("/lookup/", assetController.HandleLookup)
522542

523543
// everything below this line is protected by the session middleware
524-
sessionRouter := apiV1Router.Group("", auth.SessionMiddleware(core.NewAdminClient(ory), patService))
544+
sessionRouter := apiV1Router.Group("", auth.SessionMiddleware(core.NewAdminClient(ory), patService), externalEntityProviderOrgSyncMiddleware(externalEntityProviderService))
525545
sessionRouter.GET("/oauth2/gitlab/:integrationName/", integrationController.GitLabOauth2Login)
526546
sessionRouter.GET("/oauth2/gitlab/callback/:integrationName/", integrationController.GitLabOauth2Callback)
527547

internal/core/common_interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ type InvitationRepository interface {
223223

224224
type ExternalEntityProviderService interface {
225225
RefreshExternalEntityProviderProjects(ctx Context, org models.Org, user string) error
226+
SyncOrgs(c echo.Context) error
226227
}
227228

228229
type ProjectService interface {

internal/core/integrations/external_entity_provider_service.go

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,40 @@ func (s externalEntityProviderService) TriggerSync(c echo.Context) error {
5252
return echo.NewHTTPError(400, "organization is not an external entity provider")
5353
}
5454

55-
func (s externalEntityProviderService) syncOrgs(c echo.Context) error {
55+
func (s externalEntityProviderService) SyncOrgs(c echo.Context) error {
5656
// return the enabled git providers as well
5757
thirdPartyIntegration := core.GetThirdPartyIntegration(c)
58-
orgs, err := thirdPartyIntegration.ListOrgs(c)
59-
if err != nil {
60-
return fmt.Errorf("could not list organizations: %w", err)
61-
}
62-
// make sure, that the third party organizations exists inside the database
63-
if err := s.organizationRepository.Upsert(utils.Ptr(utils.Map(orgs, utils.Ptr)), []clause.Column{
64-
{Name: "external_entity_provider_id"},
65-
}, nil); err != nil {
66-
return fmt.Errorf("could not upsert organizations: %w", err)
67-
}
68-
return nil
58+
userID := core.GetSession(c).GetUserID()
59+
_, err, _ := s.singleFlightGroup.Do("syncOrgs/"+userID, func() (any, error) {
60+
orgs, err := thirdPartyIntegration.ListOrgs(c)
61+
if err != nil {
62+
return nil, fmt.Errorf("could not list organizations: %w", err)
63+
}
64+
65+
orgsPtr := utils.Map(orgs, utils.Ptr)
66+
67+
// make sure, that the third party organizations exists inside the database
68+
if err := s.organizationRepository.Upsert(&orgsPtr, []clause.Column{
69+
{Name: "external_entity_provider_id"},
70+
}, nil); err != nil {
71+
return nil, fmt.Errorf("could not upsert organizations: %w", err)
72+
}
73+
74+
// make sure the user is a member of the organizations
75+
for _, org := range orgsPtr {
76+
if err := s.rbacProvider.GetDomainRBAC(org.GetID().String()).GrantRole(userID, core.RoleMember); err != nil {
77+
slog.Warn("could not grant role for user in organization", "user", userID, "orgID", org.GetID(), "err", err)
78+
}
79+
}
80+
81+
return nil, nil
82+
})
83+
84+
return err
6985
}
7086

7187
func (s externalEntityProviderService) RefreshExternalEntityProviderProjects(ctx core.Context, org models.Org, user string) error {
72-
err := s.syncOrgs(ctx)
73-
if err != nil {
74-
slog.Warn("could not sync organizations", "orgID", org.GetID(), "user", user, "err", err)
75-
return err
76-
}
88+
7789
_, err, shared := s.singleFlightGroup.Do(org.ID.String()+"/"+user, func() (any, error) {
7890
if org.ExternalEntityProviderID == nil {
7991
return nil, fmt.Errorf("organization %s does not have an external entity provider configured", org.GetID())

internal/core/integrations/gitlabint/gitlab_integration.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ func (g *GitlabIntegration) HasAccessToExternalEntityProvider(ctx core.Context,
245245

246246
func (g *GitlabIntegration) checkIfTokenIsValid(ctx core.Context, token models.GitLabOauth2Token) bool {
247247
// create a new gitlab batch client
248-
gitlabClient, err := g.clientFactory.FromOauth2Token(token, true)
248+
gitlabClient, err := g.clientFactory.FromOauth2Token(token, false)
249249
if err != nil {
250250
slog.Error("failed to create gitlab batch client", "err", err)
251251
return false

0 commit comments

Comments
 (0)