Repository: owncloud/ocis
Pull request #11479 (2025-06-30 06:39:33)

[full-ci] chore: backport fix return translated role definitions
Backports fix for unified role translations

sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=11479) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=11479&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=11479&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=11479&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=11479&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [6.6% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=11479&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=11479)



Patch:
diff --git a/changelog/unreleased/fix-return-translated-role-definitions.md b/changelog/unreleased/fix-return-translated-role-definitions.md
new file mode 100644
index 00000000000..c766ad14cef
--- /dev/null
+++ b/changelog/unreleased/fix-return-translated-role-definitions.md
@@ -0,0 +1,5 @@
+Bugfix: Return translated role definitions
+
+Instead of always returning the role definitions in English, we now return the role definitions in the language set in the `Accept-Language` header if present.
+
+https://github.com/owncloud/ocis/pull/11466
diff --git a/services/graph/pkg/service/v0/api_driveitem_permissions.go b/services/graph/pkg/service/v0/api_driveitem_permissions.go
index 9cb643cb325..33bcdf79b90 100644
--- a/services/graph/pkg/service/v0/api_driveitem_permissions.go
+++ b/services/graph/pkg/service/v0/api_driveitem_permissions.go
@@ -28,6 +28,7 @@ import (
 	"github.com/cs3org/reva/v2/pkg/utils"
 
 	"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
+	settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
 	l10n_pkg "github.com/owncloud/ocis/v2/services/graph/pkg/l10n"
 
 	"github.com/owncloud/ocis/v2/ocis-pkg/conversions"
@@ -614,14 +615,16 @@ type DriveItemPermissionsApi struct {
 	logger                      log.Logger
 	driveItemPermissionsService DriveItemPermissionsProvider
 	config                      *config.Config
+	valueService                settingssvc.ValueService
 }
 
 // NewDriveItemPermissionsApi creates a new DriveItemPermissionsApi
-func NewDriveItemPermissionsApi(driveItemPermissionService DriveItemPermissionsProvider, logger log.Logger, c *config.Config) (DriveItemPermissionsApi, error) {
+func NewDriveItemPermissionsApi(driveItemPermissionService DriveItemPermissionsProvider, logger log.Logger, c *config.Config, valueService settingssvc.ValueService) (DriveItemPermissionsApi, error) {
 	return DriveItemPermissionsApi{
 		logger:                      log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemApi").Logger()},
 		driveItemPermissionsService: driveItemPermissionService,
 		config:                      c,
+		valueService:                valueService,
 	}, nil
 }
 
@@ -718,7 +721,8 @@ func (api DriveItemPermissionsApi) ListPermissions(w http.ResponseWriter, r *htt
 		return
 	}
 
-	loc := r.Header.Get(l10n.HeaderAcceptLanguage)
+	userID := revactx.ContextMustGetUser(ctx).GetId().GetOpaqueId()
+	loc := l10n.MustGetUserLocale(ctx, userID, r.Header.Get(l10n.HeaderAcceptLanguage), api.valueService)
 	w.Header().Add("Content-Language", loc)
 	if loc != "" && loc != "en" {
 		err := l10n_pkg.TranslateEntity(loc, "en", permissions,
@@ -753,7 +757,8 @@ func (api DriveItemPermissionsApi) ListSpaceRootPermissions(w http.ResponseWrite
 		return
 	}
 
-	loc := r.Header.Get(l10n.HeaderAcceptLanguage)
+	userID := revactx.ContextMustGetUser(ctx).GetId().GetOpaqueId()
+	loc := l10n.MustGetUserLocale(ctx, userID, r.Header.Get(l10n.HeaderAcceptLanguage), api.valueService)
 	w.Header().Add("Content-Language", loc)
 	if loc != "" && loc != "en" {
 		err := l10n_pkg.TranslateEntity(loc, "en", permissions,
diff --git a/services/graph/pkg/service/v0/rolemanagement.go b/services/graph/pkg/service/v0/rolemanagement.go
index 6f769136267..90d0c903a8b 100644
--- a/services/graph/pkg/service/v0/rolemanagement.go
+++ b/services/graph/pkg/service/v0/rolemanagement.go
@@ -7,14 +7,32 @@ import (
 	"github.com/go-chi/chi/v5"
 	"github.com/go-chi/render"
 
+	revactx "github.com/cs3org/reva/v2/pkg/ctx"
+	"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
+	l10n_pkg "github.com/owncloud/ocis/v2/services/graph/pkg/l10n"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
 )
 
 // GetRoleDefinitions a list of permission roles than can be used when sharing with users or groups
 func (g Graph) GetRoleDefinitions(w http.ResponseWriter, r *http.Request) {
+	logger := g.logger.SubloggerWithRequestID(r.Context())
+	roles := unifiedrole.GetRoles(unifiedrole.RoleFilterIDs(g.config.UnifiedRoles.AvailableRoles...))
+
+	userID := revactx.ContextMustGetUser(r.Context()).GetId().GetOpaqueId()
+	locale := l10n.MustGetUserLocale(r.Context(), userID, r.Header.Get(l10n.HeaderAcceptLanguage), g.valueService)
+	if locale != "" && locale != "en" {
+		err := l10n_pkg.TranslateEntity(locale, "en", roles,
+			l10n.TranslateField("DisplayName"),
+			l10n.TranslateField("Description"),
+		)
+		if err != nil {
+			logger.Error().Err(err).Msg("could not translate role definitions")
+		}
+	}
+
 	render.Status(r, http.StatusOK)
-	render.JSON(w, r, unifiedrole.GetRoles(unifiedrole.RoleFilterIDs(g.config.UnifiedRoles.AvailableRoles...)))
+	render.JSON(w, r, roles)
 }
 
 // GetRoleDefinition a permission role than can be used when sharing with users or groups
@@ -32,6 +50,19 @@ func (g Graph) GetRoleDefinition(w http.ResponseWriter, r *http.Request) {
 		errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, err.Error())
 		return
 	}
+
+	userID := revactx.ContextMustGetUser(r.Context()).GetId().GetOpaqueId()
+	locale := l10n.MustGetUserLocale(r.Context(), userID, r.Header.Get(l10n.HeaderAcceptLanguage), g.valueService)
+	if locale != "" && locale != "en" {
+		err := l10n_pkg.TranslateEntity(locale, "en", role,
+			l10n.TranslateField("DisplayName"),
+			l10n.TranslateField("Description"),
+		)
+		if err != nil {
+			logger.Error().Str("roleID", roleID).Err(err).Msg("could not translate role definition")
+		}
+	}
+
 	render.Status(r, http.StatusOK)
 	render.JSON(w, r, role)
 }
diff --git a/services/graph/pkg/service/v0/service.go b/services/graph/pkg/service/v0/service.go
index 03cc754efd9..4956a2fff63 100644
--- a/services/graph/pkg/service/v0/service.go
+++ b/services/graph/pkg/service/v0/service.go
@@ -218,7 +218,7 @@ func NewService(opts ...Option) (Graph, error) { //nolint:maintidx
 		return svc, err
 	}
 
-	driveItemPermissionsApi, err := NewDriveItemPermissionsApi(driveItemPermissionsService, options.Logger, options.Config)
+	driveItemPermissionsApi, err := NewDriveItemPermissionsApi(driveItemPermissionsService, options.Logger, options.Config, options.ValueService)
 	if err != nil {
 		return svc, err
 	}


Test patch:
diff --git a/services/graph/pkg/service/v0/api_driveitem_permissions_test.go b/services/graph/pkg/service/v0/api_driveitem_permissions_test.go
index 2761a23a5b0..e7b3f97a5a3 100644
--- a/services/graph/pkg/service/v0/api_driveitem_permissions_test.go
+++ b/services/graph/pkg/service/v0/api_driveitem_permissions_test.go
@@ -24,6 +24,7 @@ import (
 	"github.com/owncloud/ocis/v2/services/graph/pkg/config"
 	"github.com/stretchr/testify/mock"
 	"github.com/tidwall/gjson"
+	"go-micro.dev/v4/client"
 	"google.golang.org/grpc"
 
 	roleconversions "github.com/cs3org/reva/v2/pkg/conversions"
@@ -34,6 +35,7 @@ import (
 	cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
 
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
+	settings "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
 	"github.com/owncloud/ocis/v2/services/graph/mocks"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
@@ -1098,17 +1100,30 @@ var _ = Describe("DriveItemPermissionsService", func() {
 
 var _ = Describe("DriveItemPermissionsApi", func() {
 	var (
-		mockProvider *mocks.DriveItemPermissionsProvider
-		httpAPI      svc.DriveItemPermissionsApi
-		rCTX         *chi.Context
-		invite       libregraph.DriveItemInvite
+		mockProvider     *mocks.DriveItemPermissionsProvider
+		mockValueService *settings.MockValueService
+		httpAPI          svc.DriveItemPermissionsApi
+		rCTX             *chi.Context
+		invite           libregraph.DriveItemInvite
+		currentUser      = &userpb.User{
+			Id: &userpb.UserId{
+				OpaqueId: "testuser",
+			},
+			DisplayName: "Test User",
+		}
 	)
 
 	BeforeEach(func() {
 		logger := log.NewLogger()
 
 		mockProvider = mocks.NewDriveItemPermissionsProvider(GinkgoT())
-		api, err := svc.NewDriveItemPermissionsApi(mockProvider, logger, defaults.FullDefaultConfig())
+		mockValueService = &settings.MockValueService{
+			GetValueByUniqueIdentifiersFunc: func(ctx context.Context, req *settings.GetValueByUniqueIdentifiersRequest, opts ...client.CallOption) (*settings.GetValueResponse, error) {
+				return &settings.GetValueResponse{}, nil
+			},
+		}
+
+		api, err := svc.NewDriveItemPermissionsApi(mockProvider, logger, defaults.FullDefaultConfig(), mockValueService)
 		Expect(err).ToNot(HaveOccurred())
 
 		httpAPI = api
@@ -1271,9 +1286,12 @@ var _ = Describe("DriveItemPermissionsApi", func() {
 					return libregraph.CollectionOfPermissionsWithAllowedValues{}, nil
 				}).Once()
 
+			ctx := revactx.ContextSetUser(context.Background(), currentUser)
+			ctx = context.WithValue(ctx, chi.RouteCtxKey, rCTX)
+
 			request := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(inviteJson)).
 				WithContext(
-					context.WithValue(context.Background(), chi.RouteCtxKey, rCTX),
+					ctx,
 				)
 			httpAPI.ListPermissions(responseRecorder, request)