Merge branch 'master' into StoreSettingsViaMetadata
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
# The test runner source for API tests
|
||||
CORE_COMMITID=a0a4064c77a3576763885f83d57ca4c558348b8c
|
||||
CORE_COMMITID=87e97eb1a9b4795a72c5dcc94515b5b86b947274
|
||||
CORE_BRANCH=master
|
||||
|
||||
# The test runner source for UI tests
|
||||
|
||||
@@ -6,15 +6,29 @@ The following sections list the changes for unreleased.
|
||||
|
||||
## Summary
|
||||
|
||||
* Bugfix - Capabilities for password protected public links: [#3229](https://github.com/owncloud/ocis/pull/3229)
|
||||
* Bugfix - Make events settings configurable: [#3214](https://github.com/owncloud/ocis/pull/3214)
|
||||
* Bugfix - Align storage metadata GPRC bind port with other variable names: [#3169](https://github.com/owncloud/ocis/pull/3169)
|
||||
* Change - Unify file IDs: [#3185](https://github.com/owncloud/ocis/pull/3185)
|
||||
* Enhancement - Add sorting to list Spaces: [#3200](https://github.com/owncloud/ocis/issues/3200)
|
||||
* Enhancement - Change NATS port: [#3210](https://github.com/owncloud/ocis/pull/3210)
|
||||
* Enhancement - Re-Enabling web cache control: [#3109](https://github.com/owncloud/ocis/pull/3109)
|
||||
* Enhancement - Add SPA conform fileserver for web: [#3109](https://github.com/owncloud/ocis/pull/3109)
|
||||
* Enhancement - Implement notifications service: [#3217](https://github.com/owncloud/ocis/pull/3217)
|
||||
* Enhancement - Thumbnails in spaces: [#3219](https://github.com/owncloud/ocis/pull/3219)
|
||||
* Enhancement - Update reva to v1.16.1-0.20220224114254-d4ffaf323e70: [#3231](https://github.com/owncloud/ocis/pull/3231)
|
||||
* Enhancement - Update ownCloud Web to v5.1.0: [#3202](https://github.com/owncloud/ocis/pull/3202)
|
||||
|
||||
## Details
|
||||
|
||||
* Bugfix - Capabilities for password protected public links: [#3229](https://github.com/owncloud/ocis/pull/3229)
|
||||
|
||||
Allow password protected public links to request capabilities.
|
||||
|
||||
https://github.com/owncloud/web/issues/5863
|
||||
https://github.com/owncloud/ocis/pull/3229
|
||||
https://github.com/owncloud/web/pull/6471
|
||||
|
||||
* Bugfix - Make events settings configurable: [#3214](https://github.com/owncloud/ocis/pull/3214)
|
||||
|
||||
We've fixed the hardcoded events settings to be configurable.
|
||||
@@ -56,6 +70,40 @@ The following sections list the changes for unreleased.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3210
|
||||
|
||||
* Enhancement - Re-Enabling web cache control: [#3109](https://github.com/owncloud/ocis/pull/3109)
|
||||
|
||||
We've re-enable browser caching headers (`Expires` and `Last-Modified`) for the web
|
||||
service, this was disabled due to a problem in the fileserver used before. Since we're now using
|
||||
our own fileserver implementation this works again and is enabled by default.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3109
|
||||
|
||||
* Enhancement - Add SPA conform fileserver for web: [#3109](https://github.com/owncloud/ocis/pull/3109)
|
||||
|
||||
We've added an SPA conform fileserver to the web service. It enables web to use vue's history
|
||||
mode and behaves like nginx try_files.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3109
|
||||
|
||||
* Enhancement - Implement notifications service: [#3217](https://github.com/owncloud/ocis/pull/3217)
|
||||
|
||||
Implemented the minimal version of the notifications service to be able to notify a user when
|
||||
they received a share.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3217
|
||||
|
||||
* Enhancement - Thumbnails in spaces: [#3219](https://github.com/owncloud/ocis/pull/3219)
|
||||
|
||||
Added support for thumbnails in spaces.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3219
|
||||
|
||||
* Enhancement - Update reva to v1.16.1-0.20220224114254-d4ffaf323e70: [#3231](https://github.com/owncloud/ocis/pull/3231)
|
||||
|
||||
We updated reva to the latest edge branch. Changelog will follow.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3231
|
||||
|
||||
* Enhancement - Update ownCloud Web to v5.1.0: [#3202](https://github.com/owncloud/ocis/pull/3202)
|
||||
|
||||
Tags: web
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Enhancement: Re-Enabling web cache control
|
||||
|
||||
We've re-enable browser caching headers (`Expires` and `Last-Modified`) for the web service, this was disabled due to a problem in the fileserver used before.
|
||||
Since we're now using our own fileserver implementation this works again and is enabled by default.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3109
|
||||
@@ -0,0 +1,6 @@
|
||||
Enhancement: Add SPA conform fileserver for web
|
||||
|
||||
We've added an SPA conform fileserver to the web service.
|
||||
It enables web to use vue's history mode and behaves like nginx try_files.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3109
|
||||
@@ -0,0 +1,7 @@
|
||||
Bugfix: Capabilities for password protected public links
|
||||
|
||||
Allow password protected public links to request capabilities.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3229
|
||||
https://github.com/owncloud/web/pull/6471
|
||||
https://github.com/owncloud/web/issues/5863
|
||||
@@ -0,0 +1,5 @@
|
||||
Enhancement: Implement notifications service
|
||||
|
||||
Implemented the minimal version of the notifications service to be able to notify a user when they received a share.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3217
|
||||
@@ -0,0 +1,5 @@
|
||||
Enhancement: Thumbnails in spaces
|
||||
|
||||
Added support for thumbnails in spaces.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3219
|
||||
@@ -0,0 +1,5 @@
|
||||
Enhancement: Update reva to v1.16.1-0.20220224114254-d4ffaf323e70
|
||||
|
||||
We updated reva to the latest edge branch. Changelog will follow.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/3231
|
||||
@@ -7,9 +7,9 @@ geekdocEditPath: edit/master/docs/ocis/adr
|
||||
geekdocFilePath: 0003-external-user-management.md
|
||||
---
|
||||
|
||||
* Status: accepted
|
||||
* Status: superseded by [17. Allow read only external User Management]({{< ref "0017-allow-read-only-external-user-management.md" >}})
|
||||
* Deciders: @butonic, @micbar, @dragotin, @hodyroff, @pmaier1
|
||||
* Date: 2020-12-09
|
||||
* Date: 2022-02-08
|
||||
|
||||
Technical Story: [Skip account-service by talking to CS3 user-api](https://github.com/owncloud/ocis/pull/1020)
|
||||
|
||||
@@ -112,3 +112,4 @@ We should use an existing LDAP server and make GLAuth a drop in replacement for
|
||||
|
||||
## Links
|
||||
* supersedes [ADR-0001]({{< ref "0001-introduce-accounts-service.md" >}})
|
||||
* superseded by [17. Allow read only external User Management]({{< ref "0017-allow-read-only-external-user-management.md" >}})
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "17. Allow read only external User Management"
|
||||
weight: 17
|
||||
date: 2022-02-08T10:53:00+01:00
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/ocis/adr
|
||||
geekdocFilePath: 0017-allow-read-only-external-user-management.md
|
||||
---
|
||||
|
||||
* Status: proposed
|
||||
* Deciders: @butonic, @micbar, @rhafer
|
||||
* Date: 2022-02-08
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
oCIS needs to be integrated with various external Authentication and Identity Management Systems.
|
||||
Usually oCIS will have no administrative access to such a system and we will not be allowed to
|
||||
reconfigure it to suit our needs (e.g. we will not be able to enhance the schema of an already existing
|
||||
LDAP Directory). In most of the cases our access will be read-only.
|
||||
|
||||
Sidenote: There is a difference between users, identities and accounts: A user may have multiple
|
||||
identities which he can authenticate with, e.g. his facebook, twitter, microsoft or google
|
||||
identity. Multiple identities can be linked to an account in ocis, allowing to fall back to another
|
||||
identity provider should one of them shut down. This also allows migrating from one identity
|
||||
provider to another.
|
||||
|
||||
There are different cases where oCIS requires access to users:
|
||||
|
||||
1. While we settled on using OpenID Connect (OIDC) as the authentication protocol for oCIS, we
|
||||
we need to build a user object during authentication with at least an account UUID (to identify
|
||||
the account) and the email or a name (for display purposes).
|
||||
2. When searching for share recipients we need to be able to query existing users in the external
|
||||
identity management system
|
||||
3. When listing files we need to be able to look up a users display properties (username, email,
|
||||
avatar...) based on the account UUID
|
||||
|
||||
oCIS internally relies on a stable and persistent identifier (e.g. a UUID) for accounts in order to
|
||||
implement permissions and sharing. Unfortunately, some deployments are unable to deliver this kind
|
||||
of stable identifier for users:
|
||||
|
||||
- In OIDC itself the only stable identifier that is guaranteed to be provided by the IDP is
|
||||
combination of the sub and iss claims. IDPs can optionally return other claims, but we cannot
|
||||
rely on a specific claim being present.
|
||||
- When no other services (LDAP, SCIM, ...) are available that could be used look up a user UUID
|
||||
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
* oCIS should be a single binary that can run out of the box without external dependencies like an
|
||||
LDAP server.
|
||||
* Time: we want to build a release candidate asap.
|
||||
* oCIS should be easy to integrate with standard external identity mangement systems
|
||||
|
||||
## Considered Options
|
||||
|
||||
There are two case to consider:
|
||||
* External identity management system provides an OIDC IdP and an interface to query users
|
||||
* External identity management system provides just an OIDC IdP with no possibility to query users
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
It's not really possible single out any of the options for this ADR. In the end we will likely need
|
||||
to support both scenarios.
|
||||
|
||||
### Positive Consequences: <!-- optional -->
|
||||
|
||||
* Very flexible integration with a wide range of external systems
|
||||
|
||||
### Negative consequences: <!-- optional -->
|
||||
|
||||
* configuration complexity, high support efforts
|
||||
* Increasingly complex code in oCIS
|
||||
|
||||
## Pros and Cons of the Options <!-- optional -->
|
||||
|
||||
### External identity management system is read only and provides an interface to query users (e.g. Coporate Active Directy)
|
||||
|
||||
IdP sends sub & iss and mail or username claims, Identity Management System provides APIs (e.g.
|
||||
LDAP, SCIM, REST ...) to lookup additional user information. All oCIS services use the CS3 API to
|
||||
look up the account for the given email or username, where CS3 then uses a backend that relies on
|
||||
the APIs provided by the IdM.
|
||||
|
||||
* Good, because we can rely on the external identity management
|
||||
* Good, because ocis services only need to know about the CS3 user provider API, which acts as an
|
||||
abstraction layer for different identitiy management systems
|
||||
* Good, because there is only a single source of truth (the external IdM) and we don't need to
|
||||
implement a synchronization mechanism to maintain an internal user database (we will likely need
|
||||
some form of caching though, see below)
|
||||
* Bad, because the identity managment needs to provide a stable, persistent, non-reassignable user
|
||||
identifier for an account, e.g. `owncloudUUID` or `ms-DS-ConsistencyGuid`
|
||||
* Bad, because we need to implment tools that can change the account id when it did change anyway
|
||||
* Bad, because without caching we will hammer the identity management system with lookup requests
|
||||
|
||||
### External identity management system is read only and does NOT provide an API to query users
|
||||
|
||||
Idp sends sub & iss and mail or username claims. We need to provision an internal account mapping,
|
||||
creating a unique ID, upon the first login of a user to be able to look up user properties by account
|
||||
id.
|
||||
|
||||
* Good, because this has very little external requirements
|
||||
* Good, because we have accounts fully under our control
|
||||
* Bad, because we have to provide the user lookup APIs
|
||||
* Bad, because users will only a visible after the first login
|
||||
* Bad, because our internal account mapping might get out of date when user attribute (e.g. name or
|
||||
mail) change. At least until the next time that user logs in
|
||||
|
||||
## Links <!-- optional -->
|
||||
|
||||
* [Link type] [Link to ADR] <!-- example: Refined by [ADR-0005](0005-example.md) -->
|
||||
* … <!-- numbers of links can vary -->
|
||||
* supersedes [3. Use external User Management]({{< ref "0003-external-user-management.md" >}})
|
||||
@@ -7,6 +7,7 @@ require (
|
||||
github.com/GeertJohan/yubigo v0.0.0-20190917122436-175bc097e60e
|
||||
github.com/ReneKroon/ttlcache/v2 v2.11.0
|
||||
github.com/asim/go-micro/plugins/client/grpc/v4 v4.0.0-20220118152736-9e0be6c85d75
|
||||
github.com/asim/go-micro/plugins/events/nats/v4 v4.0.0-20220118152736-9e0be6c85d75
|
||||
github.com/asim/go-micro/plugins/logger/zerolog/v4 v4.0.0-20220118152736-9e0be6c85d75
|
||||
github.com/asim/go-micro/plugins/registry/consul/v4 v4.0.0-20220118152736-9e0be6c85d75
|
||||
github.com/asim/go-micro/plugins/registry/etcd/v4 v4.0.0-20220118152736-9e0be6c85d75
|
||||
@@ -21,7 +22,7 @@ require (
|
||||
github.com/blevesearch/bleve/v2 v2.3.0
|
||||
github.com/coreos/go-oidc/v3 v3.1.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19
|
||||
github.com/cs3org/reva v1.16.1-0.20220221135950-8cc813ecfc4c
|
||||
github.com/cs3org/reva v1.16.1-0.20220224115936-e17c65a48a5a
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733
|
||||
github.com/go-chi/chi/v5 v5.0.7
|
||||
@@ -69,6 +70,7 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.4.1
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5
|
||||
google.golang.org/grpc v1.44.0
|
||||
@@ -91,7 +93,6 @@ require (
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||
github.com/asim/go-micro/plugins/events/nats/v4 v4.0.0-20220118152736-9e0be6c85d75 // indirect
|
||||
github.com/aws/aws-sdk-go v1.42.39 // indirect
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
@@ -249,7 +250,6 @@ require (
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
go.uber.org/zap v1.19.1 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
|
||||
@@ -339,8 +339,8 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S
|
||||
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
|
||||
github.com/cs3org/reva v1.16.1-0.20220221135950-8cc813ecfc4c h1:52qF91Pu/jUVVWgZo4kl2GaQT5SPCdV0b5s6SQG2jrM=
|
||||
github.com/cs3org/reva v1.16.1-0.20220221135950-8cc813ecfc4c/go.mod h1:M+Nausi93NaMDoinwiUX/Ekgrp/RrYv715FG5KrIarY=
|
||||
github.com/cs3org/reva v1.16.1-0.20220224115936-e17c65a48a5a h1:LgwfJ4N+ekLRFOK2vwVKbgtnQYYcrNiMtu5kekJvJ54=
|
||||
github.com/cs3org/reva v1.16.1-0.20220224115936-e17c65a48a5a/go.mod h1:M+Nausi93NaMDoinwiUX/Ekgrp/RrYv715FG5KrIarY=
|
||||
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
|
||||
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/notifications/pkg/command"
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := command.Execute(config.DefaultConfig()); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Package channels provides different communication channels to notify users.
|
||||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/smtp"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
groups "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
"github.com/owncloud/ocis/ocis-pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Channel defines the methods of a communication channel.
|
||||
type Channel interface {
|
||||
// SendMessage sends a message to users.
|
||||
SendMessage(userIDs []string, msg string) error
|
||||
// SendMessageToGroup sends a message to a group.
|
||||
SendMessageToGroup(groupdID *groups.GroupId, msg string) error
|
||||
}
|
||||
|
||||
// NewMailChannel instantiates a new mail communication channel.
|
||||
func NewMailChannel(cfg config.Config, logger log.Logger) (Channel, error) {
|
||||
gc, err := pool.GetGatewayServiceClient(cfg.Notifications.RevaGateway)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not get gateway client")
|
||||
return nil, err
|
||||
}
|
||||
return Mail{
|
||||
gatewayClient: gc,
|
||||
conf: cfg,
|
||||
logger: logger,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Mail is the communcation channel for email.
|
||||
type Mail struct {
|
||||
gatewayClient gateway.GatewayAPIClient
|
||||
conf config.Config
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
// SendMessage sends a message to all given users.
|
||||
func (m Mail) SendMessage(userIDs []string, msg string) error {
|
||||
to, err := m.getReceiverAddresses(userIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body := []byte(msg)
|
||||
|
||||
smtpConf := m.conf.Notifications.SMTP
|
||||
auth := smtp.PlainAuth("", smtpConf.Sender, smtpConf.Password, smtpConf.Host)
|
||||
if err := smtp.SendMail(smtpConf.Host+":"+smtpConf.Port, auth, smtpConf.Sender, to, body); err != nil {
|
||||
return errors.Wrap(err, "could not send mail")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendMessageToGroup sends a message to all members of the given group.
|
||||
func (m Mail) SendMessageToGroup(groupID *groups.GroupId, msg string) error {
|
||||
// TODO We need an authenticated context here...
|
||||
res, err := m.gatewayClient.GetGroup(context.Background(), &groups.GetGroupRequest{GroupId: groupID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.Status.Code != rpc.Code_CODE_OK {
|
||||
return errors.New("could not get group")
|
||||
}
|
||||
|
||||
members := make([]string, 0, len(res.Group.Members))
|
||||
for _, id := range res.Group.Members {
|
||||
members = append(members, id.OpaqueId)
|
||||
}
|
||||
|
||||
return m.SendMessage(members, msg)
|
||||
}
|
||||
|
||||
func (m Mail) getReceiverAddresses(receivers []string) ([]string, error) {
|
||||
addresses := make([]string, 0, len(receivers))
|
||||
for _, id := range receivers {
|
||||
// Authenticate is too costly but at the moment our only option to get the user.
|
||||
// We don't have an authenticated context so calling `GetUser` doesn't work.
|
||||
res, err := m.gatewayClient.Authenticate(context.Background(), &gateway.AuthenticateRequest{
|
||||
Type: "machine",
|
||||
ClientId: "userid:" + id,
|
||||
ClientSecret: m.conf.Notifications.MachineAuthSecret,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.Status.Code != rpc.Code_CODE_OK {
|
||||
m.logger.Error().
|
||||
Interface("status", res.Status).
|
||||
Str("receiver_id", id).
|
||||
Msg("could not get user")
|
||||
continue
|
||||
}
|
||||
addresses = append(addresses, res.User.Mail)
|
||||
}
|
||||
|
||||
return addresses, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Health is the entrypoint for the health command.
|
||||
func Health(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "health",
|
||||
Usage: "Check health status",
|
||||
Action: func(c *cli.Context) error {
|
||||
// Not implemented
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
"github.com/owncloud/ocis/ocis-pkg/clihelper"
|
||||
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
|
||||
"github.com/thejerf/suture/v4"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// GetCommands provides all commands for this service
|
||||
func GetCommands(cfg *config.Config) cli.Commands {
|
||||
return []*cli.Command{
|
||||
// start this service
|
||||
Server(cfg),
|
||||
|
||||
// interaction with this service
|
||||
|
||||
// infos about this service
|
||||
Health(cfg),
|
||||
Version(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
// Execute is the entry point for the notifications command.
|
||||
func Execute(cfg *config.Config) error {
|
||||
app := clihelper.DefaultApp(&cli.App{
|
||||
Name: "notifications",
|
||||
Usage: "starts notifications service",
|
||||
Commands: GetCommands(cfg),
|
||||
})
|
||||
|
||||
cli.HelpFlag = &cli.BoolFlag{
|
||||
Name: "help,h",
|
||||
Usage: "Show the help",
|
||||
}
|
||||
|
||||
return app.Run(os.Args)
|
||||
}
|
||||
|
||||
// SutureService allows for the notifications command to be embedded and supervised by a suture supervisor tree.
|
||||
type SutureService struct {
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
// NewSutureService creates a new notifications.SutureService
|
||||
func NewSutureService(cfg *ociscfg.Config) suture.Service {
|
||||
cfg.Settings.Commons = cfg.Commons
|
||||
return SutureService{
|
||||
cfg: cfg.Notifications,
|
||||
}
|
||||
}
|
||||
|
||||
func (s SutureService) Serve(ctx context.Context) error {
|
||||
s.cfg.Context = ctx
|
||||
if err := Execute(s.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/asim/go-micro/plugins/events/nats/v4"
|
||||
"github.com/cs3org/reva/pkg/events"
|
||||
"github.com/cs3org/reva/pkg/events/server"
|
||||
"github.com/owncloud/ocis/notifications/pkg/channels"
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
"github.com/owncloud/ocis/notifications/pkg/config/parser"
|
||||
"github.com/owncloud/ocis/notifications/pkg/logging"
|
||||
"github.com/owncloud/ocis/notifications/pkg/service"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Server is the entrypoint for the server command.
|
||||
func Server(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "server",
|
||||
Usage: fmt.Sprintf("start %s extension without runtime (unsupervised mode)", cfg.Service.Name),
|
||||
Category: "server",
|
||||
Before: func(c *cli.Context) error {
|
||||
return parser.ParseConfig(cfg)
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
logger := logging.Configure(cfg.Service.Name, cfg.Log)
|
||||
|
||||
evs := []events.Unmarshaller{
|
||||
events.ShareCreated{},
|
||||
}
|
||||
|
||||
evtsCfg := cfg.Notifications.Events
|
||||
client, err := server.NewNatsStream(nats.Address(evtsCfg.Endpoint), nats.ClusterID(evtsCfg.Cluster))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
evts, err := events.Consume(client, evtsCfg.ConsumerGroup, evs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
channel, err := channels.NewMailChannel(*cfg, logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
svc := service.NewEventsNotifier(evts, channel, logger)
|
||||
return svc.Run()
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Version prints the service versions of all running instances.
|
||||
func Version(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "version",
|
||||
Usage: "print the version of this binary and the running extension instances",
|
||||
Category: "info",
|
||||
Action: func(c *cli.Context) error {
|
||||
// not implemented
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/owncloud/ocis/ocis-pkg/shared"
|
||||
)
|
||||
|
||||
// Config combines all available configuration parts.
|
||||
type Config struct {
|
||||
*shared.Commons
|
||||
|
||||
Service Service
|
||||
|
||||
Log *Log `ocisConfig:"log"`
|
||||
Debug Debug `ocisConfig:"debug"`
|
||||
|
||||
Notifications Notifications `ocisConfig:"notifications"`
|
||||
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
// Notifications definces the config options for the notifications service.
|
||||
type Notifications struct {
|
||||
SMTP SMTP `ocisConfig:"SMTP"`
|
||||
Events Events `ocisConfig:"events"`
|
||||
RevaGateway string `ocisConfig:"reva_gateway" env:"REVA_GATEWAY;NOTIFICATIONS_REVA_GATEWAY"`
|
||||
MachineAuthSecret string `ocisConfig:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;NOTIFICATIONS_MACHINE_AUTH_API_KEY"`
|
||||
}
|
||||
|
||||
// SMTP combines the smtp configuration options.
|
||||
type SMTP struct {
|
||||
Host string `ocisConfig:"smtp_host" env:"NOTIFICATIONS_SMTP_HOST"`
|
||||
Port string `ocisConfig:"smtp_port" env:"NOTIFICATIONS_SMTP_PORT"`
|
||||
Sender string `ocisConfig:"smtp_sender" env:"NOTIFICATIONS_SMTP_SENDER"`
|
||||
Password string `ocisConfig:"smtp_password" env:"NOTIFICATIONS_SMTP_PASSWORD"`
|
||||
}
|
||||
|
||||
// Events combines the configuration options for the event bus.
|
||||
type Events struct {
|
||||
Endpoint string `ocisConfig:"events_endpoint" env:"NOTIFICATIONS_EVENTS_ENDPOINT"`
|
||||
Cluster string `ocisConfig:"events_cluster" env:"NOTIFICATIONS_EVENTS_CLUSTER"`
|
||||
ConsumerGroup string `ocisConfig:"events_group" env:"NOTIFICATIONS_EVENTS_GROUP"`
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
// Debug defines the available debug configuration.
|
||||
type Debug struct {
|
||||
Addr string `ocisConfig:"addr" env:"NOTIFICATIONS_DEBUG_ADDR"`
|
||||
Token string `ocisConfig:"token" env:"NOTIFICATIONS_DEBUG_TOKEN"`
|
||||
Pprof bool `ocisConfig:"pprof" env:"NOTIFICATIONS_DEBUG_PPROF"`
|
||||
Zpages bool `ocisConfig:"zpages" env:"NOTIFICATIONS_DEBUG_ZPAGES"`
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package config
|
||||
|
||||
// NOTE: Most of this configuration is not needed to keep it as simple as possible
|
||||
// TODO: Clean up unneeded configuration
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Service: Service{
|
||||
Name: "notifications",
|
||||
},
|
||||
Notifications: Notifications{
|
||||
SMTP: SMTP{
|
||||
Host: "127.0.0.1",
|
||||
Port: "1025",
|
||||
Sender: "god@example.com",
|
||||
Password: "godisdead",
|
||||
},
|
||||
Events: Events{
|
||||
Endpoint: "127.0.0.1:4222",
|
||||
Cluster: "test-cluster",
|
||||
ConsumerGroup: "notifications",
|
||||
},
|
||||
RevaGateway: "127.0.0.1:9142",
|
||||
MachineAuthSecret: "change-me-please",
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
// Log defines the available log configuration.
|
||||
type Log struct {
|
||||
Level string `mapstructure:"level" env:"OCIS_LOG_LEVEL;NOTIFICATIONS_LOG_LEVEL"`
|
||||
Pretty bool `mapstructure:"pretty" env:"OCIS_LOG_PRETTY;NOTIFICATIONS_LOG_PRETTY"`
|
||||
Color bool `mapstructure:"color" env:"OCIS_LOG_COLOR;NOTIFICATIONS_LOG_COLOR"`
|
||||
File string `mapstructure:"file" env:"OCIS_LOG_FILE;NOTIFICATIONS_LOG_FILE"`
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
|
||||
|
||||
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
|
||||
)
|
||||
|
||||
// ParseConfig loads accounts configuration from known paths.
|
||||
func ParseConfig(cfg *config.Config) error {
|
||||
_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// provide with defaults for shared logging, since we need a valid destination address for BindEnv.
|
||||
if cfg.Log == nil && cfg.Commons != nil && cfg.Commons.Log != nil {
|
||||
cfg.Log = &config.Log{
|
||||
Level: cfg.Commons.Log.Level,
|
||||
Pretty: cfg.Commons.Log.Pretty,
|
||||
Color: cfg.Commons.Log.Color,
|
||||
File: cfg.Commons.Log.File,
|
||||
}
|
||||
} else if cfg.Log == nil {
|
||||
cfg.Log = &config.Log{}
|
||||
}
|
||||
|
||||
// load all env variables relevant to the config in the current context.
|
||||
if err := envdecode.Decode(cfg); err != nil {
|
||||
// no environment variable set for this config is an expected "error"
|
||||
if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
// Service defines the available service configuration.
|
||||
type Service struct {
|
||||
Name string
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/notifications/pkg/config"
|
||||
"github.com/owncloud/ocis/ocis-pkg/log"
|
||||
)
|
||||
|
||||
// LoggerFromConfig initializes a service-specific logger instance.
|
||||
func Configure(name string, cfg *config.Log) log.Logger {
|
||||
return log.NewLogger(
|
||||
log.Name(name),
|
||||
log.Level(cfg.Level),
|
||||
log.Pretty(cfg.Pretty),
|
||||
log.Color(cfg.Color),
|
||||
log.File(cfg.File),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/cs3org/reva/pkg/events"
|
||||
"github.com/owncloud/ocis/notifications/pkg/channels"
|
||||
"github.com/owncloud/ocis/ocis-pkg/log"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Run() error
|
||||
}
|
||||
|
||||
func NewEventsNotifier(events <-chan interface{}, channel channels.Channel, logger log.Logger) Service {
|
||||
return eventsNotifier{
|
||||
logger: logger,
|
||||
channel: channel,
|
||||
events: events,
|
||||
signals: make(chan os.Signal, 1),
|
||||
}
|
||||
}
|
||||
|
||||
type eventsNotifier struct {
|
||||
logger log.Logger
|
||||
channel channels.Channel
|
||||
events <-chan interface{}
|
||||
signals chan os.Signal
|
||||
}
|
||||
|
||||
func (s eventsNotifier) Run() error {
|
||||
signal.Notify(s.signals, syscall.SIGINT, syscall.SIGTERM)
|
||||
s.logger.Debug().
|
||||
Msg("eventsNotifier started")
|
||||
for {
|
||||
select {
|
||||
case evt := <-s.events:
|
||||
go func() {
|
||||
switch e := evt.(type) {
|
||||
case events.ShareCreated:
|
||||
msg := "You got a share!"
|
||||
var err error
|
||||
if e.GranteeUserID != nil {
|
||||
err = s.channel.SendMessage([]string{e.GranteeUserID.OpaqueId}, msg)
|
||||
} else if e.GranteeGroupID != nil {
|
||||
err = s.channel.SendMessageToGroup(e.GranteeGroupID, msg)
|
||||
}
|
||||
if err != nil {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("failed to send a message")
|
||||
}
|
||||
}
|
||||
}()
|
||||
case <-s.signals:
|
||||
s.logger.Debug().
|
||||
Msg("eventsNotifier stopped")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
graph "github.com/owncloud/ocis/graph/pkg/config"
|
||||
idp "github.com/owncloud/ocis/idp/pkg/config"
|
||||
nats "github.com/owncloud/ocis/nats/pkg/config"
|
||||
notifications "github.com/owncloud/ocis/notifications/pkg/config"
|
||||
ocs "github.com/owncloud/ocis/ocs/pkg/config"
|
||||
proxy "github.com/owncloud/ocis/proxy/pkg/config"
|
||||
settings "github.com/owncloud/ocis/settings/pkg/config"
|
||||
@@ -62,6 +63,7 @@ type Config struct {
|
||||
GraphExplorer *graphExplorer.Config `ocisConfig:"graph_explorer"`
|
||||
IDP *idp.Config `ocisConfig:"idp"`
|
||||
Nats *nats.Config `ocisConfig:"nats"`
|
||||
Notifications *notifications.Config `ocisConfig:"notifications"`
|
||||
OCS *ocs.Config `ocisConfig:"ocs"`
|
||||
Web *web.Config `ocisConfig:"web"`
|
||||
Proxy *proxy.Config `ocisConfig:"proxy"`
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
graph "github.com/owncloud/ocis/graph/pkg/config"
|
||||
idp "github.com/owncloud/ocis/idp/pkg/config"
|
||||
nats "github.com/owncloud/ocis/nats/pkg/config"
|
||||
notifications "github.com/owncloud/ocis/notifications/pkg/config"
|
||||
ocs "github.com/owncloud/ocis/ocs/pkg/config"
|
||||
proxy "github.com/owncloud/ocis/proxy/pkg/config"
|
||||
settings "github.com/owncloud/ocis/settings/pkg/config"
|
||||
@@ -31,6 +32,7 @@ func DefaultConfig() *Config {
|
||||
Graph: graph.DefaultConfig(),
|
||||
IDP: idp.DefaultConfig(),
|
||||
Nats: nats.DefaultConfig(),
|
||||
Notifications: notifications.DefaultConfig(),
|
||||
Proxy: proxy.DefaultConfig(),
|
||||
GraphExplorer: graphExplorer.DefaultConfig(),
|
||||
OCS: ocs.DefaultConfig(),
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/notifications/pkg/command"
|
||||
"github.com/owncloud/ocis/ocis-pkg/config"
|
||||
"github.com/owncloud/ocis/ocis-pkg/config/parser"
|
||||
"github.com/owncloud/ocis/ocis/pkg/register"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// NatsServerCommand is the entrypoint for the nats server command.
|
||||
func NotificationsCommand(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "notifications",
|
||||
Usage: "start notifications service",
|
||||
Category: "extensions",
|
||||
Before: func(ctx *cli.Context) error {
|
||||
return parser.ParseConfig(cfg)
|
||||
},
|
||||
Subcommands: command.GetCommands(cfg.Notifications),
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
register.AddCommand(NotificationsCommand)
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
graph "github.com/owncloud/ocis/graph/pkg/command"
|
||||
idp "github.com/owncloud/ocis/idp/pkg/command"
|
||||
nats "github.com/owncloud/ocis/nats/pkg/command"
|
||||
notifications "github.com/owncloud/ocis/notifications/pkg/command"
|
||||
"github.com/owncloud/ocis/ocis-pkg/config"
|
||||
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
|
||||
"github.com/owncloud/ocis/ocis-pkg/log"
|
||||
@@ -114,6 +115,7 @@ func NewService(options ...Option) (*Service, error) {
|
||||
s.ServicesRegistry["storage-shares"] = storage.NewStorageShares
|
||||
s.ServicesRegistry["storage-public-link"] = storage.NewStoragePublicLink
|
||||
s.ServicesRegistry["storage-appprovider"] = storage.NewAppProvider
|
||||
s.ServicesRegistry["notifications"] = notifications.NewSutureService
|
||||
|
||||
// populate delayed services
|
||||
s.Delayed["storage-sharing"] = storage.NewSharing
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"github.com/owncloud/ocis/proxy/pkg/webdav"
|
||||
)
|
||||
|
||||
const publicFilesEndpoint = "/remote.php/dav/public-files/"
|
||||
|
||||
// BasicAuth provides a middleware to check if BasicAuth is provided
|
||||
func BasicAuth(optionSetters ...Option) func(next http.Handler) http.Handler {
|
||||
options := newOptions(optionSetters...)
|
||||
@@ -111,7 +109,25 @@ type basicAuth struct {
|
||||
|
||||
func (m basicAuth) isPublicLink(req *http.Request) bool {
|
||||
login, _, ok := req.BasicAuth()
|
||||
return ok && login == "public" && strings.HasPrefix(req.URL.Path, publicFilesEndpoint)
|
||||
|
||||
if !ok || login != "public" {
|
||||
return false
|
||||
}
|
||||
|
||||
publicPaths := []string{
|
||||
"/remote.php/dav/public-files/",
|
||||
"/ocs/v1.php/cloud/capabilities",
|
||||
}
|
||||
isPublic := false
|
||||
|
||||
for _, p := range publicPaths {
|
||||
if strings.HasPrefix(req.URL.Path, p) {
|
||||
isPublic = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isPublic
|
||||
}
|
||||
|
||||
// The token auth endpoint uses basic auth for clients, see https://openid.net/specs/openid-connect-basic-1_0.html#TokenRequest
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
/**/
|
||||
|
||||
func TestBasicAuth__isPublicLink(t *testing.T) {
|
||||
tests := []struct {
|
||||
url string
|
||||
username string
|
||||
expected bool
|
||||
}{
|
||||
{url: "/remote.php/dav/public-files/", username: "", expected: false},
|
||||
{url: "/remote.php/dav/public-files/", username: "abc", expected: false},
|
||||
{url: "/remote.php/dav/public-files/", username: "private", expected: false},
|
||||
{url: "/remote.php/dav/public-files/", username: "public", expected: true},
|
||||
{url: "/ocs/v1.php/cloud/capabilities", username: "", expected: false},
|
||||
{url: "/ocs/v1.php/cloud/capabilities", username: "abc", expected: false},
|
||||
{url: "/ocs/v1.php/cloud/capabilities", username: "private", expected: false},
|
||||
{url: "/ocs/v1.php/cloud/capabilities", username: "public", expected: true},
|
||||
{url: "/ocs/v1.php/cloud/users/admin", username: "public", expected: false},
|
||||
}
|
||||
ba := basicAuth{}
|
||||
|
||||
for _, tt := range tests {
|
||||
req := httptest.NewRequest("", tt.url, nil)
|
||||
|
||||
if tt.username != "" {
|
||||
req.SetBasicAuth(tt.username, "")
|
||||
}
|
||||
|
||||
result := ba.isPublicLink(req)
|
||||
if result != tt.expected {
|
||||
t.Errorf("with %s expected %t got %t", tt.url, tt.expected, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ func Groups(cfg *config.Config) *cli.Command {
|
||||
tracing.Configure(cfg, logger)
|
||||
gr := run.Group{}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// pre-create folders
|
||||
if cfg.Reva.Groups.Driver == "json" && cfg.Reva.Groups.JSON != "" {
|
||||
@@ -40,9 +41,8 @@ func Groups(cfg *config.Config) *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
uuid := uuid.Must(uuid.NewV4())
|
||||
pidFile := path.Join(os.TempDir(), "revad-"+c.Command.Name+"-"+uuid.String()+".pid")
|
||||
defer cancel()
|
||||
cuuid := uuid.Must(uuid.NewV4())
|
||||
pidFile := path.Join(os.TempDir(), "revad-"+c.Command.Name+"-"+cuuid.String()+".pid")
|
||||
|
||||
rcfg := groupsConfigFromStruct(c, cfg)
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ The expected failures in this file are from features in the owncloud/core repo.
|
||||
Basic file management like up and download, move, copy, properties, trash, versions and chunking.
|
||||
|
||||
#### [Getting information about a folder overwritten by a file gives 500 error instead of 404](https://github.com/owncloud/ocis/issues/1239)
|
||||
- [apiWebdavProperties1/copyFile.feature:286](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L286)
|
||||
- [apiWebdavProperties1/copyFile.feature:287](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L287)
|
||||
- [apiWebdavProperties1/copyFile.feature:288](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L288)
|
||||
- [apiWebdavProperties1/copyFile.feature:309](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L309)
|
||||
- [apiWebdavProperties1/copyFile.feature:310](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L310)
|
||||
- [apiWebdavProperties1/copyFile.feature:311](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L311)
|
||||
|
||||
|
||||
#### [Custom dav properties with namespaces are rendered incorrectly](https://github.com/owncloud/ocis/issues/2140)
|
||||
@@ -21,12 +21,12 @@ _ocdav: double check the webdav property parsing when custom namespaces are used
|
||||
- [apiWebdavProperties1/setFileProperties.feature:84](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/setFileProperties.feature#L84)
|
||||
|
||||
#### [Cannot set custom webDav properties](https://github.com/owncloud/product/issues/264)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:348](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L348)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:353](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L353)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:358](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L358)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:389](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L389)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:394](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L394)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:399](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L399)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:360](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L360)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:365](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L365)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:370](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L370)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:401](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L401)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:406](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L406)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:411](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L411)
|
||||
|
||||
#### [downloading an old version of a file returns 501](https://github.com/owncloud/ocis/issues/2261)
|
||||
- [apiVersions/fileVersions.feature:426](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiVersions/fileVersions.feature#L426)
|
||||
@@ -538,12 +538,6 @@ cannot share a folder with create permission
|
||||
- [apiSharePublicLink2/copyFromPublicLink.feature:182](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/copyFromPublicLink.feature#L182)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:45](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L45)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:46](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L46)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:118](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L118)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:119](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L119)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:120](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L120)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:121](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L121)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:126](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L126)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:127](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L127)
|
||||
|
||||
#### [OCIS share permissions not enforced](https://github.com/owncloud/product/issues/270)
|
||||
|
||||
@@ -554,10 +548,10 @@ cannot share a folder with create permission
|
||||
|
||||
#### [Adding public upload to a read only shared folder as a recipient is allowed ](https://github.com/owncloud/ocis/issues/2164)
|
||||
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:342](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L342)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:343](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L343)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:402](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L402)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:403](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L403)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:338](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L338)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:339](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L339)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:398](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L398)
|
||||
- [apiSharePublicLink2/updatePublicLinkShare.feature:399](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/updatePublicLinkShare.feature#L399)
|
||||
|
||||
#### [Upload-only shares must not overwrite but create a separate file](https://github.com/owncloud/ocis-reva/issues/286)
|
||||
|
||||
@@ -651,32 +645,32 @@ _getting and setting quota_
|
||||
- [apiMain/quota.feature:269](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/quota.feature#L269)
|
||||
- [apiMain/quota.feature:283](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/quota.feature#L283)
|
||||
- [apiMain/quota.feature:289](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/quota.feature#L289)
|
||||
Scenario Outline: Retrieving folder quota of shared folder with quota when no quota is set for recipient
|
||||
- [apiWebdavProperties1/getQuota.feature:58](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L58)
|
||||
- [apiWebdavProperties1/getQuota.feature:59](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L59)
|
||||
- [apiWebdavProperties1/getQuota.feature:64](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L64)
|
||||
Scenario Outline: Retrieving folder quota when quota is set and a file was uploaded
|
||||
- [apiWebdavProperties1/getQuota.feature:77](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L77)
|
||||
- [apiWebdavProperties1/getQuota.feature:78](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L78)
|
||||
- [apiWebdavProperties1/getQuota.feature:83](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L83)
|
||||
Scenario Outline: Retrieving folder quota when quota is set and a file was received
|
||||
- [apiWebdavProperties1/getQuota.feature:98](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L98)
|
||||
- [apiWebdavProperties1/getQuota.feature:99](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L99)
|
||||
- [apiWebdavProperties1/getQuota.feature:104](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L104)
|
||||
Scenario Outline: Retrieving folder quota when no quota is set
|
||||
- [apiWebdavProperties1/getQuota.feature:17](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L17)
|
||||
- [apiWebdavProperties1/getQuota.feature:18](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L18)
|
||||
- [apiWebdavProperties1/getQuota.feature:23](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L23)
|
||||
- [apiWebdavProperties1/getQuota.feature:19](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L19)
|
||||
- [apiWebdavProperties1/getQuota.feature:24](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L24)
|
||||
Scenario Outline: Retrieving folder quota when quota is set
|
||||
- [apiWebdavProperties1/getQuota.feature:32](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L32)
|
||||
- [apiWebdavProperties1/getQuota.feature:33](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L33)
|
||||
- [apiWebdavProperties1/getQuota.feature:38](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L38)
|
||||
- [apiWebdavProperties1/getQuota.feature:34](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L34)
|
||||
- [apiWebdavProperties1/getQuota.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L35)
|
||||
- [apiWebdavProperties1/getQuota.feature:40](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L40)
|
||||
Scenario Outline: Retrieving folder quota of shared folder with quota when no quota is set for recipient
|
||||
- [apiWebdavProperties1/getQuota.feature:61](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L61)
|
||||
- [apiWebdavProperties1/getQuota.feature:62](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L62)
|
||||
- [apiWebdavProperties1/getQuota.feature:67](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L67)
|
||||
Scenario Outline: Retrieving folder quota when quota is set and a file was uploaded
|
||||
- [apiWebdavProperties1/getQuota.feature:81](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L81)
|
||||
- [apiWebdavProperties1/getQuota.feature:82](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L82)
|
||||
- [apiWebdavProperties1/getQuota.feature:87](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L87)
|
||||
Scenario Outline: Retrieving folder quota when quota is set and a file was received
|
||||
- [apiWebdavProperties1/getQuota.feature:103](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L103)
|
||||
- [apiWebdavProperties1/getQuota.feature:104](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L104)
|
||||
- [apiWebdavProperties1/getQuota.feature:109](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L109)
|
||||
|
||||
#### [Private link support](https://github.com/owncloud/product/issues/201)
|
||||
#### [oc:privatelink property not returned in webdav responses](https://github.com/owncloud/product/issues/262)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:295](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L295)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:296](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L296)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:301](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L301)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:306](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L306)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:307](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L307)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:312](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L312)
|
||||
|
||||
#### [changing user quota gives ocs status 103 / Cannot set quota](https://github.com/owncloud/product/issues/247)
|
||||
- [apiShareOperationsToShares2/uploadToShare.feature:193](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/uploadToShare.feature#L193)
|
||||
@@ -1104,10 +1098,6 @@ API, search, favorites, config, capabilities, not existing endpoints, CORS and o
|
||||
#### [no robots.txt available](https://github.com/owncloud/ocis/issues/1314)
|
||||
- [apiMain/main.feature:5](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/main.feature#L5) Scenario: robots.txt file should be accessible
|
||||
|
||||
#### [Different version, edition and productname in status request and capabilities request](https://github.com/owncloud/ocis/issues/2174)
|
||||
- [apiMain/status.feature:5](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/status.feature#L5) Scenario: Status.php is correct
|
||||
#### [ocs config endpoint only accessible by authorized users](https://github.com/owncloud/ocis/issues/1338)
|
||||
|
||||
#### [Ability to return error messages in Webdav response bodies](https://github.com/owncloud/ocis/issues/1293)
|
||||
- [apiAuthOcs/ocsDELETEAuth.feature:10](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthOcs/ocsDELETEAuth.feature#L10) Scenario: send DELETE requests to OCS endpoints as admin with wrong password
|
||||
- [apiAuthOcs/ocsGETAuth.feature:10](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthOcs/ocsGETAuth.feature#L10) Scenario: using OCS anonymously
|
||||
@@ -1197,24 +1187,24 @@ _ocdav: api compatibility, return correct status code_
|
||||
- [apiWebdavOperations/search.feature:270](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/search.feature#L270)
|
||||
|
||||
And other missing implementation of favorites
|
||||
- [apiFavorites/favorites.feature:158](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L158)
|
||||
- [apiFavorites/favorites.feature:159](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L159)
|
||||
- [apiFavorites/favorites.feature:183](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L183)
|
||||
- [apiFavorites/favorites.feature:184](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L184)
|
||||
- [apiFavorites/favorites.feature:189](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L189)
|
||||
- [apiFavorites/favorites.feature:216](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L216)
|
||||
- [apiFavorites/favorites.feature:217](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L217)
|
||||
- [apiFavorites/favorites.feature:222](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L222)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:77](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L77)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:78](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L78)
|
||||
- [apiFavorites/favorites.feature:162](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L162)
|
||||
- [apiFavorites/favorites.feature:163](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L163)
|
||||
- [apiFavorites/favorites.feature:187](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L187)
|
||||
- [apiFavorites/favorites.feature:188](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L188)
|
||||
- [apiFavorites/favorites.feature:193](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L193)
|
||||
- [apiFavorites/favorites.feature:220](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L220)
|
||||
- [apiFavorites/favorites.feature:221](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L221)
|
||||
- [apiFavorites/favorites.feature:226](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L226)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:82](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L82)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:88](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L88)
|
||||
|
||||
#### [resource inside Shares dir is not found using the spaces WebDAV API](https://github.com/owncloud/ocis/issues/2968)
|
||||
- [apiFavorites/favorites.feature:164](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L164)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:27](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L27)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:46](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L46)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:64](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L64)
|
||||
- [apiFavorites/favorites.feature:168](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L168)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:28](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L28)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:48](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L48)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:67](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L67)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:83](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L83)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:102](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L102)
|
||||
- [apiFavorites/favoritesSharingToShares.feature:108](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L108)
|
||||
- [apiMain/checksums.feature:203](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/checksums.feature#L203)
|
||||
- [apiShareOperationsToShares2/getWebDAVSharePermissions.feature:49](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/getWebDAVSharePermissions.feature#L49)
|
||||
- [apiShareOperationsToShares2/getWebDAVSharePermissions.feature:75](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/getWebDAVSharePermissions.feature#L75)
|
||||
@@ -1239,18 +1229,18 @@ And other missing implementation of favorites
|
||||
- [apiShareOperationsToShares2/uploadToShare.feature:171](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/uploadToShare.feature#L171)
|
||||
- [apiShareOperationsToShares2/uploadToShare.feature:346](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/uploadToShare.feature#L346)
|
||||
- [apiShareOperationsToShares2/uploadToShare.feature:347](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/uploadToShare.feature#L347)
|
||||
- [apiWebdavProperties1/copyFile.feature:90](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L90)
|
||||
- [apiWebdavProperties1/copyFile.feature:117](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L117)
|
||||
- [apiWebdavProperties1/copyFile.feature:293](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L293)
|
||||
- [apiWebdavProperties1/copyFile.feature:316](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L316)
|
||||
- [apiWebdavProperties1/copyFile.feature:344](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L344)
|
||||
- [apiWebdavProperties1/copyFile.feature:374](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L374)
|
||||
- [apiWebdavProperties1/copyFile.feature:403](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L403)
|
||||
- [apiWebdavProperties1/copyFile.feature:432](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L432)
|
||||
- [apiWebdavProperties1/copyFile.feature:516](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L516)
|
||||
- [apiWebdavProperties1/copyFile.feature:549](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L549)
|
||||
- [apiWebdavProperties1/copyFile.feature:581](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L581)
|
||||
- [apiWebdavProperties1/copyFile.feature:613](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L613)
|
||||
- [apiWebdavProperties1/copyFile.feature:89](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L89)
|
||||
- [apiWebdavProperties1/copyFile.feature:116](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L116)
|
||||
- [apiWebdavProperties1/copyFile.feature:292](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L292)
|
||||
- [apiWebdavProperties1/copyFile.feature:315](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L315)
|
||||
- [apiWebdavProperties1/copyFile.feature:343](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L343)
|
||||
- [apiWebdavProperties1/copyFile.feature:373](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L373)
|
||||
- [apiWebdavProperties1/copyFile.feature:402](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L402)
|
||||
- [apiWebdavProperties1/copyFile.feature:431](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L431)
|
||||
- [apiWebdavProperties1/copyFile.feature:515](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L515)
|
||||
- [apiWebdavProperties1/copyFile.feature:548](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L548)
|
||||
- [apiWebdavProperties1/copyFile.feature:580](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L580)
|
||||
- [apiWebdavProperties1/copyFile.feature:612](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L612)
|
||||
- [apiWebdavProperties1/createFileFolderWhenSharesExist.feature:37](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFileFolderWhenSharesExist.feature#L37)
|
||||
- [apiWebdavProperties1/createFileFolderWhenSharesExist.feature:38](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFileFolderWhenSharesExist.feature#L38)
|
||||
- [apiWebdavProperties1/createFileFolderWhenSharesExist.feature:39](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFileFolderWhenSharesExist.feature#L39)
|
||||
@@ -1559,26 +1549,26 @@ And other missing implementation of favorites
|
||||
- [apiShareOperationsToShares2/shareAccessByID.feature:163](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/shareAccessByID.feature#L163)
|
||||
|
||||
#### [[OC-storage] share-types field empty for shared file folder in webdav response](https://github.com/owncloud/ocis/issues/2144)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:207](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L207)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:208](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L208)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:213](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L213)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:215](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L215)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:216](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L216)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:221](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L221)
|
||||
|
||||
#### [Creating a public link with all permissions(31) fails](https://github.com/owncloud/ocis/issues/2145)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:265](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L265)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:266](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L266)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:271](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L271)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:275](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L275)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:276](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L276)
|
||||
- [apiWebdavProperties2/getFileProperties.feature:281](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L281)
|
||||
|
||||
#### [Shares to deleted group listed in the response](https://github.com/owncloud/ocis/issues/2441)
|
||||
- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:504](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L504)
|
||||
- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:505](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L505)
|
||||
|
||||
#### [Trying to copy a file into a readonly share gives HTTP 500 error](https://github.com/owncloud/ocis/issues/2166)
|
||||
- [apiWebdavProperties1/copyFile.feature:452](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L452)
|
||||
- [apiWebdavProperties1/copyFile.feature:453](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L453)
|
||||
- [apiWebdavProperties1/copyFile.feature:454](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L454)
|
||||
- [apiWebdavProperties1/copyFile.feature:459](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L459)
|
||||
- [apiWebdavProperties1/copyFile.feature:458](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L458)
|
||||
- [apiWebdavProperties1/copyFile.feature:478](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L478)
|
||||
- [apiWebdavProperties1/copyFile.feature:479](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L479)
|
||||
- [apiWebdavProperties1/copyFile.feature:480](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L480)
|
||||
- [apiWebdavProperties1/copyFile.feature:485](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L485)
|
||||
- [apiWebdavProperties1/copyFile.feature:484](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L484)
|
||||
|
||||
### Won't fix
|
||||
Not everything needs to be implemented for ocis. While the oc10 testsuite covers these things we are not looking at them right now.
|
||||
@@ -1598,12 +1588,12 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers
|
||||
- [apiWebdavUpload1/uploadFileToExcludedDirectory.feature:87](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavUpload1/uploadFileToExcludedDirectory.feature#L87)
|
||||
|
||||
#### [Blacklist files extensions](https://github.com/owncloud/ocis/issues/2177)
|
||||
- [apiWebdavProperties1/copyFile.feature:132](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L132)
|
||||
- [apiWebdavProperties1/copyFile.feature:133](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L133)
|
||||
- [apiWebdavProperties1/copyFile.feature:134](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L134)
|
||||
- [apiWebdavProperties1/copyFile.feature:139](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L139)
|
||||
- [apiWebdavProperties1/createFolder.feature:92](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFolder.feature#L92)
|
||||
- [apiWebdavProperties1/createFolder.feature:93](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFolder.feature#L93)
|
||||
- [apiWebdavProperties1/createFolder.feature:98](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFolder.feature#L98)
|
||||
- [apiWebdavProperties1/copyFile.feature:138](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/copyFile.feature#L138)
|
||||
- [apiWebdavProperties1/createFolder.feature:95](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFolder.feature#L95)
|
||||
- [apiWebdavProperties1/createFolder.feature:96](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFolder.feature#L96)
|
||||
- [apiWebdavProperties1/createFolder.feature:101](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/createFolder.feature#L101)
|
||||
- [apiWebdavUpload1/uploadFile.feature:181](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavUpload1/uploadFile.feature#L181)
|
||||
- [apiWebdavUpload1/uploadFile.feature:182](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavUpload1/uploadFile.feature#L182)
|
||||
- [apiWebdavUpload1/uploadFile.feature:187](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavUpload1/uploadFile.feature#L187)
|
||||
@@ -1721,9 +1711,9 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers
|
||||
- [apiWebdavMove2/moveFileToBlacklistedName.feature:80](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavMove2/moveFileToBlacklistedName.feature#L80)
|
||||
|
||||
#### [REPORT method on spaces returns an incorrect d:href response](https://github.com/owncloud/ocis/issues/3111)
|
||||
- [apiFavorites/favorites.feature:117](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L117)
|
||||
- [apiFavorites/favorites.feature:143](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L143)
|
||||
- [apiFavorites/favorites.feature:268](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L268)
|
||||
- [apiFavorites/favorites.feature:121](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L121)
|
||||
- [apiFavorites/favorites.feature:147](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L147)
|
||||
- [apiFavorites/favorites.feature:273](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L273)
|
||||
|
||||
#### [could not create system tag](https://github.com/owncloud/ocis/issues/3092)
|
||||
- [apiWebdavOperations/search.feature:273](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/search.feature#L273)
|
||||
|
||||
@@ -491,9 +491,6 @@ Other free text and markdown formatting can be used elsewhere in the document if
|
||||
- [webUISharingInternalGroups/shareWithGroups.feature:77](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingInternalGroups/shareWithGroups.feature#L77)
|
||||
- [webUISharingInternalUsers/shareWithUsers.feature:57](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingInternalUsers/shareWithUsers.feature#L57)
|
||||
|
||||
### [shares are not listed with full paths](https://github.com/owncloud/ocis/issues/2462)
|
||||
- [webUISharingPublicBasic/publicLinkCreate.feature:88](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingPublicBasic/publicLinkCreate.feature#L88)
|
||||
|
||||
### [web config update is not properly reflected after the ocis start](https://github.com/owncloud/ocis/issues/2944)
|
||||
- [webUIFiles/breadcrumb.feature:50](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFiles/breadcrumb.feature#L50)
|
||||
|
||||
|
||||
@@ -217,11 +217,24 @@ func (g Thumbnail) handleWebdavSource(ctx context.Context, req *thumbnailssvc.Ge
|
||||
func (g Thumbnail) stat(path, auth string) (*provider.StatResponse, error) {
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), revactx.TokenHeader, auth)
|
||||
|
||||
req := &provider.StatRequest{
|
||||
Ref: &provider.Reference{
|
||||
var ref *provider.Reference
|
||||
if strings.Contains(path, "!") {
|
||||
parts := strings.Split(path, "!")
|
||||
spaceID, path := parts[0], parts[1]
|
||||
ref = &provider.Reference{
|
||||
ResourceId: &provider.ResourceId{
|
||||
StorageId: spaceID,
|
||||
OpaqueId: spaceID,
|
||||
},
|
||||
Path: path,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
ref = &provider.Reference{
|
||||
Path: path,
|
||||
}
|
||||
}
|
||||
|
||||
req := &provider.StatRequest{Ref: ref}
|
||||
rsp, err := g.cs3Client.Stat(ctx, req)
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Str("path", path).Msg("could not stat file")
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
@@ -42,12 +43,24 @@ func (s CS3) Get(ctx context.Context, path string) (io.ReadCloser, error) {
|
||||
if !ok {
|
||||
return nil, errors.New("cs3source: authorization missing")
|
||||
}
|
||||
ctx = metadata.AppendToOutgoingContext(context.Background(), revactx.TokenHeader, auth)
|
||||
rsp, err := s.client.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{
|
||||
Ref: &provider.Reference{
|
||||
var ref *provider.Reference
|
||||
if strings.Contains(path, "!") {
|
||||
parts := strings.Split(path, "!")
|
||||
spaceID, path := parts[0], parts[1]
|
||||
ref = &provider.Reference{
|
||||
ResourceId: &provider.ResourceId{
|
||||
StorageId: spaceID,
|
||||
OpaqueId: spaceID,
|
||||
},
|
||||
Path: path,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
ref = &provider.Reference{
|
||||
Path: path,
|
||||
}
|
||||
}
|
||||
ctx = metadata.AppendToOutgoingContext(context.Background(), revactx.TokenHeader, auth)
|
||||
rsp, err := s.client.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: ref})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"golang.org/x/net/html"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type fileServer struct {
|
||||
root http.FileSystem
|
||||
}
|
||||
|
||||
func FileServer(root http.FileSystem) http.Handler {
|
||||
return &fileServer{root}
|
||||
}
|
||||
|
||||
func (f *fileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
upath := path.Clean(path.Join("/", r.URL.Path))
|
||||
r.URL.Path = upath
|
||||
|
||||
asset, err := f.root.Open(upath)
|
||||
if err != nil {
|
||||
r.URL.Path = "/index.html"
|
||||
f.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
defer asset.Close()
|
||||
|
||||
s, _ := asset.Stat()
|
||||
if s.IsDir() {
|
||||
r.URL.Path = "/index.html"
|
||||
f.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(s.Name())))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
switch s.Name() {
|
||||
case "index.html", "oidc-callback.html", "oidc-silent-redirect.html":
|
||||
_ = withBase(buf, asset, "/")
|
||||
default:
|
||||
_, _ = buf.ReadFrom(asset)
|
||||
}
|
||||
|
||||
_, _ = w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
func withBase(w io.Writer, r io.Reader, base string) error {
|
||||
doc, _ := html.Parse(r)
|
||||
var parse func(*html.Node)
|
||||
parse = func(n *html.Node) {
|
||||
if n.Type == html.ElementNode && n.Data == "head" {
|
||||
n.InsertBefore(&html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: "base",
|
||||
Attr: []html.Attribute{
|
||||
{
|
||||
Key: "href",
|
||||
Val: base,
|
||||
},
|
||||
},
|
||||
}, n.FirstChild)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
parse(c)
|
||||
}
|
||||
}
|
||||
parse(doc)
|
||||
|
||||
return html.Render(w, doc)
|
||||
}
|
||||
@@ -2,10 +2,12 @@ package svc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -141,28 +143,19 @@ func (p Web) Static(ttl int) http.HandlerFunc {
|
||||
if !strings.HasSuffix(rootWithSlash, "/") {
|
||||
rootWithSlash = rootWithSlash + "/"
|
||||
}
|
||||
assets := assets.New(
|
||||
assets.Logger(p.logger),
|
||||
assets.Config(p.config),
|
||||
)
|
||||
|
||||
notFoundFunc := func(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO: replace the redirect with a not found page containing a link to the Web UI
|
||||
http.Redirect(w, r, rootWithSlash, http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
||||
static := http.StripPrefix(
|
||||
rootWithSlash,
|
||||
interceptNotFound(
|
||||
http.FileServer(assets),
|
||||
notFoundFunc,
|
||||
assets.FileServer(
|
||||
assets.New(
|
||||
assets.Logger(p.logger),
|
||||
assets.Config(p.config),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// TODO: investigate broken caching - https://github.com/owncloud/ocis/issues/1094
|
||||
// we don't have a last modification date of the static assets, so we use the service start date
|
||||
//lastModified := time.Now().UTC().Format(http.TimeFormat)
|
||||
//expires := time.Now().Add(time.Second * time.Duration(ttl)).UTC().Format(http.TimeFormat)
|
||||
lastModified := time.Now().UTC().Format(http.TimeFormat)
|
||||
expires := time.Now().Add(time.Second * time.Duration(ttl)).UTC().Format(http.TimeFormat)
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if rootWithSlash != "/" && r.URL.Path == p.config.HTTP.Root {
|
||||
@@ -175,49 +168,11 @@ func (p Web) Static(ttl int) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Path != rootWithSlash && strings.HasSuffix(r.URL.Path, "/") {
|
||||
notFoundFunc(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: investigate broken caching - https://github.com/owncloud/ocis/issues/1094
|
||||
//w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%s, must-revalidate", strconv.Itoa(ttl)))
|
||||
//w.Header().Set("Expires", expires)
|
||||
//w.Header().Set("Last-Modified", lastModified)
|
||||
w.Header().Set("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
|
||||
w.Header().Set("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
|
||||
w.Header().Set("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
|
||||
w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%s, must-revalidate", strconv.Itoa(ttl)))
|
||||
w.Header().Set("Expires", expires)
|
||||
w.Header().Set("Last-Modified", lastModified)
|
||||
w.Header().Set("SameSite", "Strict")
|
||||
|
||||
static.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func interceptNotFound(h http.Handler, notFoundFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
notFoundInterceptor := &NotFoundInterceptor{ResponseWriter: w}
|
||||
h.ServeHTTP(notFoundInterceptor, r)
|
||||
if notFoundInterceptor.status == http.StatusNotFound {
|
||||
notFoundFunc(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type NotFoundInterceptor struct {
|
||||
http.ResponseWriter
|
||||
status int
|
||||
}
|
||||
|
||||
func (w *NotFoundInterceptor) WriteHeader(status int) {
|
||||
w.status = status
|
||||
if status != http.StatusNotFound {
|
||||
w.ResponseWriter.WriteHeader(status)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *NotFoundInterceptor) Write(p []byte) (int, error) {
|
||||
if w.status != http.StatusNotFound {
|
||||
return w.ResponseWriter.Write(p)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ type ThumbnailRequest struct {
|
||||
Height int32
|
||||
// In case of a public share the public link token.
|
||||
PublicLinkToken string
|
||||
// The username from the requested URL
|
||||
Username string
|
||||
// The Identifier from the requested URL
|
||||
Identifier string
|
||||
}
|
||||
|
||||
// ParseThumbnailRequest extracts all required parameters from a http request.
|
||||
func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) {
|
||||
fp, username, err := extractFilePath(r)
|
||||
fp, id, err := extractFilePath(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) {
|
||||
Width: int32(width),
|
||||
Height: int32(height),
|
||||
PublicLinkToken: chi.URLParam(r, "token"),
|
||||
Username: username,
|
||||
Identifier: id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -68,16 +68,17 @@ func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) {
|
||||
// User and filepath are dynamic and filepath can contain slashes
|
||||
// So using the URLParam function is not possible.
|
||||
func extractFilePath(r *http.Request) (string, string, error) {
|
||||
user := chi.URLParam(r, "user")
|
||||
user, err := url.QueryUnescape(user)
|
||||
id := chi.URLParam(r, "id")
|
||||
id, err := url.QueryUnescape(id)
|
||||
if err != nil {
|
||||
return "", "", errors.New("could not unescape user")
|
||||
}
|
||||
if user != "" {
|
||||
parts := strings.SplitN(r.URL.Path, user, 2)
|
||||
return parts[1], user, nil
|
||||
if id != "" {
|
||||
parts := strings.SplitN(r.URL.Path, id, 2)
|
||||
return parts[1], id, nil
|
||||
}
|
||||
|
||||
// This is for public links
|
||||
token := chi.URLParam(r, "token")
|
||||
if token != "" {
|
||||
parts := strings.SplitN(r.URL.Path, token, 2)
|
||||
|
||||
@@ -66,7 +66,8 @@ func NewService(opts ...Option) (Service, error) {
|
||||
}
|
||||
|
||||
m.Route(options.Config.HTTP.Root, func(r chi.Router) {
|
||||
r.Get("/remote.php/dav/files/{user}/*", svc.Thumbnail)
|
||||
r.Get("/remote.php/dav/spaces/{id}/*", svc.SpacesThumbnail)
|
||||
r.Get("/remote.php/dav/files/{id}/*", svc.Thumbnail)
|
||||
r.Get("/remote.php/dav/public-files/{token}/*", svc.PublicThumbnail)
|
||||
r.Head("/remote.php/dav/public-files/{token}/*", svc.PublicThumbnailHead)
|
||||
})
|
||||
@@ -88,6 +89,53 @@ func (g Webdav) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
g.mux.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// SpacesThumbnail is the endpoint for retrieving thumbnails inside of spaces.
|
||||
func (g Webdav) SpacesThumbnail(w http.ResponseWriter, r *http.Request) {
|
||||
tr, err := requests.ParseThumbnailRequest(r)
|
||||
if err != nil {
|
||||
g.log.Error().Err(err).Msg("could not create Request")
|
||||
renderError(w, r, errBadRequest(err.Error()))
|
||||
return
|
||||
}
|
||||
t := r.Header.Get(TokenHeader)
|
||||
|
||||
fullPath := tr.Identifier + "!" + tr.Filepath
|
||||
rsp, err := g.thumbnailsClient.GetThumbnail(r.Context(), &thumbnailssvc.GetThumbnailRequest{
|
||||
Filepath: strings.TrimLeft(tr.Filepath, "/"),
|
||||
ThumbnailType: extensionToThumbnailType(strings.TrimLeft(tr.Extension, ".")),
|
||||
Width: tr.Width,
|
||||
Height: tr.Height,
|
||||
Source: &thumbnailssvc.GetThumbnailRequest_Cs3Source{
|
||||
Cs3Source: &thumbnailsmsg.CS3Source{
|
||||
Path: fullPath,
|
||||
Authorization: t,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
e := merrors.Parse(err.Error())
|
||||
switch e.Code {
|
||||
case http.StatusNotFound:
|
||||
// StatusNotFound is expected for unsupported files
|
||||
renderError(w, r, errNotFound(notFoundMsg(tr.Filename)))
|
||||
return
|
||||
case http.StatusBadRequest:
|
||||
renderError(w, r, errBadRequest(err.Error()))
|
||||
default:
|
||||
renderError(w, r, errInternalError(err.Error()))
|
||||
}
|
||||
g.log.Error().Err(err).Msg("could not get thumbnail")
|
||||
return
|
||||
}
|
||||
|
||||
if len(rsp.Thumbnail) == 0 {
|
||||
renderError(w, r, errNotFound(""))
|
||||
return
|
||||
}
|
||||
|
||||
g.mustRender(w, r, newThumbnailResponse(rsp))
|
||||
}
|
||||
|
||||
// Thumbnail implements the Service interface.
|
||||
func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) {
|
||||
tr, err := requests.ParseThumbnailRequest(r)
|
||||
@@ -101,7 +149,7 @@ func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := metadata.AppendToOutgoingContext(r.Context(), TokenHeader, t)
|
||||
userRes, err := g.revaClient.GetUserByClaim(ctx, &userv1beta1.GetUserByClaimRequest{
|
||||
Claim: "username",
|
||||
Value: tr.Username,
|
||||
Value: tr.Identifier,
|
||||
})
|
||||
if err != nil || userRes.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
g.log.Error().Err(err).Msg("could not get user")
|
||||
|
||||
Reference in New Issue
Block a user