mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-01 18:01:28 -06:00
Merge branch 'master' into fix-userlog-jwt-secret
This commit is contained in:
44
.drone.star
44
.drone.star
@@ -17,7 +17,7 @@ OC_CI_PHP = "owncloudci/php:%s"
|
||||
OC_CI_WAIT_FOR = "owncloudci/wait-for:latest"
|
||||
OC_CS3_API_VALIDATOR = "owncloud/cs3api-validator:0.2.0"
|
||||
OC_LITMUS = "owncloudci/litmus:latest"
|
||||
OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.8.3"
|
||||
OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.8.5"
|
||||
OC_UBUNTU = "owncloud/ubuntu:20.04"
|
||||
PLUGINS_CODACY = "plugins/codacy:1"
|
||||
PLUGINS_DOCKER = "plugins/docker:latest"
|
||||
@@ -152,7 +152,7 @@ config = {
|
||||
"os": ["linux", "darwin"],
|
||||
},
|
||||
"dockerReleases": {
|
||||
"architectures": ["arm", "arm64", "amd64"],
|
||||
"architectures": ["arm64", "amd64"],
|
||||
},
|
||||
"litmus": True,
|
||||
"codestyle": True,
|
||||
@@ -1144,7 +1144,8 @@ def e2eTests(ctx):
|
||||
ocisServer("ocis", 4, []) + \
|
||||
e2e_test_ocis + \
|
||||
uploadTracingResult(ctx) + \
|
||||
publishTracingResult(ctx, "e2e test")
|
||||
buildTracingComment() + \
|
||||
e2eGithubComment()
|
||||
|
||||
if ("skip-e2e" in ctx.build.title.lower()):
|
||||
return []
|
||||
@@ -1177,7 +1178,7 @@ def uploadTracingResult(ctx):
|
||||
"path_style": True,
|
||||
"source": "webTestRunner/reports/e2e/playwright/tracing/**/*",
|
||||
"strip_prefix": "webTestRunner/reports/e2e/playwright/tracing",
|
||||
"target": "${DRONE_BUILD_NUMBER}/tracing",
|
||||
"target": "/${DRONE_REPO}/${DRONE_BUILD_NUMBER}/tracing",
|
||||
},
|
||||
"environment": {
|
||||
"AWS_ACCESS_KEY_ID": {
|
||||
@@ -1198,19 +1199,18 @@ def uploadTracingResult(ctx):
|
||||
},
|
||||
}]
|
||||
|
||||
def publishTracingResult(ctx, suite):
|
||||
def buildTracingComment():
|
||||
return [{
|
||||
"name": "publish-tracing-result",
|
||||
"name": "build-tracing-comment",
|
||||
"image": OC_UBUNTU,
|
||||
"commands": [
|
||||
"cd %s/reports/e2e/playwright/tracing/" % dirs["web"],
|
||||
'echo "<details><summary>:boom: To see the trace, please open the link in the console ...</summary>\\n\\n<p>\\n\\n" >> comments.file',
|
||||
'for f in *.zip; do echo "#### npx playwright show-trace $CACHE_ENDPOINT/$CACHE_BUCKET/${DRONE_BUILD_NUMBER}/tracing/$f \n" >> comments.file; done',
|
||||
'for f in *.zip; do echo "#### npx playwright show-trace $CACHE_ENDPOINT/$CACHE_BUCKET/${DRONE_REPO}/${DRONE_BUILD_NUMBER}/tracing/$f \n" >> comments.file; done',
|
||||
'echo "\n</p></details>" >> comments.file',
|
||||
"more comments.file",
|
||||
],
|
||||
"environment": {
|
||||
"TEST_CONTEXT": suite,
|
||||
"CACHE_ENDPOINT": {
|
||||
"from_secret": "cache_public_s3_server",
|
||||
},
|
||||
@@ -1229,6 +1229,34 @@ def publishTracingResult(ctx, suite):
|
||||
},
|
||||
}]
|
||||
|
||||
def e2eGithubComment():
|
||||
prefix = "E2E tests failed: ${DRONE_BUILD_LINK}/${DRONE_JOB_NUMBER}${DRONE_STAGE_NUMBER}/1"
|
||||
return [{
|
||||
"name": "github-comment",
|
||||
"image": THEGEEKLAB_DRONE_GITHUB_COMMENT,
|
||||
"pull": "if-not-exists",
|
||||
"settings": {
|
||||
"message": "%s/reports/e2e/playwright/tracing/comments.file" % dirs["web"],
|
||||
"key": "pr-${DRONE_PULL_REQUEST}",
|
||||
"update": "true",
|
||||
"api_key": {
|
||||
"from_secret": "github_token",
|
||||
},
|
||||
},
|
||||
"commands": [
|
||||
"cd %s/reports/e2e/playwright/tracing/" % dirs["web"],
|
||||
"if [ -s comments.file ]; then echo '%s' | cat - comments.file > temp && mv temp comments.file && /bin/drone-github-comment; fi" % prefix,
|
||||
],
|
||||
"when": {
|
||||
"status": [
|
||||
"failure",
|
||||
],
|
||||
"event": [
|
||||
"pull_request",
|
||||
],
|
||||
},
|
||||
}]
|
||||
|
||||
def failEarly(ctx, early_fail):
|
||||
"""failEarly sends posts a comment about the failed pipeline to the github pr and then kills all pipelines of the current build
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ See the [Quick Guide](https://doc.owncloud.com/ocis/next/quickguide/quickguide.h
|
||||
|
||||
### Use the ocis Repo as Source
|
||||
|
||||
Use this method to run an instance with the latest code. This is only recommended for development purposes. The minimum go version required is 1.19. To build and run a local instance with demo users:
|
||||
Use this method to run an instance with the latest code. This is only recommended for development purposes. The minimum go version required is 1.19. Note that you need as prerequisite a C compile environment installed because some dependences like reva have components that require c-go libraries/tool-chains. The command installing for debian based systems is: `sudo apt install build-essentials`. To build and run a local instance with demo users:
|
||||
|
||||
```console
|
||||
# get the source
|
||||
|
||||
@@ -8,3 +8,4 @@ https://github.com/owncloud/ocis/pull/5310
|
||||
https://github.com/owncloud/ocis/pull/5404
|
||||
https://github.com/owncloud/ocis/pull/5460
|
||||
https://github.com/owncloud/ocis/pull/5613
|
||||
https://github.com/owncloud/ocis/pull/5714
|
||||
|
||||
2
go.mod
2
go.mod
@@ -11,7 +11,7 @@ require (
|
||||
github.com/blevesearch/bleve/v2 v2.3.5
|
||||
github.com/coreos/go-oidc/v3 v3.4.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20221012090518-ef2996678965
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230301100432-f65cdbafbe3e
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230303141425-83ae3a7e5333
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/ggwhite/go-masker v1.0.9
|
||||
github.com/go-chi/chi/v5 v5.0.7
|
||||
|
||||
6
go.sum
6
go.sum
@@ -344,10 +344,8 @@ github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3p
|
||||
github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
|
||||
github.com/crewjam/saml v0.4.9 h1:X2jDv4dv3IvfT9t+RhADavzNFAcq3fVxzTCIH3G605U=
|
||||
github.com/crewjam/saml v0.4.9/go.mod h1:9Zh6dWPtB3MSzTRt8fIFH60Z351QQ+s7hCU3J/tTlA4=
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230222151731-83c7b4d26b2b h1:wIwnuSyH8tM4dbr16UYEoYF7ESlfxah2q99oz/FscU0=
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230222151731-83c7b4d26b2b/go.mod h1:dbaNP2U3nGQA5BHLc5w/hqviq7b0F4eygNwC38jeaiU=
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230301100432-f65cdbafbe3e h1:FMxx/Mr+3HVY9CuTPRI55AGExCRamjMTZlum1ckBBm4=
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230301100432-f65cdbafbe3e/go.mod h1:dbaNP2U3nGQA5BHLc5w/hqviq7b0F4eygNwC38jeaiU=
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230303141425-83ae3a7e5333 h1:1z2AmAGfAgIqCE09CIQFpUhMXwG38PlqVYZqKbrxSXQ=
|
||||
github.com/cs3org/reva/v2 v2.12.1-0.20230303141425-83ae3a7e5333/go.mod h1:dbaNP2U3nGQA5BHLc5w/hqviq7b0F4eygNwC38jeaiU=
|
||||
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=
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
FROM arm32v6/alpine:3.17
|
||||
|
||||
ARG VERSION=""
|
||||
ARG REVISION=""
|
||||
|
||||
RUN apk add --no-cache ca-certificates mailcap tree attr curl && \
|
||||
echo 'hosts: files dns' >| /etc/nsswitch.conf
|
||||
|
||||
LABEL maintainer="ownCloud GmbH <devops@owncloud.com>" \
|
||||
org.opencontainers.image.title="ownCloud Infinite Scale" \
|
||||
org.opencontainers.image.vendor="ownCloud GmbH" \
|
||||
org.opencontainers.image.authors="ownCloud GmbH" \
|
||||
org.opencontainers.image.description="oCIS - ownCloud Infinite Scale is a modern file-sync and share platform" \
|
||||
org.opencontainers.image.licenses="Apache-2.0" \
|
||||
org.opencontainers.image.documentation="https://github.com/owncloud/ocis" \
|
||||
org.opencontainers.image.url="https://hub.docker.com/r/owncloud/ocis" \
|
||||
org.opencontainers.image.source="https://github.com/owncloud/ocis" \
|
||||
org.opencontainers.image.version="${VERSION}" \
|
||||
org.opencontainers.image.revision="${REVISION}"
|
||||
|
||||
RUN addgroup -g 1000 -S ocis-group && \
|
||||
adduser -S --ingroup ocis-group --uid 1000 ocis-user --home /var/lib/ocis
|
||||
|
||||
RUN mkdir -p /var/lib/ocis && \
|
||||
chown -R ocis-user:ocis-group /var/lib/ocis && \
|
||||
chmod -R 751 /var/lib/ocis && \
|
||||
mkdir -p /etc/ocis && \
|
||||
chown -R ocis-user:ocis-group /etc/ocis && \
|
||||
chmod -R 751 /etc/ocis
|
||||
|
||||
VOLUME [ "/var/lib/ocis", "/etc/ocis" ]
|
||||
WORKDIR /var/lib/ocis
|
||||
|
||||
USER 1000
|
||||
|
||||
EXPOSE 9200/tcp
|
||||
|
||||
ENTRYPOINT ["/usr/bin/ocis"]
|
||||
CMD ["server"]
|
||||
|
||||
COPY dist/binaries/ocis-linux-arm /usr/bin/ocis
|
||||
@@ -15,8 +15,3 @@ manifests:
|
||||
architecture: arm64
|
||||
variant: v8
|
||||
os: linux
|
||||
- image: owncloud/ocis:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
||||
platform:
|
||||
architecture: arm
|
||||
variant: v6
|
||||
os: linux
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
# Graph service
|
||||
|
||||
The graph service provides the Graph API which is a RESTful web API used to access Infinite Scale resources. It is inspired by the [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/use-the-api) and can be used by clients or other services or extensions.
|
||||
|
||||
## Manual Filters
|
||||
|
||||
Using the API, you can manually filter like for users. See the [Libre Graph API](https://owncloud.dev/libre-graph-api/#/users/ListUsers) for examples in the [developer documentation](https://owncloud.dev). Note that you can use `and` and `or` to refine results.
|
||||
|
||||
## Sequence Diagram
|
||||
|
||||
The following image gives an overview of the scenario when a client requests to list available spaces the user has access to. To do so, the client is directed with his request automatically via the proxy service to the graph service.
|
||||
|
||||
<!-- referencing: https://github.com/owncloud/ocis/pull/3816 ([docs-only] add client protocol overview) -->
|
||||
|
||||
<img src="./images/mermaid-graph.svg" width="500" />
|
||||
|
||||
1
services/graph/images/mermaid-graph.svg
Normal file
1
services/graph/images/mermaid-graph.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 28 KiB |
@@ -50,6 +50,12 @@ func (g Graph) applyFilterLogical(ctx context.Context, req *godata.GoDataRequest
|
||||
return users, invalidFilterError()
|
||||
}
|
||||
return g.applyFilterLogicalAnd(ctx, req, root.Children[0], root.Children[1])
|
||||
case "or":
|
||||
// 'or' needs 2 operands
|
||||
if len(root.Children) != 2 {
|
||||
return users, invalidFilterError()
|
||||
}
|
||||
return g.applyFilterLogicalOr(ctx, req, root.Children[0], root.Children[1])
|
||||
}
|
||||
logger.Debug().Str("Token", root.Token.Value).Msg("unsupported logical filter")
|
||||
return users, unsupportedFilterError()
|
||||
@@ -109,6 +115,32 @@ func (g Graph) applyFilterLogicalAnd(ctx context.Context, req *godata.GoDataRequ
|
||||
return filteredUsers, nil
|
||||
}
|
||||
|
||||
func (g Graph) applyFilterLogicalOr(ctx context.Context, req *godata.GoDataRequest, operand1 *godata.ParseNode, operand2 *godata.ParseNode) (users []*libregraph.User, err error) {
|
||||
// logger := g.logger.SubloggerWithRequestID(ctx)
|
||||
var res1, res2 []*libregraph.User
|
||||
|
||||
res1, err = g.applyUserFilter(ctx, req, operand1)
|
||||
if err != nil {
|
||||
return []*libregraph.User{}, err
|
||||
}
|
||||
|
||||
res2, err = g.applyUserFilter(ctx, req, operand2)
|
||||
if err != nil {
|
||||
return []*libregraph.User{}, err
|
||||
}
|
||||
|
||||
// We now have two slices with results of the subfilters. Now turn one of them
|
||||
// into a map for efficiently getting the union of both slices
|
||||
userSet := userSliceToMap(res1)
|
||||
filteredUsers := make([]*libregraph.User, 0, len(res1)+len(res2))
|
||||
filteredUsers = append(filteredUsers, res1...)
|
||||
for _, user := range res2 {
|
||||
if _, found := userSet[user.GetId()]; !found {
|
||||
filteredUsers = append(filteredUsers, user)
|
||||
}
|
||||
}
|
||||
return filteredUsers, nil
|
||||
}
|
||||
func (g Graph) applyFilterLambda(ctx context.Context, req *godata.GoDataRequest, nodes []*godata.ParseNode) (users []*libregraph.User, err error) {
|
||||
logger := g.logger.SubloggerWithRequestID(ctx)
|
||||
if len(nodes) != 2 {
|
||||
|
||||
@@ -378,9 +378,12 @@ var _ = Describe("Users", func() {
|
||||
Entry("with memberOf lambda filter with UUID", "memberOf/any(n:n/id eq 25cb7bc0-3168-4a0c-adbe-396f478ad494)", http.StatusOK),
|
||||
Entry("with memberOf lambda filter with UUID string", "memberOf/any(n:n/id eq '25cb7bc0-3168-4a0c-adbe-396f478ad494')", http.StatusOK),
|
||||
Entry("with appRoleAssignments lambda filter with appRoleId", "appRoleAssignments/any(n:n/appRoleId eq 'some-appRole-ID')", http.StatusOK),
|
||||
Entry("with two memberOf lambda filters",
|
||||
Entry("with two memberOf lambda filters combined with and",
|
||||
"memberOf/any(n:n/id eq 25cb7bc0-3168-4a0c-adbe-396f478ad494) and memberOf/any(n:n/id eq 2713f1d5-6822-42bd-ad56-9f6c55a3a8fa)",
|
||||
http.StatusOK),
|
||||
Entry("with two memberOf lambda filters combined with or",
|
||||
"memberOf/any(n:n/id eq 25cb7bc0-3168-4a0c-adbe-396f478ad494) or memberOf/any(n:n/id eq 2713f1d5-6822-42bd-ad56-9f6c55a3a8fa)",
|
||||
http.StatusOK),
|
||||
Entry("with supported appRoleAssignments lambda filter property",
|
||||
"appRoleAssignments/any(n:n/appRoleId eq 'some-appRoleAssignment-ID') and memberOf/any(n:n/id eq 2713f1d5-6822-42bd-ad56-9f6c55a3a8fa)",
|
||||
http.StatusOK),
|
||||
|
||||
@@ -31,3 +31,17 @@ Feature: assign role
|
||||
| Space Admin | 401 |
|
||||
| User | 401 |
|
||||
| Guest | 401 |
|
||||
|
||||
|
||||
Scenario Outline: assign role to the user with setting api and list role with graph api
|
||||
Given user "Alice" has been created with default attributes and without skeleton files
|
||||
And the administrator has given "Alice" the role "<userRole>" using the settings api
|
||||
When the administrator retrieves the assigned role of user "Alice" using the Graph API
|
||||
Then the HTTP status code should be "200"
|
||||
And the Graph API response should have the role "<userRole>"
|
||||
Examples:
|
||||
| userRole |
|
||||
| Admin |
|
||||
| Space Admin |
|
||||
| User |
|
||||
| Guest |
|
||||
|
||||
@@ -1727,20 +1727,7 @@ class GraphContext implements Context {
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id') ?? $user;
|
||||
|
||||
if (empty($this->appEntity)) {
|
||||
$applicationEntity = (
|
||||
$this->featureContext->getJsonDecodedResponse(
|
||||
GraphHelper::getApplications(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$this->featureContext->getAdminPassword(),
|
||||
)
|
||||
)
|
||||
)['value'][0];
|
||||
$this->appEntity["id"] = $applicationEntity["id"];
|
||||
foreach ($applicationEntity["appRoles"] as $value) {
|
||||
$this->appEntity["appRoles"][$value['displayName']] = $value['id'];
|
||||
}
|
||||
$this->setApplicationEntity();
|
||||
}
|
||||
|
||||
$response = GraphHelper::assignRole(
|
||||
@@ -1782,6 +1769,29 @@ class GraphContext implements Context {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* set application Entity in global variable
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function setApplicationEntity(): void {
|
||||
$applicationEntity = (
|
||||
$this->featureContext->getJsonDecodedResponse(
|
||||
GraphHelper::getApplications(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$this->featureContext->getAdminPassword(),
|
||||
)
|
||||
)
|
||||
)['value'][0];
|
||||
$this->appEntity["id"] = $applicationEntity["id"];
|
||||
foreach ($applicationEntity["appRoles"] as $value) {
|
||||
$this->appEntity["appRoles"][$value['displayName']] = $value['id'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the Graph API response should have the role "([^"]*)"$/
|
||||
*
|
||||
@@ -1789,9 +1799,13 @@ class GraphContext implements Context {
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theGraphApiResponseShouldHaveTheRole(string $role): void {
|
||||
$response = $this->featureContext->getJsonDecodedResponse($this->featureContext->getResponse())['value'][0];
|
||||
if (empty($this->appEntity)) {
|
||||
$this->setApplicationEntity();
|
||||
}
|
||||
Assert::assertEquals(
|
||||
$this->appEntity["appRoles"][$role],
|
||||
$response['appRoleId'],
|
||||
|
||||
Reference in New Issue
Block a user