Skip to content

Commit

Permalink
Merge pull request #5559 from owncloud/branding-api
Browse files Browse the repository at this point in the history
Branding api
  • Loading branch information
micbar authored Feb 13, 2023
2 parents 8fb9914 + 2323410 commit 2b04573
Show file tree
Hide file tree
Showing 18 changed files with 401 additions and 101 deletions.
4 changes: 2 additions & 2 deletions .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ def wopiValidatorTests(ctx, storage, accounts_hash_difficulty = 4):
},
{
"name": "wopiserver",
"image": "cs3org/wopiserver:v9.4.0",
"image": "cs3org/wopiserver:v9.4.1",
"detach": True,
"commands": [
"cp %s/tests/config/drone/wopiserver.conf /etc/wopi/wopiserver.conf" % (dirs["base"]),
Expand All @@ -810,7 +810,7 @@ def wopiValidatorTests(ctx, storage, accounts_hash_difficulty = 4):
"name": "wait-for-wopi-server",
"image": OC_CI_ALPINE,
"commands": [
"curl -k --fail --retry-connrefused --retry 7 --retry-all-errors 'http://wopiserver:8880/wopi'",
"curl -k --fail --retry-connrefused --retry 9 --retry-all-errors 'http://wopiserver:8880/wopi'",
],
},
] +
Expand Down
6 changes: 6 additions & 0 deletions changelog/unreleased/branding-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Add endpoints to upload a custom logo

Added endpoints to upload and reset custom logos. The files are stored under the `WEB_ASSET_PATH`
which defaults to `$OCIS_BASE_DATA_PATH/web/assets`.

https://github.com/owncloud/ocis/pull/5559
46 changes: 22 additions & 24 deletions ocis-pkg/assetsfs/assetsfs.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package assetsfs

import (
"embed"
"fmt"
"io/fs"
"net/http"
"os"
"path"
"path/filepath"

"github.com/owncloud/ocis/v2/ocis-pkg/log"
)
Expand All @@ -21,22 +20,35 @@ type FileSystem struct {
// Open checks if assetPath is set and tries to load from there. Falls back to fs if that is not possible
func (f *FileSystem) Open(original string) (http.File, error) {
if f.assetPath != "" {
file, err := read(f.assetPath, original)
file, err := os.Open(filepath.Join(f.assetPath, original))
if err == nil {
return file, nil
}
f.log.Warn().
Str("path", f.assetPath).
Str("filename", original).
Str("error", err.Error()).
Msg("error reading from assetPath")
}

return f.fs.Open(original)
}

func (f *FileSystem) OpenEmbedded(name string) (http.File, error) {
return f.fs.Open(name)
}

// Create creates a new file in the assetPath
func (f *FileSystem) Create(name string) (*os.File, error) {
fullPath := f.jailPath(name)
if err := os.MkdirAll(filepath.Dir(fullPath), 0770); err != nil {
return nil, err
}
return os.Create(fullPath)
}

// jailPath returns the fullPath `<assetPath>/<name>`. It makes sure that the path is
// always under `<assetPath>` to prevent directory traversal.
func (f *FileSystem) jailPath(name string) string {
return filepath.Join(f.assetPath, filepath.Join("/", name))
}

// New initializes a new FileSystem. Quits on error
func New(embedFS embed.FS, assetPath string, logger log.Logger) *FileSystem {
func New(embedFS fs.FS, assetPath string, logger log.Logger) *FileSystem {
f, err := fs.Sub(embedFS, "assets")
if err != nil {
fmt.Println("Cannot load subtree fs:", err.Error())
Expand All @@ -49,17 +61,3 @@ func New(embedFS embed.FS, assetPath string, logger log.Logger) *FileSystem {
log: logger,
}
}

// tries to read file from disk or errors
func read(assetPath string, fileName string) (http.File, error) {
if stat, err := os.Stat(assetPath); err != nil || !stat.IsDir() {
return nil, fmt.Errorf("can't load asset path: %s", err)
}

p := path.Join(assetPath, fileName)
if _, err := os.Stat(p); err != nil {
return nil, err
}

return os.Open(p)
}
4 changes: 4 additions & 0 deletions services/proxy/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ func DefaultPolicies() []config.Policy {
Service: "com.owncloud.web.idp",
Unprotected: true,
},
{
Endpoint: "/branding/logo",
Service: "com.owncloud.web.web",
},
{
Endpoint: "/konnect/",
Service: "com.owncloud.web.idp",
Expand Down
23 changes: 23 additions & 0 deletions services/settings/pkg/service/v0/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ const (
SelfManagementPermissionID string = "e03070e9-4362-4cc6-a872-1c7cb2eb2b8e"
// SelfManagementPermissionName is the hardcoded setting name for the self management permission
SelfManagementPermissionName string = "self-management"

// ChangeLogoPermissionID is the hardcoded setting UUID for the change-logo permission
ChangeLogoPermissionID string = "ed83fc10-1f54-4a9e-b5a7-fb517f5f3e01"
// ChangeLogoPermissionName is the hardcoded setting name for the change-logo permission
ChangeLogoPermissionName string = "change-logo"
)

// generateBundlesDefaultRoles bootstraps the default roles.
Expand Down Expand Up @@ -438,6 +443,24 @@ func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest {
},
},
},
{
BundleId: BundleUUIDRoleAdmin,
Setting: &settingsmsg.Setting{
Id: ChangeLogoPermissionID,
Name: ChangeLogoPermissionName,
DisplayName: "Change logo",
Description: "This permission permits to change the system logo.",
Resource: &settingsmsg.Resource{
Type: settingsmsg.Resource_TYPE_SYSTEM,
},
Value: &settingsmsg.Setting_PermissionValue{
PermissionValue: &settingsmsg.Permission{
Operation: settingsmsg.Permission_OPERATION_READWRITE,
Constraint: settingsmsg.Permission_CONSTRAINT_ALL,
},
},
},
},
{
BundleId: BundleUUIDRoleSpaceAdmin,
Setting: &settingsmsg.Setting{
Expand Down
20 changes: 20 additions & 0 deletions services/settings/pkg/store/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ const (
SelfManagementPermissionID string = "e03070e9-4362-4cc6-a872-1c7cb2eb2b8e"
// SelfManagementPermissionName is the hardcoded setting name for the self management permission
SelfManagementPermissionName string = "self-management"

// ChangeLogoPermissionID is the hardcoded setting UUID for the change-logo permission
ChangeLogoPermissionID string = "ed83fc10-1f54-4a9e-b5a7-fb517f5f3e01"
// ChangeLogoPermissionName is the hardcoded setting name for the change-logo permission
ChangeLogoPermissionName string = "change-logo"
)

// GenerateBundlesDefaultRoles bootstraps the default roles.
Expand Down Expand Up @@ -260,6 +265,21 @@ func generateBundleAdminRole() *settingsmsg.Bundle {
},
},
},
{
Id: ChangeLogoPermissionID,
Name: ChangeLogoPermissionName,
DisplayName: "Change logo",
Description: "This permission permits to change the system logo.",
Resource: &settingsmsg.Resource{
Type: settingsmsg.Resource_TYPE_SYSTEM,
},
Value: &settingsmsg.Setting_PermissionValue{
PermissionValue: &settingsmsg.Permission{
Operation: settingsmsg.Permission_OPERATION_READWRITE,
Constraint: settingsmsg.Permission_CONSTRAINT_ALL,
},
},
},
},
}
}
Expand Down
50 changes: 0 additions & 50 deletions services/web/pkg/assets/option.go

This file was deleted.

3 changes: 2 additions & 1 deletion services/web/pkg/assets/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package assets

import (
"bytes"
"golang.org/x/net/html"
"io"
"mime"
"net/http"
"path"
"path/filepath"

"golang.org/x/net/html"
)

type fileServer struct {
Expand Down
25 changes: 17 additions & 8 deletions services/web/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ type Config struct {
File string `yaml:"file" env:"WEB_UI_CONFIG" desc:"Read the ownCloud Web configuration from this file."` // TODO: rename this to a more self explaining string
Web Web `yaml:"web"`

Context context.Context `yaml:"-"`
TokenManager *TokenManager `yaml:"token_manager"`

GatewayAddress string `yaml:"gateway_addr" env:"WEB_GATEWAY_GRPC_ADDR" desc:"The bind address of the GRPC service."`
Context context.Context `yaml:"-"`
}

// Asset defines the available asset configuration.
Expand Down Expand Up @@ -60,13 +63,14 @@ type Application struct {
}

// ExternalApp defines an external web app.
// {
// "name": "hello",
// "path": "http://localhost:9105/hello.js",
// "config": {
// "url": "http://localhost:9105"
// }
// }
//
// {
// "name": "hello",
// "path": "http://localhost:9105/hello.js",
// "config": {
// "url": "http://localhost:9105"
// }
// }
type ExternalApp struct {
ID string `json:"id,omitempty" yaml:"id"`
Path string `json:"path,omitempty" yaml:"path"`
Expand All @@ -86,3 +90,8 @@ type Web struct {
ThemePath string `yaml:"theme_path" env:"WEB_UI_THEME_PATH" desc:"URL path to load themes from. The theme server will be prepended."` // used to build Theme in WebConfig
Config WebConfig `yaml:"config"`
}

// TokenManager is the config for using the reva token manager
type TokenManager struct {
JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;WEB_JWT_SECRET" desc:"The secret to mint and validate jwt tokens."`
}
12 changes: 11 additions & 1 deletion services/web/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package defaults

import (
"path/filepath"
"strings"

"github.com/owncloud/ocis/v2/ocis-pkg/config/defaults"
"github.com/owncloud/ocis/v2/services/web/pkg/config"
)

Expand Down Expand Up @@ -31,8 +33,9 @@ func DefaultConfig() *config.Config {
Name: "web",
},
Asset: config.Asset{
Path: "",
Path: filepath.Join(defaults.BaseDataPath(), "web/assets"),
},
GatewayAddress: "127.0.0.1:9142",
Web: config.Web{
Path: "",
ThemeServer: "https://localhost:9200",
Expand Down Expand Up @@ -93,6 +96,13 @@ func EnsureDefaults(cfg *config.Config) {
cfg.Tracing = &config.Tracing{}
}

if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil {
cfg.TokenManager = &config.TokenManager{
JWTSecret: cfg.Commons.TokenManager.JWTSecret,
}
} else if cfg.TokenManager == nil {
cfg.TokenManager = &config.TokenManager{}
}
if cfg.Commons != nil {
cfg.HTTP.TLS = cfg.Commons.HTTPServiceTLS
}
Expand Down
4 changes: 4 additions & 0 deletions services/web/pkg/config/parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"

ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
"github.com/owncloud/ocis/v2/services/web/pkg/config"
"github.com/owncloud/ocis/v2/services/web/pkg/config/defaults"

Expand Down Expand Up @@ -33,5 +34,8 @@ func ParseConfig(cfg *config.Config) error {
}

func Validate(cfg *config.Config) error {
if cfg.TokenManager.JWTSecret == "" {
return shared.MissingJWTTokenError(cfg.Service.Name)
}
return nil
}
7 changes: 7 additions & 0 deletions services/web/pkg/server/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package http
import (
"fmt"

"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
chimiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/service/http"
Expand Down Expand Up @@ -33,9 +34,15 @@ func Server(opts ...Option) (http.Service, error) {
return http.Service{}, fmt.Errorf("could not initialize http service: %w", err)
}

client, err := pool.GetGatewayServiceClient(options.Config.GatewayAddress)
if err != nil {
return http.Service{}, err
}

handle := svc.NewService(
svc.Logger(options.Logger),
svc.Config(options.Config),
svc.GatewayClient(client),
svc.Middleware(
chimiddleware.RealIP,
chimiddleware.RequestID,
Expand Down
Loading

0 comments on commit 2b04573

Please sign in to comment.