Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions changelog/unreleased/oidc-profile-picture-sync.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the changelog folder, it seems we're not doing changelog items there anymore - but I'm not sure about that

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's correct. Changelog is being built from PR titles (linking to the PRs) by the ready-release-go. So having a meaningful PR title and description is all you need. This changelog item can be deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Enhancement: Sync user profile pictures from OIDC claims

The proxy now reads a profile picture URL from the OIDC `picture` claim (configurable
via `PROXY_AUTOPROVISION_CLAIM_PICTURE`, defaults to the standard `picture` claim,
set to an empty string to disable) and emits a `ProfilePictureSyncRequested` event.
The graph service consumes this event, downloads the image and stores it as the
user's avatar. Allowed image URLs can be restricted via
`GRAPH_PROFILE_PICTURE_URL_ALLOWLIST` (glob patterns, defaults to the OpenCloud URL
host). A `UserProfilePictureUpdated` event is emitted after a successful update so
the UI can refresh the avatar without a page reload.

https://github.com/opencloud-eu/opencloud/issues/1499
https://github.com/opencloud-eu/opencloud/pull/2704
25 changes: 25 additions & 0 deletions pkg/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
)

type ResourceMention struct {
Expand All @@ -20,3 +21,27 @@ func (ResourceMention) Unmarshal(v []byte) (interface{}, error) {
err := json.Unmarshal(v, &e)
return e, err
}

type ProfilePictureSyncRequested struct {
Executant *user.UserId
PictureURL string `json:",omitempty"`
Timestamp *types.Timestamp
}

func (ProfilePictureSyncRequested) Unmarshal(v []byte) (interface{}, error) {
e := ProfilePictureSyncRequested{}
err := json.Unmarshal(v, &e)
return e, err
}

// UserProfilePictureUpdated can be consumed by frontend-facing services to refresh the avatar without a page reload.
type UserProfilePictureUpdated struct {
Executant *user.UserId
Timestamp *types.Timestamp
}

func (UserProfilePictureUpdated) Unmarshal(v []byte) (interface{}, error) {
e := UserProfilePictureUpdated{}
err := json.Unmarshal(v, &e)
return e, err
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nitpick: one event has User prefix, one has not - feels a bit inconsistent

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

188 changes: 100 additions & 88 deletions services/graph/mocks/users_user_profile_photo_provider.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions services/graph/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ type Config struct {
TokenManager *TokenManager `yaml:"token_manager"`
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`

Application Application `yaml:"application"`
Spaces Spaces `yaml:"spaces"`
Identity Identity `yaml:"identity"`
IncludeOCMSharees bool `yaml:"include_ocm_sharees" env:"OC_ENABLE_OCM;GRAPH_INCLUDE_OCM_SHAREES" desc:"Include OCM sharees when listing users." introductionVersion:"1.0.0"`
Events Events `yaml:"events"`
UnifiedRoles UnifiedRoles `yaml:"unified_roles"`
MaxConcurrency int `yaml:"max_concurrency" env:"OC_MAX_CONCURRENCY;GRAPH_MAX_CONCURRENCY" desc:"The maximum number of concurrent requests the service will handle." introductionVersion:"1.0.0"`
Application Application `yaml:"application"`
Spaces Spaces `yaml:"spaces"`
Identity Identity `yaml:"identity"`
ProfilePictureURLAllowlist []string `yaml:"profile_picture_url_allowlist" env:"GRAPH_PROFILE_PICTURE_URL_ALLOWLIST" desc:"A comma separated allowlist of URL patterns accepted for profile-picture sync events. Patterns can be full URLs with glob support in the host (for example 'https://*.example.com') or '*' to allow all URLs (dangerous: only use if the IdP is fully trusted to provide safe URLs, otherwise this is an SSRF attack vector). If empty, the OpenCloud URL host is allowed by default." introductionVersion:"6.3.0"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

introductionVersion needs to be %%NEXT%% for all newly introduced config settings. It will be replaced with the correct version during the release process.

IncludeOCMSharees bool `yaml:"include_ocm_sharees" env:"OC_ENABLE_OCM;GRAPH_INCLUDE_OCM_SHAREES" desc:"Include OCM sharees when listing users." introductionVersion:"1.0.0"`
Events Events `yaml:"events"`
UnifiedRoles UnifiedRoles `yaml:"unified_roles"`
MaxConcurrency int `yaml:"max_concurrency" env:"OC_MAX_CONCURRENCY;GRAPH_MAX_CONCURRENCY" desc:"The maximum number of concurrent requests the service will handle." introductionVersion:"1.0.0"`

Keycloak Keycloak `yaml:"keycloak"`
ServiceAccount ServiceAccount `yaml:"service_account"`
Expand Down
1 change: 1 addition & 0 deletions services/graph/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func DefaultConfig() *config.Config {
EducationResourcesEnabled: false,
},
},
ProfilePictureURLAllowlist: []string{},
Cache: &config.Cache{
Store: "memory",
Nodes: []string{"127.0.0.1:9233"},
Expand Down
Loading