diff --git a/services/graph/pkg/config/config.go b/services/graph/pkg/config/config.go index 950760825..2198ddcac 100644 --- a/services/graph/pkg/config/config.go +++ b/services/graph/pkg/config/config.go @@ -46,6 +46,7 @@ type Spaces struct { UsersCacheTTL int `yaml:"users_cache_ttl" env:"GRAPH_SPACES_USERS_CACHE_TTL" desc:"Max TTL in seconds for the spaces users cache." introductionVersion:"pre5.0"` GroupsCacheTTL int `yaml:"groups_cache_ttl" env:"GRAPH_SPACES_GROUPS_CACHE_TTL" desc:"Max TTL in seconds for the spaces groups cache." introductionVersion:"pre5.0"` StorageUsersAddress string `yaml:"storage_users_address" env:"GRAPH_SPACES_STORAGE_USERS_ADDRESS" desc:"The address of the storage-users service." introductionVersion:"5.0"` + DefaultLanguage string `yaml:"default_language" env:"OCIS_DEFAULT_LANGUAGE" desc:"The default language used by services and the WebUI. If not defined, English will be used as default. See the documentation for more details." introductionVersion:"5.0"` } type LDAP struct { diff --git a/services/graph/pkg/service/v0/drives.go b/services/graph/pkg/service/v0/drives.go index 6dbf31864..5719e0844 100644 --- a/services/graph/pkg/service/v0/drives.go +++ b/services/graph/pkg/service/v0/drives.go @@ -29,6 +29,7 @@ import ( "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" "github.com/owncloud/ocis/v2/ocis-pkg/conversions" + "github.com/owncloud/ocis/v2/ocis-pkg/l10n" "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc" v0 "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0" settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" @@ -326,7 +327,10 @@ func (g Graph) canCreateSpace(ctx context.Context, ownPersonalHome bool) bool { func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { logger := g.logger.SubloggerWithRequestID(r.Context()) logger.Info().Msg("calling create drive") - us, ok := revactx.ContextGetUser(r.Context()) + + ctx := r.Context() + + us, ok := revactx.ContextGetUser(ctx) if !ok { logger.Debug().Msg("could not create drive: invalid user") errorcode.NotAllowed.Render(w, r, http.StatusUnauthorized, "invalid user") @@ -334,7 +338,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { } // TODO determine if the user tries to create his own personal space and pass that as a boolean - canCreateSpace := g.canCreateSpace(r.Context(), false) + canCreateSpace := g.canCreateSpace(ctx, false) if !canCreateSpace { logger.Debug().Bool("cancreatespace", canCreateSpace).Msg("could not create drive: insufficient permissions") // if the permission is not existing for the user in context we can assume we don't have it. Return 401. @@ -393,7 +397,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { csr.Owner = us } - resp, err := gatewayClient.CreateStorageSpace(r.Context(), &csr) + resp, err := gatewayClient.CreateStorageSpace(ctx, &csr) if err != nil { logger.Error().Err(err).Msg("could not create drive: transport error") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) @@ -424,15 +428,16 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { } space := resp.GetStorageSpace() - if t := r.URL.Query().Get("template"); t != "" && driveType == _spaceTypeProject { - if err := g.applySpaceTemplate(r.Context(), gatewayClient, resp.GetStorageSpace().GetRoot(), t); err != nil { + if t := r.URL.Query().Get(TemplateParameter); t != "" && driveType == _spaceTypeProject { + loc := l10n.MustGetUserLocale(ctx, us.GetId().GetOpaqueId(), r.Header.Get(HeaderAcceptLanguage), g.valueService) + if err := g.applySpaceTemplate(ctx, gatewayClient, space.GetRoot(), t, loc); err != nil { logger.Error().Err(err).Msg("could not apply template to space") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return } // refetch the drive to get quota information - should we calculate this ourselves to avoid the extra call? - space, err = utils.GetSpace(r.Context(), resp.GetStorageSpace().GetId().GetOpaqueId(), gatewayClient) + space, err = utils.GetSpace(ctx, space.GetId().GetOpaqueId(), gatewayClient) if err != nil { logger.Error().Err(err).Msg("could not refetch space") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) @@ -440,7 +445,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { } } - spaces, err := g.formatDrives(r.Context(), webDavBaseURL, []*storageprovider.StorageSpace{space}, APIVersion_1) + spaces, err := g.formatDrives(ctx, webDavBaseURL, []*storageprovider.StorageSpace{space}, APIVersion_1) if err != nil { logger.Debug().Err(err).Msg("could not get drive: error parsing grpc response") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) diff --git a/services/graph/pkg/service/v0/spacetemplates.go b/services/graph/pkg/service/v0/spacetemplates.go index c66453295..b9d41438a 100644 --- a/services/graph/pkg/service/v0/spacetemplates.go +++ b/services/graph/pkg/service/v0/spacetemplates.go @@ -24,30 +24,50 @@ var ( //go:embed l10n/locale _localeFS embed.FS + // subfolder where the translation files are stored + _localeSubPath = "l10n/locale" + + // name of the secret space folder + _spaceFolderName = ".space" + + // path to the image file _imagepath = "spacetemplate/image.png" + // text for the readme.md file _readmeText = l10n.Template("Here you can add a description for this Space.") + + // name of the readme.md file + _readmeName = "readme.md" + + // domain of the graph service (transifex) + _domain = "graph" + + // HeaderAcceptLanguage is the header key for the accept-language header + HeaderAcceptLanguage = "Accept-Language" + + // TemplateParameter is the key for the template parameter in the request + TemplateParameter = "template" ) -func (g Graph) applySpaceTemplate(ctx context.Context, gwc gateway.GatewayAPIClient, root *storageprovider.ResourceId, template string) error { +func (g Graph) applySpaceTemplate(ctx context.Context, gwc gateway.GatewayAPIClient, root *storageprovider.ResourceId, template string, locale string) error { switch template { default: fallthrough case "none": return nil case "default": - return g.applyDefaultTemplate(ctx, gwc, root) + return g.applyDefaultTemplate(ctx, gwc, root, locale) } } -func (g Graph) applyDefaultTemplate(ctx context.Context, gwc gateway.GatewayAPIClient, root *storageprovider.ResourceId) error { +func (g Graph) applyDefaultTemplate(ctx context.Context, gwc gateway.GatewayAPIClient, root *storageprovider.ResourceId, locale string) error { mdc := metadata.NewCS3(g.config.Reva.Address, g.config.Spaces.StorageUsersAddress) mdc.SpaceRoot = root var opaque *v1beta1.Opaque // create .space folder - if err := mdc.MakeDirIfNotExist(ctx, ".space"); err != nil { + if err := mdc.MakeDirIfNotExist(ctx, _spaceFolderName); err != nil { return err } @@ -59,7 +79,7 @@ func (g Graph) applyDefaultTemplate(ctx context.Context, gwc gateway.GatewayAPIC opaque = utils.AppendPlainToOpaque(opaque, SpaceImageSpecialFolderName, iid) // upload readme.md - rid, err := readmeUpload(ctx, mdc) + rid, err := readmeUpload(ctx, mdc, locale, g.config.Spaces.DefaultLanguage) if err != nil { return err } @@ -91,7 +111,7 @@ func imageUpload(ctx context.Context, mdc *metadata.CS3) (string, error) { return "", err } res, err := mdc.Upload(ctx, metadata.UploadRequest{ - Path: filepath.Join(".space", filepath.Base(_imagepath)), + Path: filepath.Join(_spaceFolderName, filepath.Base(_imagepath)), Content: b, }) if err != nil { @@ -100,11 +120,11 @@ func imageUpload(ctx context.Context, mdc *metadata.CS3) (string, error) { return res.FileID, nil } -func readmeUpload(ctx context.Context, mdc *metadata.CS3) (string, error) { - t := l10n.NewTranslatorFromCommonConfig("en", "graph", "", _localeFS, "l10n/locale") +func readmeUpload(ctx context.Context, mdc *metadata.CS3, locale string, defaultLocale string) (string, error) { + t := l10n.NewTranslatorFromCommonConfig(defaultLocale, _domain, "", _localeFS, _localeSubPath) res, err := mdc.Upload(ctx, metadata.UploadRequest{ - Path: filepath.Join(".space", "readme.md"), - Content: []byte(t.Translate(_readmeText, "en_GB")), + Path: filepath.Join(_spaceFolderName, _readmeName), + Content: []byte(t.Translate(_readmeText, locale)), }) if err != nil { return "", err diff --git a/services/notifications/pkg/service/service.go b/services/notifications/pkg/service/service.go index d24a13356..3a48f788c 100644 --- a/services/notifications/pkg/service/service.go +++ b/services/notifications/pkg/service/service.go @@ -29,8 +29,6 @@ import ( "google.golang.org/protobuf/types/known/fieldmaskpb" ) -var _defaultLocale = "en" - // Service should be named `Runner` type Service interface { Run() error