mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-03-04 07:17:16 -05:00
Merge branch 'master' into config-housekeeping-proxy
This commit is contained in:
@@ -7,8 +7,12 @@ exclude_paths:
|
||||
- 'docs/**'
|
||||
- '**/docs/**'
|
||||
- '**/pkg/proto/**'
|
||||
- 'konnectd/assets/identifier/**'
|
||||
- 'konnectd/ui_config/**'
|
||||
- 'konnectd/scripts/**'
|
||||
- 'settings/rollup.config.js'
|
||||
- 'accounts/rollup.config.js'
|
||||
- 'ocis/docker/eos-ocis/Dockerfile'
|
||||
- 'ocis/docker/eos-ocis-dev/Dockerfile'
|
||||
- 'deployments/**'
|
||||
|
||||
...
|
||||
...
|
||||
|
||||
338
.drone.star
338
.drone.star
@@ -15,12 +15,12 @@ config = {
|
||||
},
|
||||
'apiTests': {
|
||||
'coreBranch': 'master',
|
||||
'coreCommit': '35c53c096f40dd15ae15940c589965379e921857',
|
||||
'numberOfParts': 4
|
||||
'coreCommit': '6e5e252dcd18448709006cb2de6fe86cb6d0ecec',
|
||||
'numberOfParts': 6
|
||||
},
|
||||
'uiTests': {
|
||||
'phoenixBranch': 'master',
|
||||
'phoenixCommit': '42c2a372aceb31eb17e13ebae08e2e25e2447dfe',
|
||||
'phoenixCommit': '492e6a663efad67f770ba4ac405c4d9983d00cd3',
|
||||
'suites': {
|
||||
'phoenixWebUI1': [
|
||||
'webUICreateFilesFolders',
|
||||
@@ -38,12 +38,12 @@ config = {
|
||||
'webUIRenameFiles',
|
||||
'webUIRenameFolders',
|
||||
],
|
||||
'phoenixWebUI4': [
|
||||
'phoenixWebUI4': [
|
||||
'webUITrashbin',
|
||||
'webUIUpload',
|
||||
# All tests in the following suites are skipped currently
|
||||
# so they won't run now but when they are enabled they will run
|
||||
'webUIRestrictSharing',
|
||||
],
|
||||
'phoenixWebUI5': [
|
||||
'webUISharingAutocompletion',
|
||||
'webUISharingInternalGroups',
|
||||
'webUISharingInternalUsers',
|
||||
@@ -51,17 +51,27 @@ config = {
|
||||
'webUISharingFilePermissionsGroups',
|
||||
'webUISharingFolderPermissionsGroups',
|
||||
'webUISharingFolderAdvancedPermissionsGroups',
|
||||
],
|
||||
'phoenixWebUI6': [
|
||||
'webUIResharing',
|
||||
'webUISharingPublic',
|
||||
'webUISharingPublicDifferentRoles',
|
||||
'webUISharingAcceptShares',
|
||||
'webUISharingFilePermissionMultipleUsers',
|
||||
'webUISharingFolderPermissionMultipleUsers',
|
||||
'webUISharingFolderAdvancedPermissionMultipleUsers',
|
||||
'webUISharingNotifications',
|
||||
],
|
||||
'phoenixWebUI7': [
|
||||
'webUISharingFilePermissionMultipleUsers',
|
||||
],
|
||||
'phoenixWebUI8': [
|
||||
'webUISharingFolderPermissionMultipleUsers',
|
||||
'webUISharingFolderAdvancedPermissionMultipleUsers',
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
'rocketchat': {
|
||||
'channel': 'ocis-internal',
|
||||
'from_secret': 'private_rocketchat',
|
||||
},
|
||||
}
|
||||
def getTestSuiteNames():
|
||||
keys = config['modules'].keys()
|
||||
@@ -84,13 +94,11 @@ def getCoreApiTestPipelineNames():
|
||||
return names
|
||||
|
||||
def getDependsOnAllTestPipelines(ctx):
|
||||
dependencies = getTestSuiteNames() + [ 'upload-coverage' ]
|
||||
if ctx.build.ref != "refs/heads/master":
|
||||
dependencies = getTestSuiteNames() + [
|
||||
'upload-coverage',
|
||||
'localApiTests-owncloud-storage',
|
||||
'localApiTests-ocis-storage',
|
||||
] + getCoreApiTestPipelineNames() + getUITestSuiteNames()
|
||||
dependencies = getTestSuiteNames() + [
|
||||
'upload-coverage',
|
||||
'localApiTests-owncloud-storage',
|
||||
'localApiTests-ocis-storage',
|
||||
] + getCoreApiTestPipelineNames() + getUITestSuiteNames() + ['accountsUITests']
|
||||
|
||||
return dependencies
|
||||
|
||||
@@ -102,6 +110,7 @@ def main(ctx):
|
||||
docker(ctx, 'amd64'),
|
||||
docker(ctx, 'arm64'),
|
||||
docker(ctx, 'arm'),
|
||||
dockerEos(ctx),
|
||||
binary(ctx, 'linux'),
|
||||
binary(ctx, 'darwin'),
|
||||
binary(ctx, 'windows'),
|
||||
@@ -114,12 +123,18 @@ def main(ctx):
|
||||
readme(ctx),
|
||||
badges(ctx),
|
||||
docs(ctx),
|
||||
updateDeployment(ctx)
|
||||
updateDeployment(ctx),
|
||||
notify(ctx),
|
||||
]
|
||||
|
||||
if '[docs-only]' in ctx.build.title:
|
||||
pipelines = docs(ctx)
|
||||
pipelines['depends_on'] = []
|
||||
if '[docs-only]' in (ctx.build.title + ctx.build.message):
|
||||
doc_pipelines = docs(ctx)
|
||||
doc_pipelines['depends_on'] = []
|
||||
|
||||
notify_pipelines = notify(ctx)
|
||||
notify_pipelines['depends_on'] = ['docs']
|
||||
|
||||
pipelines = [ doc_pipelines, notify_pipelines ]
|
||||
else:
|
||||
pipelines = before + stages + after
|
||||
|
||||
@@ -142,13 +157,14 @@ def testPipelines(ctx):
|
||||
pipelines.append(coreApiTests(ctx, config['apiTests']['coreBranch'], config['apiTests']['coreCommit'], runPart, config['apiTests']['numberOfParts'], 'ocis'))
|
||||
|
||||
pipelines += uiTests(ctx, config['uiTests']['phoenixBranch'], config['uiTests']['phoenixCommit'])
|
||||
pipelines.append(accountsUITests(ctx, config['uiTests']['phoenixBranch'], config['uiTests']['phoenixCommit']))
|
||||
return pipelines
|
||||
|
||||
def testing(ctx, module):
|
||||
steps = generate(module) + [
|
||||
{
|
||||
'name': 'vet',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd %s' % (module),
|
||||
@@ -163,7 +179,7 @@ def testing(ctx, module):
|
||||
},
|
||||
{
|
||||
'name': 'staticcheck',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd %s' % (module),
|
||||
@@ -178,7 +194,7 @@ def testing(ctx, module):
|
||||
},
|
||||
{
|
||||
'name': 'lint',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd %s' % (module),
|
||||
@@ -193,7 +209,7 @@ def testing(ctx, module):
|
||||
},
|
||||
{
|
||||
'name': 'test',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd %s' % (module),
|
||||
@@ -292,9 +308,9 @@ def uploadCoverage(ctx):
|
||||
'SONAR_TOKEN': {
|
||||
'from_secret': 'sonar_token',
|
||||
},
|
||||
'SONAR_PULL_REQUEST_BASE': 'master' if ctx.build.event == 'pull_request' else None,
|
||||
'SONAR_PULL_REQUEST_BRANCH': ctx.build.source if ctx.build.event == 'pull_request' else None,
|
||||
'SONAR_PULL_REQUEST_KEY': ctx.build.ref.replace("refs/pull/", "").split("/")[0] if ctx.build.event == 'pull_request' else None,
|
||||
'SONAR_PULL_REQUEST_BASE': '%s' % ('master' if ctx.build.event == 'pull_request' else None),
|
||||
'SONAR_PULL_REQUEST_BRANCH': '%s' % (ctx.build.source if ctx.build.event == 'pull_request' else None),
|
||||
'SONAR_PULL_REQUEST_KEY': '%s' % (ctx.build.ref.replace("refs/pull/", "").split("/")[0] if ctx.build.event == 'pull_request' else None),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -336,13 +352,14 @@ def localApiTests(ctx, coreBranch = 'master', coreCommit = '', storage = 'ownclo
|
||||
cloneCoreRepos(coreBranch, coreCommit) + [
|
||||
{
|
||||
'name': 'localApiTests-%s-storage' % (storage),
|
||||
'image': 'owncloudci/php:7.2',
|
||||
'image': 'owncloudci/php:7.4',
|
||||
'pull': 'always',
|
||||
'environment' : {
|
||||
'TEST_SERVER_URL': 'https://ocis-server:9200',
|
||||
'OCIS_REVA_DATA_ROOT': '%s' % ('/srv/app/tmp/ocis/owncloud/' if storage == 'owncloud' else ''),
|
||||
'DELETE_USER_DATA_CMD': '%s' % ('rm -rf /srv/app/tmp/ocis/owncloud/data/*' if storage == 'owncloud' else 'rm -rf /srv/app/tmp/ocis/storage/users/nodes/root/*'),
|
||||
'OCIS_REVA_DATA_ROOT': '%s' % ('/srv/app/tmp/ocis/owncloud/data/' if storage == 'owncloud' else ''),
|
||||
'DELETE_USER_DATA_CMD': '%s' % ('' if storage == 'owncloud' else 'rm -rf /srv/app/tmp/ocis/storage/users/nodes/root/* /srv/app/tmp/ocis/storage/users/nodes/*-*-*-*'),
|
||||
'SKELETON_DIR': '/srv/app/tmp/testing/data/apiSkeleton',
|
||||
'OCIS_SKELETON_STRATEGY': '%s' % ('copy' if storage == 'owncloud' else 'upload'),
|
||||
'TEST_OCIS':'true',
|
||||
'BEHAT_FILTER_TAGS': '~@skipOnOcis-%s-Storage' % ('OC' if storage == 'owncloud' else 'OCIS'),
|
||||
'PATH_TO_CORE': '/srv/app/testrunner'
|
||||
@@ -367,6 +384,7 @@ def localApiTests(ctx, coreBranch = 'master', coreCommit = '', storage = 'ownclo
|
||||
],
|
||||
'trigger': {
|
||||
'ref': [
|
||||
'refs/heads/master',
|
||||
'refs/tags/v*',
|
||||
'refs/pull/**',
|
||||
],
|
||||
@@ -389,13 +407,14 @@ def coreApiTests(ctx, coreBranch = 'master', coreCommit = '', part_number = 1, n
|
||||
cloneCoreRepos(coreBranch, coreCommit) + [
|
||||
{
|
||||
'name': 'oC10ApiTests-%s-storage-%s' % (storage, part_number),
|
||||
'image': 'owncloudci/php:7.2',
|
||||
'image': 'owncloudci/php:7.4',
|
||||
'pull': 'always',
|
||||
'environment' : {
|
||||
'TEST_SERVER_URL': 'https://ocis-server:9200',
|
||||
'OCIS_REVA_DATA_ROOT': '%s' % ('/srv/app/tmp/ocis/owncloud/' if storage == 'owncloud' else ''),
|
||||
'DELETE_USER_DATA_CMD': '%s' % ('rm -rf /srv/app/tmp/ocis/owncloud/*' if storage == 'owncloud' else 'rm -rf /srv/app/tmp/ocis/storage/users/nodes/root/*'),
|
||||
'OCIS_REVA_DATA_ROOT': '%s' % ('/srv/app/tmp/ocis/owncloud/data/' if storage == 'owncloud' else ''),
|
||||
'DELETE_USER_DATA_CMD': '%s' % ('' if storage == 'owncloud' else 'rm -rf /srv/app/tmp/ocis/storage/users/nodes/root/* /srv/app/tmp/ocis/storage/users/nodes/*-*-*-*'),
|
||||
'SKELETON_DIR': '/srv/app/tmp/testing/data/apiSkeleton',
|
||||
'OCIS_SKELETON_STRATEGY': '%s' % ('copy' if storage == 'owncloud' else 'upload'),
|
||||
'TEST_OCIS':'true',
|
||||
'BEHAT_FILTER_TAGS': '~@notToImplementOnOCIS&&~@toImplementOnOCIS&&~comments-app-required&&~@federation-app-required&&~@notifications-app-required&&~systemtags-app-required&&~@local_storage&&~@skipOnOcis-%s-Storage' % ('OC' if storage == 'owncloud' else 'OCIS'),
|
||||
'DIVIDE_INTO_NUM_PARTS': number_of_parts,
|
||||
@@ -422,6 +441,7 @@ def coreApiTests(ctx, coreBranch = 'master', coreCommit = '', part_number = 1, n
|
||||
],
|
||||
'trigger': {
|
||||
'ref': [
|
||||
'refs/heads/master',
|
||||
'refs/tags/v*',
|
||||
'refs/pull/**',
|
||||
],
|
||||
@@ -458,7 +478,7 @@ def uiTestPipeline(suiteName, phoenixBranch = 'master', phoenixCommit = '', stor
|
||||
'SERVER_HOST': 'https://ocis-server:9200',
|
||||
'BACKEND_HOST': 'https://ocis-server:9200',
|
||||
'RUN_ON_OCIS': 'true',
|
||||
'OCIS_REVA_DATA_ROOT': '/srv/app/tmp/ocis/owncloud',
|
||||
'OCIS_REVA_DATA_ROOT': '/srv/app/tmp/ocis/owncloud/data',
|
||||
'OCIS_SKELETON_DIR': '/srv/app/testing/data/webUISkeleton',
|
||||
'PHOENIX_CONFIG': '/drone/src/ocis/tests/config/drone/ocis-config.json',
|
||||
'TEST_TAGS': 'not @skipOnOCIS and not @skip',
|
||||
@@ -502,6 +522,100 @@ def uiTestPipeline(suiteName, phoenixBranch = 'master', phoenixCommit = '', stor
|
||||
],
|
||||
'trigger': {
|
||||
'ref': [
|
||||
'refs/heads/master',
|
||||
'refs/tags/v*',
|
||||
'refs/pull/**',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
def accountsUITests(ctx, phoenixBranch, phoenixCommit, storage = 'owncloud'):
|
||||
return {
|
||||
'kind': 'pipeline',
|
||||
'type': 'docker',
|
||||
'name': 'accountsUITests',
|
||||
'platform': {
|
||||
'os': 'linux',
|
||||
'arch': 'amd64',
|
||||
},
|
||||
'steps':
|
||||
generate('ocis') +
|
||||
build() +
|
||||
ocisServer(storage) + [
|
||||
{
|
||||
'name': 'WebUIAcceptanceTests',
|
||||
'image': 'owncloudci/nodejs:11',
|
||||
'pull': 'always',
|
||||
'environment': {
|
||||
'SERVER_HOST': 'https://ocis-server:9200',
|
||||
'BACKEND_HOST': 'https://ocis-server:9200',
|
||||
'RUN_ON_OCIS': 'true',
|
||||
'OCIS_REVA_DATA_ROOT': '/srv/app/tmp/ocis/owncloud/data',
|
||||
'OCIS_SKELETON_DIR': '/srv/app/testing/data/webUISkeleton',
|
||||
'PHOENIX_CONFIG': '/drone/src/ocis/tests/config/drone/ocis-config.json',
|
||||
'TEST_TAGS': 'not @skipOnOCIS and not @skip',
|
||||
'LOCAL_UPLOAD_DIR': '/uploads',
|
||||
'NODE_TLS_REJECT_UNAUTHORIZED': 0,
|
||||
'PHOENIX_PATH': '/srv/app/phoenix',
|
||||
'FEATURE_PATH': '/drone/src/accounts/ui/tests/acceptance/features',
|
||||
},
|
||||
'commands': [
|
||||
'git clone -b master --depth=1 https://github.com/owncloud/testing.git /srv/app/testing',
|
||||
'git clone -b %s --single-branch --no-tags https://github.com/owncloud/phoenix.git /srv/app/phoenix' % (phoenixBranch),
|
||||
'cp -r /srv/app/phoenix/tests/acceptance/filesForUpload/* /uploads',
|
||||
'cd /srv/app/phoenix',
|
||||
] + ([
|
||||
'git checkout %s' % (phoenixCommit)
|
||||
] if phoenixCommit != '' else []) + [
|
||||
'yarn install-all',
|
||||
'cd /drone/src/accounts',
|
||||
'yarn install --all',
|
||||
'make test-acceptance-webui'
|
||||
],
|
||||
'volumes': [{
|
||||
'name': 'gopath',
|
||||
'path': '/srv/app',
|
||||
},
|
||||
{
|
||||
'name': 'uploads',
|
||||
'path': '/uploads'
|
||||
}],
|
||||
},
|
||||
],
|
||||
'services': [
|
||||
{
|
||||
'name': 'redis',
|
||||
'image': 'webhippie/redis',
|
||||
'pull': 'always',
|
||||
'environment': {
|
||||
'REDIS_DATABASES': 1
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'selenium',
|
||||
'image': 'selenium/standalone-chrome-debug:3.141.59-20200326',
|
||||
'pull': 'always',
|
||||
'volumes': [
|
||||
{
|
||||
'name': 'uploads',
|
||||
'path': '/uploads'
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
'volumes': [
|
||||
{
|
||||
'name': 'gopath',
|
||||
'temp': {},
|
||||
},
|
||||
{
|
||||
'name': 'uploads',
|
||||
'temp': {}
|
||||
}
|
||||
],
|
||||
'trigger': {
|
||||
'ref': [
|
||||
'refs/heads/master',
|
||||
'refs/tags/v*',
|
||||
'refs/pull/**',
|
||||
],
|
||||
@@ -581,6 +695,78 @@ def docker(ctx, arch):
|
||||
},
|
||||
}
|
||||
|
||||
def dockerEos(ctx):
|
||||
return {
|
||||
'kind': 'pipeline',
|
||||
'type': 'docker',
|
||||
'name': 'docker-eos-ocis',
|
||||
'platform': {
|
||||
'os': 'linux',
|
||||
'arch': 'amd64',
|
||||
},
|
||||
'steps':
|
||||
generate('ocis') +
|
||||
build() + [
|
||||
{
|
||||
'name': 'dryrun-eos-ocis',
|
||||
'image': 'plugins/docker:18.09',
|
||||
'pull': 'always',
|
||||
'settings': {
|
||||
'dry_run': True,
|
||||
'context': 'ocis/docker/eos-ocis',
|
||||
'tags': 'linux-eos-ocis',
|
||||
'dockerfile': 'ocis/docker/eos-ocis/Dockerfile',
|
||||
'repo': 'owncloud/eos-ocis',
|
||||
},
|
||||
'when': {
|
||||
'ref': {
|
||||
'include': [
|
||||
'refs/pull/**',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'docker-eos-ocis',
|
||||
'image': 'plugins/docker:18.09',
|
||||
'pull': 'always',
|
||||
'settings': {
|
||||
'username': {
|
||||
'from_secret': 'docker_username',
|
||||
},
|
||||
'password': {
|
||||
'from_secret': 'docker_password',
|
||||
},
|
||||
'auto_tag': True,
|
||||
'context': 'ocis/docker/eos-ocis',
|
||||
'dockerfile': 'ocis/docker/eos-ocis/Dockerfile',
|
||||
'repo': 'owncloud/eos-ocis',
|
||||
},
|
||||
'when': {
|
||||
'ref': {
|
||||
'exclude': [
|
||||
'refs/pull/**',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
'volumes': [
|
||||
{
|
||||
'name': 'gopath',
|
||||
'temp': {},
|
||||
},
|
||||
],
|
||||
'depends_on': getDependsOnAllTestPipelines(ctx),
|
||||
'trigger': {
|
||||
'ref': [
|
||||
'refs/heads/master',
|
||||
'refs/tags/v*',
|
||||
'refs/pull/**',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
def binary(ctx, name):
|
||||
if ctx.build.event == "tag":
|
||||
settings = {
|
||||
@@ -633,7 +819,7 @@ def binary(ctx, name):
|
||||
generate('ocis') + [
|
||||
{
|
||||
'name': 'build',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd ocis',
|
||||
@@ -648,7 +834,7 @@ def binary(ctx, name):
|
||||
},
|
||||
{
|
||||
'name': 'finish',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd ocis',
|
||||
@@ -684,8 +870,7 @@ def binary(ctx, name):
|
||||
'image': 'toolhippie/calens:latest',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd ocis',
|
||||
'calens --version %s -o dist/CHANGELOG.md' % ctx.build.ref.replace("refs/tags/v", "").split("-")[0],
|
||||
'calens --version %s -o ocis/dist/CHANGELOG.md' % ctx.build.ref.replace("refs/tags/v", "").split("-")[0],
|
||||
],
|
||||
'when': {
|
||||
'ref': [
|
||||
@@ -814,6 +999,7 @@ def manifest(ctx):
|
||||
'docker-amd64',
|
||||
'docker-arm64',
|
||||
'docker-arm',
|
||||
'docker-eos-ocis',
|
||||
'binaries-linux',
|
||||
'binaries-darwin',
|
||||
'binaries-windows',
|
||||
@@ -838,7 +1024,7 @@ def changelog(ctx):
|
||||
'steps': [
|
||||
{
|
||||
'name': 'generate',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd ocis',
|
||||
@@ -968,6 +1154,7 @@ def badges(ctx):
|
||||
'docker-amd64',
|
||||
'docker-arm64',
|
||||
'docker-arm',
|
||||
'docker-eos-ocis',
|
||||
],
|
||||
'trigger': {
|
||||
'ref': [
|
||||
@@ -1001,7 +1188,7 @@ def docs(ctx):
|
||||
},
|
||||
{
|
||||
'name': 'generate-config-docs',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'commands': generateConfigDocs,
|
||||
'volumes': [
|
||||
{
|
||||
@@ -1089,7 +1276,7 @@ def generate(module):
|
||||
return [
|
||||
{
|
||||
'name': 'generate',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd %s' % (module),
|
||||
@@ -1144,6 +1331,42 @@ def updateDeployment(ctx):
|
||||
}
|
||||
}
|
||||
|
||||
def notify(ctx):
|
||||
return {
|
||||
'kind': 'pipeline',
|
||||
'type': 'docker',
|
||||
'name': 'chat-notifications',
|
||||
'clone': {
|
||||
'disable': True
|
||||
},
|
||||
'steps': [
|
||||
{
|
||||
'name': 'notify-rocketchat',
|
||||
'image': 'plugins/slack:1',
|
||||
'pull': 'always',
|
||||
'settings': {
|
||||
'webhook': {
|
||||
'from_secret': config['rocketchat']['from_secret']
|
||||
},
|
||||
'channel': config['rocketchat']['channel']
|
||||
},
|
||||
'when': {
|
||||
'status': [
|
||||
'failure',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
'depends_on': [],
|
||||
'trigger': {
|
||||
'ref': [
|
||||
'refs/heads/master',
|
||||
'refs/heads/release*',
|
||||
'refs/tags/**',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
def frontend(module):
|
||||
return [
|
||||
{
|
||||
@@ -1164,32 +1387,29 @@ def ocisServer(storage):
|
||||
return [
|
||||
{
|
||||
'name': 'ocis-server',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'detach': True,
|
||||
'environment' : {
|
||||
#'OCIS_LOG_LEVEL': 'debug',
|
||||
'STORAGE_STORAGE_HOME_DRIVER': '%s' % (storage),
|
||||
'STORAGE_STORAGE_HOME_DATA_DRIVER': '%s' % (storage),
|
||||
'STORAGE_STORAGE_OC_DRIVER': '%s' % (storage),
|
||||
'STORAGE_STORAGE_OC_DATA_DRIVER': '%s' % (storage),
|
||||
'STORAGE_STORAGE_HOME_DATA_TEMP_FOLDER': '/srv/app/tmp/',
|
||||
'STORAGE_STORAGE_OCIS_ROOT': '/srv/app/tmp/ocis/storage/users',
|
||||
'STORAGE_STORAGE_LOCAL_ROOT': '/srv/app/tmp/ocis/local/root',
|
||||
'STORAGE_STORAGE_OWNCLOUD_DATADIR': '/srv/app/tmp/ocis/owncloud/data',
|
||||
'STORAGE_STORAGE_OC_DATA_TEMP_FOLDER': '/srv/app/tmp/',
|
||||
'STORAGE_STORAGE_OWNCLOUD_REDIS_ADDR': 'redis:6379',
|
||||
'STORAGE_HOME_DRIVER': '%s' % (storage),
|
||||
'STORAGE_USERS_DRIVER': '%s' % (storage),
|
||||
'STORAGE_DRIVER_OCIS_ROOT': '/srv/app/tmp/ocis/storage/users',
|
||||
'STORAGE_DRIVER_LOCAL_ROOT': '/srv/app/tmp/ocis/local/root',
|
||||
'STORAGE_METADATA_ROOT': '/srv/app/tmp/ocis/metadata',
|
||||
'STORAGE_DRIVER_OWNCLOUD_DATADIR': '/srv/app/tmp/ocis/owncloud/data',
|
||||
'STORAGE_DRIVER_OWNCLOUD_REDIS_ADDR': 'redis:6379',
|
||||
'STORAGE_LDAP_IDP': 'https://ocis-server:9200',
|
||||
'STORAGE_OIDC_ISSUER': 'https://ocis-server:9200',
|
||||
'PROXY_OIDC_ISSUER': 'https://ocis-server:9200',
|
||||
'STORAGE_STORAGE_OC_DATA_SERVER_URL': 'http://ocis-server:9164/data',
|
||||
'STORAGE_DATAGATEWAY_URL': 'https://ocis-server:9200/data',
|
||||
'STORAGE_FRONTEND_URL': 'https://ocis-server:9200',
|
||||
'STORAGE_HOME_DATA_SERVER_URL': 'http://ocis-server:9155/data',
|
||||
'STORAGE_DATAGATEWAY_PUBLIC_URL': 'https://ocis-server:9200/data',
|
||||
'STORAGE_USERS_DATA_SERVER_URL': 'http://ocis-server:9158/data',
|
||||
'STORAGE_FRONTEND_PUBLIC_URL': 'https://ocis-server:9200',
|
||||
'PHOENIX_WEB_CONFIG': '/drone/src/ocis/tests/config/drone/ocis-config.json',
|
||||
'KONNECTD_IDENTIFIER_REGISTRATION_CONF': '/drone/src/ocis/tests/config/drone/identifier-registration.yml',
|
||||
'KONNECTD_ISS': 'https://ocis-server:9200',
|
||||
'KONNECTD_TLS': 'true',
|
||||
'ACCOUNTS_DATA_PATH': '/srv/app/tmp/ocis-accounts/',
|
||||
},
|
||||
'commands': [
|
||||
'apk add mailcap', # install /etc/mime.types
|
||||
@@ -1210,7 +1430,7 @@ def cloneCoreRepos(coreBranch, coreCommit):
|
||||
return [
|
||||
{
|
||||
'name': 'clone-core-repos',
|
||||
'image': 'owncloudci/php:7.2',
|
||||
'image': 'owncloudci/php:7.4',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'git clone -b master --depth=1 https://github.com/owncloud/testing.git /srv/app/tmp/testing',
|
||||
@@ -1255,7 +1475,7 @@ def build():
|
||||
return [
|
||||
{
|
||||
'name': 'build',
|
||||
'image': 'webhippie/golang:1.13',
|
||||
'image': 'webhippie/golang:1.14',
|
||||
'pull': 'always',
|
||||
'commands': [
|
||||
'cd ocis',
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -10,3 +10,8 @@ node_modules/
|
||||
*/assets
|
||||
|
||||
.idea
|
||||
|
||||
*/yarn-error.log
|
||||
|
||||
# Konnectd
|
||||
konnectd/assets/identifier
|
||||
240
CHANGELOG.md
240
CHANGELOG.md
@@ -4,10 +4,18 @@
|
||||
|
||||
* Bugfix - Add missing env vars to docker compose: [#392](https://github.com/owncloud/ocis/pull/392)
|
||||
* Bugfix - Don't enforce empty external apps slice: [#473](https://github.com/owncloud/ocis/pull/473)
|
||||
* Bugfix - Lower Bound was not working for the cs3 api index implementation: [#741](https://github.com/owncloud/ocis/pull/741)
|
||||
* Bugfix - Fix button layout after phoenix update: [#625](https://github.com/owncloud/ocis/pull/625)
|
||||
* Bugfix - Fix id or username query handling: [#745](https://github.com/owncloud/ocis/pull/745)
|
||||
* Bugfix - Use micro default client: [#718](https://github.com/owncloud/ocis/pull/718)
|
||||
* Bugfix - Allow consent-prompt with switch-account: [#788](https://github.com/owncloud/ocis/pull/788)
|
||||
* Bugfix - Mint token with uid and gid: [#737](https://github.com/owncloud/ocis/pull/737)
|
||||
* Bugfix - Don't create account if id/mail/username already taken: [#709](https://github.com/owncloud/ocis/pull/709)
|
||||
* Bugfix - Fix director selection in proxy: [#521](https://github.com/owncloud/ocis/pull/521)
|
||||
* Bugfix - Build docker images with alpine:latest instead of alpine:edge: [#416](https://github.com/owncloud/ocis/pull/416)
|
||||
* Change - Accounts UI shows message when no permissions: [#656](https://github.com/owncloud/ocis/pull/656)
|
||||
* Change - Filesystem based index: [#709](https://github.com/owncloud/ocis/pull/709)
|
||||
* Change - Rebuild index command for accounts: [#748](https://github.com/owncloud/ocis/pull/748)
|
||||
* Change - Add the thumbnails command: [#156](https://github.com/owncloud/ocis/issues/156)
|
||||
* Change - Choose disk or cs3 storage for accounts and groups: [#623](https://github.com/owncloud/ocis/pull/623)
|
||||
* Change - Integrate import command from ocis-migration: [#249](https://github.com/owncloud/ocis/pull/249)
|
||||
@@ -15,12 +23,22 @@
|
||||
* Change - Initial release of basic version: [#2](https://github.com/owncloud/ocis/issues/2)
|
||||
* Change - Add cli-commands to manage accounts: [#115](https://github.com/owncloud/product/issues/115)
|
||||
* Change - Start ocis-accounts with the ocis server command: [#25](https://github.com/owncloud/product/issues/25)
|
||||
* Change - Properly style konnectd consent page: [#754](https://github.com/owncloud/ocis/pull/754)
|
||||
* Change - Move the indexer package from ocis/accounts to ocis/ocis-pkg: [#794](https://github.com/owncloud/ocis/pull/794)
|
||||
* Change - Switch over to a new custom-built runtime: [#287](https://github.com/owncloud/ocis/pull/287)
|
||||
* Change - Remove username field in OCS: [#709](https://github.com/owncloud/ocis/pull/709)
|
||||
* Change - Account management permissions for Admin role: [#124](https://github.com/owncloud/product/issues/124)
|
||||
* Change - Update phoenix to v0.18.0: [#651](https://github.com/owncloud/ocis/pull/651)
|
||||
* Change - Default apps in ownCloud Web: [#688](https://github.com/owncloud/ocis/pull/688)
|
||||
* Change - Make ocis-settings available: [#287](https://github.com/owncloud/ocis/pull/287)
|
||||
* Change - Start ocis-proxy with the ocis server command: [#119](https://github.com/owncloud/ocis/issues/119)
|
||||
* Change - Bring oC theme: [#698](https://github.com/owncloud/ocis/pull/698)
|
||||
* Change - Update phoenix to v0.20.0: [#674](https://github.com/owncloud/ocis/pull/674)
|
||||
* Change - Update phoenix to v0.21.0: [#728](https://github.com/owncloud/ocis/pull/728)
|
||||
* Change - Update phoenix to v0.22.0: [#757](https://github.com/owncloud/ocis/pull/757)
|
||||
* Change - Update phoenix to v0.23.0: [#785](https://github.com/owncloud/ocis/pull/785)
|
||||
* Change - Update reva config: [#336](https://github.com/owncloud/ocis/pull/336)
|
||||
* Change - Clarify storage driver env vars: [#729](https://github.com/owncloud/ocis/pull/729)
|
||||
* Change - Settings and accounts appear in the user menu: [#656](https://github.com/owncloud/ocis/pull/656)
|
||||
* Enhancement - Add the accounts service: [#244](https://github.com/owncloud/product/issues/244)
|
||||
* Enhancement - Document how to run OCIS on top of EOS: [#172](https://github.com/owncloud/ocis/pull/172)
|
||||
@@ -39,6 +57,10 @@
|
||||
* Enhancement - Add glauth fallback backend: [#649](https://github.com/owncloud/ocis/pull/649)
|
||||
* Enhancement - Launch a storage to store ocis-metadata: [#602](https://github.com/owncloud/ocis/pull/602)
|
||||
* Enhancement - Simplify tracing config: [#92](https://github.com/owncloud/product/issues/92)
|
||||
* Enhancement - Update glauth to dev 4f029234b2308: [#786](https://github.com/owncloud/ocis/pull/786)
|
||||
* Enhancement - Update konnectd to v0.33.8: [#744](https://github.com/owncloud/ocis/pull/744)
|
||||
* Enhancement - Update reva to cdb3d6688da5: [#748](https://github.com/owncloud/ocis/pull/748)
|
||||
* Enhancement - Update reva to dd3a8c0f38: [#725](https://github.com/owncloud/ocis/pull/725)
|
||||
|
||||
## Details
|
||||
|
||||
@@ -60,6 +82,14 @@
|
||||
|
||||
https://github.com/owncloud/ocis/pull/473
|
||||
|
||||
* Bugfix - Lower Bound was not working for the cs3 api index implementation: [#741](https://github.com/owncloud/ocis/pull/741)
|
||||
|
||||
Tags: accounts
|
||||
|
||||
Lower bound working on the cs3 index implementation
|
||||
|
||||
https://github.com/owncloud/ocis/pull/741
|
||||
|
||||
* Bugfix - Fix button layout after phoenix update: [#625](https://github.com/owncloud/ocis/pull/625)
|
||||
|
||||
Tags: accounts
|
||||
@@ -70,6 +100,51 @@
|
||||
|
||||
https://github.com/owncloud/ocis/pull/625
|
||||
|
||||
* Bugfix - Fix id or username query handling: [#745](https://github.com/owncloud/ocis/pull/745)
|
||||
|
||||
Tags: accounts
|
||||
|
||||
The code was stopping execution when encountering an error while loading an account by id. But
|
||||
for or queries we can continue execution.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/745
|
||||
|
||||
* Bugfix - Use micro default client: [#718](https://github.com/owncloud/ocis/pull/718)
|
||||
|
||||
Tags: glauth
|
||||
|
||||
We found a file descriptor leak in the glauth connections to the accounts service. Fixed it by
|
||||
using the micro default client.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/718
|
||||
|
||||
* Bugfix - Allow consent-prompt with switch-account: [#788](https://github.com/owncloud/ocis/pull/788)
|
||||
|
||||
Multiple prompt values are allowed and this change fixes the check for select_account if it was
|
||||
used together with other prompt values. Where select_account previously was ignored, it is
|
||||
now processed as required, fixing the use case when a RP wants to trigger select_account first
|
||||
while at the same time wants also to request interactive consent.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/788
|
||||
|
||||
* Bugfix - Mint token with uid and gid: [#737](https://github.com/owncloud/ocis/pull/737)
|
||||
|
||||
Tags: accounts
|
||||
|
||||
The eos driver expects the uid and gid from the opaque map of a user. While the proxy does mint
|
||||
tokens correctly, the accounts service wasn't.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/737
|
||||
|
||||
* Bugfix - Don't create account if id/mail/username already taken: [#709](https://github.com/owncloud/ocis/pull/709)
|
||||
|
||||
Tags: accounts
|
||||
|
||||
We don't allow anymore to create a new account if the provided id/mail/username is already
|
||||
taken.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/709
|
||||
|
||||
* Bugfix - Fix director selection in proxy: [#521](https://github.com/owncloud/ocis/pull/521)
|
||||
|
||||
Tags: proxy
|
||||
@@ -96,6 +171,35 @@
|
||||
|
||||
https://github.com/owncloud/ocis/pull/656
|
||||
|
||||
* Change - Filesystem based index: [#709](https://github.com/owncloud/ocis/pull/709)
|
||||
|
||||
Tags: accounts, storage
|
||||
|
||||
We replaced `bleve` with a new filesystem based index implementation. There is an `indexer`
|
||||
which is capable of orchestrating different index types to build indices on documents by
|
||||
field. You can choose from the index types `unique`, `non-unique` or `autoincrement`.
|
||||
Indices can be utilized to run search queries (full matches or globbing) on document fields.
|
||||
The accounts service is using this index internally to run the search queries coming in via
|
||||
`ListAccounts` and `ListGroups` and to generate UIDs for new accounts as well as GIDs for new
|
||||
groups.
|
||||
|
||||
The accounts service can be configured to store the index on the local FS / a NFS (`disk`
|
||||
implementation of the index) or to use an arbitrary storage ( `cs3` implementation of the
|
||||
index). `cs3` is the new default, which is configured to use the `metadata` storage.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/709
|
||||
|
||||
* Change - Rebuild index command for accounts: [#748](https://github.com/owncloud/ocis/pull/748)
|
||||
|
||||
Tags: accounts
|
||||
|
||||
The index for the accounts service can now be rebuilt by running the cli command `./bin/ocis
|
||||
accounts rebuild`. It deletes all configured indices and rebuilds them from the documents
|
||||
found on storage. For this we also introduced a `LoadAccounts` and `LoadGroups` function on
|
||||
storage for loading all existing documents.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/748
|
||||
|
||||
* Change - Add the thumbnails command: [#156](https://github.com/owncloud/ocis/issues/156)
|
||||
|
||||
Tags: thumbnails
|
||||
@@ -162,6 +266,22 @@
|
||||
https://github.com/owncloud/product/issues/25
|
||||
https://github.com/owncloud/ocis/pull/239/files
|
||||
|
||||
* Change - Properly style konnectd consent page: [#754](https://github.com/owncloud/ocis/pull/754)
|
||||
|
||||
Tags: konnectd
|
||||
|
||||
After bringing our theme into konnectd, we've had to adjust the styles of the consent page so the
|
||||
text is visible and button reflects our theme.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/754
|
||||
|
||||
* Change - Move the indexer package from ocis/accounts to ocis/ocis-pkg: [#794](https://github.com/owncloud/ocis/pull/794)
|
||||
|
||||
We are making that change for semantic reasons. So consumers of any index don't necessarily
|
||||
need to know of the accounts service.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/794
|
||||
|
||||
* Change - Switch over to a new custom-built runtime: [#287](https://github.com/owncloud/ocis/pull/287)
|
||||
|
||||
We moved away from using the go-micro runtime and are now using [our own
|
||||
@@ -171,6 +291,17 @@
|
||||
|
||||
https://github.com/owncloud/ocis/pull/287
|
||||
|
||||
* Change - Remove username field in OCS: [#709](https://github.com/owncloud/ocis/pull/709)
|
||||
|
||||
Tags: ocs
|
||||
|
||||
We use the incoming userid as both the `id` and the `on_premises_sam_account_name` for new
|
||||
accounts in the accounts service. The userid in OCS requests is in fact the username, not our
|
||||
internal account id. We need to enforce the userid as our internal account id though, because
|
||||
the account id is part of various `path` formats.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/709
|
||||
|
||||
* Change - Account management permissions for Admin role: [#124](https://github.com/owncloud/product/issues/124)
|
||||
|
||||
Tags: accounts, settings
|
||||
@@ -209,6 +340,15 @@
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.18.0
|
||||
https://github.com/owncloud/owncloud-design-system/releases/tag/v1.12.1
|
||||
|
||||
* Change - Default apps in ownCloud Web: [#688](https://github.com/owncloud/ocis/pull/688)
|
||||
|
||||
Tags: web
|
||||
|
||||
We changed the default apps for ownCloud Web to be only files and media-viewer.
|
||||
Markdown-editor and draw-io have been removed as defaults.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/688
|
||||
|
||||
* Change - Make ocis-settings available: [#287](https://github.com/owncloud/ocis/pull/287)
|
||||
|
||||
Tags: settings
|
||||
@@ -228,6 +368,54 @@
|
||||
https://github.com/owncloud/ocis/issues/119
|
||||
https://github.com/owncloud/ocis/issues/136
|
||||
|
||||
* Change - Bring oC theme: [#698](https://github.com/owncloud/ocis/pull/698)
|
||||
|
||||
Tags: konnectd
|
||||
|
||||
We've styled our konnectd login page to reflect ownCloud theme.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/698
|
||||
|
||||
* Change - Update phoenix to v0.20.0: [#674](https://github.com/owncloud/ocis/pull/674)
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.20.0. Please refer to the changelog (linked) for details on the
|
||||
phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/674
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.20.0
|
||||
|
||||
* Change - Update phoenix to v0.21.0: [#728](https://github.com/owncloud/ocis/pull/728)
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.21.0. Please refer to the changelog (linked) for details on the
|
||||
phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/728
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.21.0
|
||||
|
||||
* Change - Update phoenix to v0.22.0: [#757](https://github.com/owncloud/ocis/pull/757)
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.22.0. Please refer to the changelog (linked) for details on the
|
||||
phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/757
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.22.0
|
||||
|
||||
* Change - Update phoenix to v0.23.0: [#785](https://github.com/owncloud/ocis/pull/785)
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.23.0. Please refer to the changelog (linked) for details on the
|
||||
phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/785
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.23.0
|
||||
|
||||
* Change - Update reva config: [#336](https://github.com/owncloud/ocis/pull/336)
|
||||
|
||||
* EOS homes are not configured with an enable-flag anymore, but with a dedicated storage driver.
|
||||
@@ -238,6 +426,16 @@
|
||||
https://github.com/owncloud/ocis/pull/338
|
||||
https://github.com/owncloud/ocis-reva/pull/891
|
||||
|
||||
* Change - Clarify storage driver env vars: [#729](https://github.com/owncloud/ocis/pull/729)
|
||||
|
||||
After renaming ocsi-reva to storage and combining the storage and data providers some env vars
|
||||
were confusingly named `STORAGE_STORAGE_...`. We are changing the prefix for driver related
|
||||
env vars to `STORAGE_DRIVER_...`. This makes changing the storage driver using eg.:
|
||||
`STORAGE_HOME_DRIVER=eos` and setting driver options using
|
||||
`STORAGE_DRIVER_EOS_LAYOUT=...` less confusing.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/729
|
||||
|
||||
* Change - Settings and accounts appear in the user menu: [#656](https://github.com/owncloud/ocis/pull/656)
|
||||
|
||||
We moved settings and accounts to the user menu.
|
||||
@@ -1239,3 +1437,45 @@
|
||||
https://github.com/owncloud/product/issues/92
|
||||
https://github.com/owncloud/ocis/pull/329
|
||||
https://github.com/owncloud/ocis/pull/409
|
||||
|
||||
* Enhancement - Update glauth to dev 4f029234b2308: [#786](https://github.com/owncloud/ocis/pull/786)
|
||||
|
||||
Includes a bugfix, don't mix graph and provisioning api.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/786
|
||||
|
||||
* Enhancement - Update konnectd to v0.33.8: [#744](https://github.com/owncloud/ocis/pull/744)
|
||||
|
||||
This update adds options which allow the configuration of oidc-token expiration parameters:
|
||||
KONNECTD_ACCESS_TOKEN_EXPIRATION, KONNECTD_ID_TOKEN_EXPIRATION and
|
||||
KONNECTD_REFRESH_TOKEN_EXPIRATION.
|
||||
|
||||
Other changes from upstream:
|
||||
|
||||
- Generate random endsession state for external authority - Update dependencies in
|
||||
Dockerfile - Set prompt=None to avoid loops with external authority - Update Jenkins
|
||||
reporting plugin from checkstyle to recordIssues - Remove extra kty key from JWKS top level
|
||||
document - Fix regression which encodes URL fragments twice - Avoid generating fragmet/query
|
||||
URLs with wrong order - Return state for oidc endsession response redirects - Use server
|
||||
provided username to avoid case mismatch - Use signed-out-uri if set as fallback for goodbye
|
||||
redirect on saml slo - Add checks to ensure post_logout_redirect_uri is not empty - Fix SAML2
|
||||
logout request parsing - Cure panic when no state is found in saml esr - Use SAML IdP Issuer value
|
||||
from meta data entityID - Allow configuration of expiration of oidc access, id and refresh
|
||||
tokens - Implement trampolin for external OIDC authority end session - Update
|
||||
ca-certificates version
|
||||
|
||||
https://github.com/owncloud/ocis/pull/744
|
||||
|
||||
* Enhancement - Update reva to cdb3d6688da5: [#748](https://github.com/owncloud/ocis/pull/748)
|
||||
|
||||
* let the gateway filter invalid references
|
||||
|
||||
https://github.com/owncloud/ocis/pull/748
|
||||
https://github.com/cs3org/reva/pull/1274
|
||||
|
||||
* Enhancement - Update reva to dd3a8c0f38: [#725](https://github.com/owncloud/ocis/pull/725)
|
||||
|
||||
* fixes etag propagation in the ocis driver
|
||||
|
||||
https://github.com/owncloud/ocis/pull/725
|
||||
https://github.com/cs3org/reva/pull/1264
|
||||
|
||||
@@ -156,8 +156,8 @@ $(GOPATH)/bin/protoc-gen-micro:
|
||||
$(GOPATH)/bin/protoc-gen-microweb:
|
||||
GO111MODULE=off go get -v github.com/owncloud/protoc-gen-microweb
|
||||
|
||||
$(GOPATH)/bin/protoc-gen-swagger:
|
||||
GO111MODULE=off go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
|
||||
$(GOPATH)/bin/protoc-gen-openapiv2:
|
||||
GO111MODULE=off go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv2
|
||||
|
||||
$(PROTO_SRC)/accounts.pb.go: $(PROTO_SRC)/accounts.proto
|
||||
protoc \
|
||||
@@ -186,5 +186,5 @@ $(PROTO_SRC)/accounts.swagger.json: $(PROTO_SRC)/accounts.proto
|
||||
--swagger_out=$(PROTO_SRC) accounts.proto
|
||||
|
||||
.PHONY: protobuf
|
||||
protobuf: $(GOPATH)/bin/protoc-gen-go $(GOPATH)/bin/protoc-gen-micro $(GOPATH)/bin/protoc-gen-microweb $(GOPATH)/bin/protoc-gen-swagger \
|
||||
protobuf: $(GOPATH)/bin/protoc-gen-go $(GOPATH)/bin/protoc-gen-micro $(GOPATH)/bin/protoc-gen-microweb $(GOPATH)/bin/protoc-gen-openapiv2 \
|
||||
$(PROTO_SRC)/accounts.pb.go $(PROTO_SRC)/accounts.pb.micro.go $(PROTO_SRC)/accounts.pb.web.go $(PROTO_SRC)/accounts.swagger.json
|
||||
|
||||
@@ -3,43 +3,39 @@ module github.com/owncloud/ocis/accounts
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/CiscoM31/godata v0.0.0-20191007193734-c2c4ebb1b415
|
||||
github.com/blevesearch/bleve v1.0.9
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200730121022-c4f3d4f7ddfd
|
||||
github.com/cs3org/reva v1.1.0
|
||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect
|
||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
|
||||
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect
|
||||
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
|
||||
github.com/CiscoM31/godata v0.0.0-20201003040028-eadcd34e7f06 // indirect
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20201007120910-416ed6cf8b00
|
||||
github.com/cs3org/reva v1.3.1-0.20201023144216-cdb3d6688da5
|
||||
github.com/go-chi/chi v4.1.2+incompatible
|
||||
github.com/go-chi/render v1.0.1
|
||||
github.com/gofrs/uuid v3.3.0+incompatible
|
||||
github.com/golang/protobuf v1.4.2
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/mennanov/fieldmask-utils v0.3.2
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
||||
github.com/iancoleman/strcase v0.1.2 // indirect
|
||||
github.com/mennanov/fieldmask-utils v0.3.3
|
||||
github.com/micro/cli/v2 v2.1.2
|
||||
github.com/micro/go-micro/v2 v2.9.1
|
||||
github.com/oklog/run v1.1.0
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/owncloud/ocis/ocis-pkg v0.0.0-20200918114005-1a0ddd2190ee
|
||||
github.com/owncloud/ocis v1.0.0-rc3.0.20201103111659-46bf133a3c63 // indirect
|
||||
github.com/owncloud/ocis/ocis-pkg v0.0.0-20201103111659-46bf133a3c63
|
||||
github.com/owncloud/ocis/settings v0.0.0-20200918114005-1a0ddd2190ee
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/owncloud/ocis/storage v0.0.0-20201015120921-38358ba4d4df // indirect
|
||||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/restic/calens v0.2.0
|
||||
github.com/rs/zerolog v1.19.0
|
||||
github.com/rs/zerolog v1.20.0
|
||||
github.com/spf13/viper v1.7.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
|
||||
github.com/tredoe/osutil v1.0.5
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202
|
||||
google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad
|
||||
google.golang.org/grpc v1.31.0
|
||||
google.golang.org/grpc v1.33.1
|
||||
google.golang.org/protobuf v1.25.0
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/owncloud/ocis/ocis-pkg => ../ocis-pkg
|
||||
github.com/owncloud/ocis/settings => ../settings
|
||||
github.com/owncloud/ocis/storage => ../storage
|
||||
google.golang.org/grpc => google.golang.org/grpc v1.26.0
|
||||
)
|
||||
|
||||
200
accounts/go.sum
200
accounts/go.sum
@@ -50,8 +50,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzS
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CiscoM31/godata v0.0.0-20191007193734-c2c4ebb1b415 h1:rATYsVSP89BOyS9/o+cdGZ8qU7AHh4frtS59nFPoX8k=
|
||||
github.com/CiscoM31/godata v0.0.0-20191007193734-c2c4ebb1b415/go.mod h1:tjaihnMBH6p5DVnGBksDQQHpErbrLvb9ek6cEWuyc7E=
|
||||
github.com/CiscoM31/godata v0.0.0-20201003040028-eadcd34e7f06 h1:FKxVU/j9Dd8Je0YkVkm8Fxpz9zIeN21SEkcbzA6NWgY=
|
||||
github.com/CiscoM31/godata v0.0.0-20201003040028-eadcd34e7f06/go.mod h1:tjaihnMBH6p5DVnGBksDQQHpErbrLvb9ek6cEWuyc7E=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
|
||||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
@@ -68,10 +68,9 @@ github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcy
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||
github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8=
|
||||
github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/UnnoTed/fileb0x v1.1.4 h1:IUgFzgBipF/ujNx9wZgkrKOF3oltUuXMSoaejrBws+A=
|
||||
@@ -103,12 +102,17 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
github.com/ascarter/requestid v0.0.0-20170313220838-5b76ab3d4aee h1:3T/l+vMotQ7cDSLWNAn2Vg1SAQ3mdyLgBWWBitSS3uU=
|
||||
github.com/ascarter/requestid v0.0.0-20170313220838-5b76ab3d4aee/go.mod h1:u7Wtt4WATGGgae9mURNGQQqxAudPKrxfsbSDSGOso+g=
|
||||
github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.23.19/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.33.19/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.34.12 h1:7UbBEYDUa4uW0YmRnOd806MS1yoJMcaodBWDzvBShAI=
|
||||
github.com/aws/aws-sdk-go v1.34.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.35.9/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
|
||||
github.com/aws/aws-xray-sdk-go v0.9.4/go.mod h1:XtMKdBQfpVut+tJEwI7+dJFRxxRdxHDyVNp2tHXRq04=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@@ -120,26 +124,6 @@ github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkN
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blevesearch/bleve v1.0.9 h1:kqw/Ank/61UV9/Bx9kCcnfH6qWPgmS8O5LNfpsgzASg=
|
||||
github.com/blevesearch/bleve v1.0.9/go.mod h1:tb04/rbU29clbtNgorgFd8XdJea4x3ybYaOjWKr+UBU=
|
||||
github.com/blevesearch/blevex v0.0.0-20190916190636-152f0fe5c040 h1:SjYVcfJVZoCfBlg+fkaq2eoZHTf5HaJfaTeTkOtyfHQ=
|
||||
github.com/blevesearch/blevex v0.0.0-20190916190636-152f0fe5c040/go.mod h1:WH+MU2F4T0VmSdaPX+Wu5GYoZBrYWdOZWSjzvYcDmqQ=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/mmap-go v1.0.2 h1:JtMHb+FgQCTTYIhtMvimw15dJwu1Y5lrZDMOFXVWPk0=
|
||||
github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA=
|
||||
github.com/blevesearch/segment v0.9.0 h1:5lG7yBCx98or7gK2cHMKPukPZ/31Kag7nONpoBt22Ac=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
||||
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
|
||||
github.com/blevesearch/zap/v11 v11.0.9 h1:wlSrDBeGN1G4M51NQHIXca23ttwUfQpWaK7uhO5lRSo=
|
||||
github.com/blevesearch/zap/v11 v11.0.9/go.mod h1:47hzinvmY2EvvJruzsSCJpro7so8L1neseaGjrtXHOY=
|
||||
github.com/blevesearch/zap/v12 v12.0.9 h1:PpatkY+BLVFZf0Ok3/fwgI/I4RU0z5blXFGuQANmqXk=
|
||||
github.com/blevesearch/zap/v12 v12.0.9/go.mod h1:paQuvxy7yXor+0Mx8p2KNmJgygQbQNN+W6HRfL5Hvwc=
|
||||
github.com/blevesearch/zap/v13 v13.0.1 h1:NSCM6uKu77Vn/x9nlPp4pE1o/bftqcOWZEHSyZVpGBQ=
|
||||
github.com/blevesearch/zap/v13 v13.0.1/go.mod h1:XmyNLMvMf8Z5FjLANXwUeDW3e1+o77TTGUWrth7T9WI=
|
||||
github.com/blevesearch/zap/v14 v14.0.0 h1:HF8Ysjm13qxB0jTGaKLlatNXmJbQD8bY+PrPxm5v4hE=
|
||||
github.com/blevesearch/zap/v14 v14.0.0/go.mod h1:sUc/gPGJlFbSQ2ZUh/wGRYwkKx+Dg/5p+dd+eq6QMXk=
|
||||
github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ=
|
||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
@@ -147,6 +131,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR
|
||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo=
|
||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
||||
github.com/bwmarrin/discordgo v0.20.2/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
||||
github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
||||
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||
github.com/caddyserver/certmagic v0.10.6 h1:sCya6FmfaN74oZE46kqfaFOVoROD/mF36rTQfjN7TZc=
|
||||
github.com/caddyserver/certmagic v0.10.6/go.mod h1:Y8jcUBctgk/IhpAzlHKfimZNyXCkfGgRTC0orl8gROQ=
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
@@ -162,6 +148,7 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
|
||||
github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
@@ -200,10 +187,6 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k=
|
||||
github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
|
||||
github.com/couchbase/vellum v1.0.1 h1:qrj9ohvZedvc51S5KzPfJ6P6z0Vqzv7Lx7k3mVc2WOk=
|
||||
github.com/couchbase/vellum v1.0.1/go.mod h1:FcwrEivFpNi24R3jLOs3n+fs5RnuQnQqCLBJ1uAg1W4=
|
||||
github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
@@ -213,21 +196,30 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
|
||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cs3org/cato v0.0.0-20200626150132-28a40e643719/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
|
||||
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200730121022-c4f3d4f7ddfd h1:uMaudkC7znaiIKT9rxIhoRYzrhTg1Nc78X7XEqhmjSk=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200730121022-c4f3d4f7ddfd/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200810113633-b00aca449666 h1:E7VsSSN/2YZLSwrDMJJdAWU11lP7W1qkcXbrslb0PM0=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200810113633-b00aca449666/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20201007120910-416ed6cf8b00 h1:LVl25JaflluOchVvaHWtoCynm5OaM+VNai0IYkcCSe0=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20201007120910-416ed6cf8b00/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
|
||||
github.com/cs3org/reva v1.1.0 h1:Gih6ECHvMMGSx523SFluFlDmNMuhYelXYShdWvjvW38=
|
||||
github.com/cs3org/reva v1.1.0/go.mod h1:fBzTrNuAKdQ62ybjpdu8nyhBin90/3/3s6DGQDCdBp4=
|
||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
|
||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
|
||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
|
||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 h1:MZRmHqDBd0vxNwenEbKSQqRVT24d3C05ft8kduSwlqM=
|
||||
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
|
||||
github.com/cs3org/reva v1.2.2-0.20200924071957-e6676516e61e h1:khITGSnfDXtByQsLezoXgocUgGHJBBn0BPsUihGvk7w=
|
||||
github.com/cs3org/reva v1.2.2-0.20200924071957-e6676516e61e/go.mod h1:DOV5SjpOBKN+aWfOHLdA4KiLQkpyC786PQaXEdRAZ0M=
|
||||
github.com/cs3org/reva v1.3.1-0.20201023144216-cdb3d6688da5 h1:nkmk9ywGKpJthWeMYGBiXh4DD6mTCOZLRfGDjp9rsKg=
|
||||
github.com/cs3org/reva v1.3.1-0.20201023144216-cdb3d6688da5/go.mod h1:V50GXMiT524bvxACFkrkZqBzK4BoXLSprxcPshBlSOY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE=
|
||||
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI=
|
||||
github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
@@ -254,13 +246,8 @@ github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl
|
||||
github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59 h1:t2+zxJPT/jq/YOx/JRsoByAZI/GHOxYJ7MKeillEX4U=
|
||||
github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59/go.mod h1:XYuK1S5+kS6FGhlIUFuZFPvWiSrOIoLk6+ro33Xce3Y=
|
||||
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
|
||||
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
|
||||
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
|
||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
|
||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
@@ -268,6 +255,8 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
|
||||
github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
@@ -275,10 +264,6 @@ github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc
|
||||
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-acme/lego/v3 v3.4.0 h1:deB9NkelA+TfjGHVw8J7iKl/rMtffcGMWSMmptvMv0A=
|
||||
github.com/go-acme/lego/v3 v3.4.0/go.mod h1:xYbLDuxq3Hy4bMUT1t9JIuz6GWIWb3m5X+TeTHYaT7M=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
||||
@@ -306,6 +291,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-ldap/ldap/v3 v3.2.3 h1:FBt+5w3q/vPVPb4eYMQSn+pOiz4zewPamYhlGMmc7yM=
|
||||
github.com/go-ldap/ldap/v3 v3.2.3/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-ldap/ldap/v3 v3.2.4/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
|
||||
@@ -517,6 +503,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -533,9 +520,10 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
|
||||
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||
@@ -561,11 +549,14 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181004151105-1babbf986f6f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
@@ -588,6 +579,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
@@ -631,12 +624,15 @@ github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0
|
||||
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
|
||||
github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo=
|
||||
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/iancoleman/strcase v0.1.2 h1:gnomlvw9tnV3ITTAxzKSgTF+8kFWcU/f+TgttpXGz1U=
|
||||
github.com/iancoleman/strcase v0.1.2/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
|
||||
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||
@@ -647,8 +643,8 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
@@ -681,15 +677,17 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw=
|
||||
github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
@@ -733,26 +731,40 @@ github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGD
|
||||
github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/mattn/goveralls v0.0.5/go.mod h1:Xg2LHi51faXLyKXwsndxiW6uxEEQT9+3sjGzzwU4xy0=
|
||||
github.com/mattn/goveralls v0.0.6 h1:cr8Y0VMo/MnEZBjxNN/vh6G90SZ7IMb6lms1dzMoO+Y=
|
||||
github.com/mattn/goveralls v0.0.6/go.mod h1:h8b4ow6FxSPMQHF6o2ve3qsclnffZjYTNEKmLesRwqw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mennanov/fieldmask-utils v0.3.2 h1:AkHXYBEOoyvocl8YhzoStATRnto5OH1PY4Rj78I5Cuc=
|
||||
github.com/mennanov/fieldmask-utils v0.3.2/go.mod h1:JpaanSp6Ql5A8dGktEFxTmA9uBXmz3F+2LAXDZwiimU=
|
||||
github.com/mennanov/fieldmask-utils v0.3.3 h1:/cAjLk3ja74dQJ0BBxEsK4xyzvECcOYLLB1lo6HuLog=
|
||||
github.com/mennanov/fieldmask-utils v0.3.3/go.mod h1:OcOWam4DG685inAjtNuFONKpkitiCCK1W5yKljvWwCY=
|
||||
github.com/micro/cli/v2 v2.1.2 h1:43J1lChg/rZCC1rvdqZNFSQDrGT7qfMrtp6/ztpIkEM=
|
||||
github.com/micro/cli/v2 v2.1.2/go.mod h1:EguNh6DAoWKm9nmk+k/Rg0H3lQnDxqzu5x5srOtGtYg=
|
||||
github.com/micro/go-micro/v2 v2.9.1 h1:+S9koIrNWARjpP6k2TZ7kt0uC9zUJtNXzIdZTZRms7Q=
|
||||
@@ -788,6 +800,7 @@ github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||
@@ -803,9 +816,6 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd
|
||||
github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/moul/http2curl v0.0.0-20170919181001-9ac6cf4d929b/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
||||
github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
|
||||
@@ -834,6 +844,7 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/oleiade/reflections v1.0.0 h1:0ir4pc6v8/PJ0yw5AEtMddfXpWBXg9cnG7SgSoJuCgY=
|
||||
github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w=
|
||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
@@ -862,16 +873,30 @@ github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnh
|
||||
github.com/ory/fosite v0.29.0/go.mod h1:0atSZmXO7CAcs6NPMI/Qtot8tmZYj04Nddoold4S2h0=
|
||||
github.com/ory/fosite v0.32.2 h1:iRV495P/9EyoYQ8qEHYxFQeeYCdDFawqjAML+qiMF9s=
|
||||
github.com/ory/fosite v0.32.2/go.mod h1:UeBhRgW6nAjTcd8S7kAo0IFsY/rTPyOXPq/t8N20Q8I=
|
||||
github.com/ory/fosite v0.33.0 h1:tK+3Luazv4vIBJY3uagOBryAQ3IG3cs6kfo8piGBhAY=
|
||||
github.com/ory/fosite v0.33.0/go.mod h1:h+ize9gk0GvRyGjabriqSEmTkMhny+O95cijb8DVqPE=
|
||||
github.com/ory/fosite v0.35.1/go.mod h1:h+ize9gk0GvRyGjabriqSEmTkMhny+O95cijb8DVqPE=
|
||||
github.com/ory/go-acc v0.0.0-20181118080137-ddc355013f90/go.mod h1:sxnvPCxChFuSmTJGj8FdMupeq1BezCiEpDjTUXQ4hf4=
|
||||
github.com/ory/go-acc v0.2.1/go.mod h1:0omgy2aa3nDBJ45VAKeLHH8ccPBudxLeic4xiDRtug0=
|
||||
github.com/ory/go-acc v0.2.5 h1:31irXHzG2vnKQSE4weJm7AdfrnpaVjVCq3nD7viXCJE=
|
||||
github.com/ory/go-acc v0.2.5/go.mod h1:4Kb/UnPcT8qRAk3IAxta+hvVapdxTLWtrr7bFLlEgpw=
|
||||
github.com/ory/go-convenience v0.1.0 h1:zouLKfF2GoSGnJwGq+PE/nJAE6dj2Zj5QlTgmMTsTS8=
|
||||
github.com/ory/go-convenience v0.1.0/go.mod h1:uEY/a60PL5c12nYz4V5cHY03IBmwIAEm8TWB0yn9KNs=
|
||||
github.com/ory/gojsonreference v0.0.0-20190720135523-6b606c2d8ee8/go.mod h1:wsH1C4nIeeQClDtD5AH7kF1uTS6zWyqfjVDTmB0Em7A=
|
||||
github.com/ory/gojsonschema v1.1.1-0.20190919112458-f254ca73d5e9/go.mod h1:BNZpdJgB74KOLSsWFvzw6roXg1I6O51WO8roMmW+T7Y=
|
||||
github.com/ory/herodot v0.6.2/go.mod h1:3BOneqcyBsVybCPAJoi92KN2BpJHcmDqAMcAAaJiJow=
|
||||
github.com/ory/viper v1.5.6/go.mod h1:TYmpFpKLxjQwvT4f0QPpkOn4sDXU1kDgAwJpgLYiQ28=
|
||||
github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE=
|
||||
github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM=
|
||||
github.com/ory/x v0.0.85/go.mod h1:s44V8t3xyjWZREcU+mWlp4h302rTuM4aLXcW+y5FbQ8=
|
||||
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
|
||||
github.com/owncloud/flaex v0.0.0-20200411150708-dce59891a203/go.mod h1:jip86t4OVURJTf8CM/0e2qcji/Y4NG3l2lR8kex4JWw=
|
||||
github.com/owncloud/ocis v1.0.0-rc3 h1:ZFQxg7OhvO08l5Hvqa4gQS0HT6ul7s1j3w3qvHPh8gc=
|
||||
github.com/owncloud/ocis v1.0.0-rc3.0.20201103111659-46bf133a3c63 h1:IkzoExiUk2zOWSTt5dlZmbmzs/wFz8zo/tHgz4QOFKY=
|
||||
github.com/owncloud/ocis v1.0.0-rc3.0.20201103111659-46bf133a3c63/go.mod h1:kHoustfrV4pGvkKcNFXIr8GRT9MY25mzOKGij4uAC60=
|
||||
github.com/owncloud/ocis/accounts v0.5.3-0.20201103104733-ff2c41028d9b/go.mod h1:IX7T4MJ1U8Y4z9dfDW1J2jq1nv/SHCM7n2zt1fmBHI8=
|
||||
github.com/owncloud/ocis/storage v0.0.0-20201015120921-38358ba4d4df h1:PhRLD+WTGIfQ1T4MqBabp6/1Q8H/iwxjlygh6xzao0A=
|
||||
github.com/owncloud/ocis/storage v0.0.0-20201015120921-38358ba4d4df/go.mod h1:s9kJvxtBlHEi5qc1TuPAdz2bprk9yGFe+FSOeC76Pbs=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||
github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
|
||||
@@ -884,8 +909,8 @@ github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
|
||||
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -893,6 +918,9 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03/go.mod h1:Z9+Ul5bCbBKnbCvdOWbLqTHhJiYV414CURZJba6L8qA=
|
||||
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
|
||||
github.com/pkg/xattr v0.4.1 h1:dhclzL6EqOXNaPDWqoeb9tIxATfBSmjqL0b4DpSjwRw=
|
||||
github.com/pkg/xattr v0.4.1/go.mod h1:W2cGD0TBEus7MkUgv0tNZ9JutLtVO3cXu+IBRuHqnFs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -936,9 +964,6 @@ github.com/prometheus/statsd_exporter v0.15.0/go.mod h1:Dv8HnkoLQkeEjkIE4/2ndAA7
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/restic/calens v0.2.0 h1:LVNAtmFc+Pb4ODX66qdX1T3Di1P0OTLyUsVyvM/xD7E=
|
||||
github.com/restic/calens v0.2.0/go.mod h1:UXwyAKS4wsgUZGEc7NrzzygJbLsQZIo3wl+62Q1wvmU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
@@ -953,6 +978,8 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg=
|
||||
github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
|
||||
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||
github.com/rubenv/sql-migrate v0.0.0-20190212093014-1007f53448d7/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
@@ -1001,17 +1028,24 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.0/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.3.2 h1:GDarE4TJQI52kYSbSAmLiId1Elfj+xgSDqrUZxFhxlU=
|
||||
github.com/spf13/afero v1.3.2/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
@@ -1023,11 +1057,10 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
|
||||
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
|
||||
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/steveyen/gtreap v0.1.0 h1:CjhzTa274PyJLJuMZwIzCO1PfC00oRa8d1Kc78bFXJM=
|
||||
github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7Z4dM9/Y=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -1038,22 +1071,20 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1 h1:TPyHV/OgChqNcnYqCoCvIFjR9TU60gFXXBKnhOBzVEI=
|
||||
github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s=
|
||||
github.com/subosito/gotenv v1.1.1/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||
github.com/tidwall/gjson v1.3.2/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
||||
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y=
|
||||
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
|
||||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc h1:yUaosFVTJwnltaHbSNC3i82I92quFs+OFPRl8kNMVwo=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
@@ -1085,8 +1116,6 @@ github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QI
|
||||
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
|
||||
github.com/vimeo/go-util v1.2.0/go.mod h1:s13SMDTSO7AjH1nbgp707mfN5JFIWUFDU5MDDuRRtKs=
|
||||
github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA=
|
||||
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -1098,6 +1127,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||
@@ -1112,6 +1143,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
||||
@@ -1150,16 +1183,20 @@ golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaE
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1170,6 +1207,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@@ -1190,6 +1228,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1232,6 +1272,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
@@ -1278,12 +1319,12 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1297,34 +1338,48 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666 h1:gVCS+QOncANNPlmlO1AhlU3oxs4V9z+gTtPwIk3p2N8=
|
||||
golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1392,6 +1447,9 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200721223218-6123e77877b2 h1:kxDWg8KNMtpGjI/XVKGgOtSljTnVg/PrjhS8+0pxjLE=
|
||||
golang.org/x/tools v0.0.0-20200721223218-6123e77877b2/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
@@ -1441,6 +1499,7 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece h1:1YM0uhfumvoDu9sx8+RyWwTI63zoCQvI23IYFRlvte0=
|
||||
@@ -1483,6 +1542,8 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
|
||||
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw=
|
||||
gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc=
|
||||
@@ -1492,6 +1553,8 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.5.0 h1:OZ4sdq+Y+SHfYB7vfthi1Ei8b0vkP8ZPQgUfUwdUSqo=
|
||||
gopkg.in/square/go-jose.v2 v2.5.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
@@ -1505,6 +1568,9 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"watch": "rollup -c -w",
|
||||
"test": "echo 'Not implemented'",
|
||||
"generate-api": "node node_modules/swagger-vue-generator/bin/generate-api.js --package-version v0 --source pkg/proto/v0/accounts.swagger.json --moduleName accounts --destination ui/client/accounts/index.js",
|
||||
"acceptance-tests": "cucumber-js --require-module @babel/register --require-module @babel/polyfill --require ${TEST_INFRA_DIRECTORY}/acceptance/setup.js --require ui/tests/acceptance/stepDefinitions --require ${TEST_INFRA_DIRECTORY}/acceptance/stepDefinitions --format node_modules/cucumber-pretty -t \"${TEST_TAGS:-not @skip and not @skipOnOC10}\""
|
||||
"acceptance-tests": "cucumber-js --retry 1 --require-module @babel/register --require-module @babel/polyfill --require ${TEST_INFRA_DIRECTORY}/acceptance/setup.js --require ui/tests/acceptance/stepDefinitions --require ${TEST_INFRA_DIRECTORY}/acceptance/stepDefinitions --format node_modules/cucumber-pretty -t \"${TEST_TAGS:-not @skip and not @skipOnOC10}\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.7.7",
|
||||
@@ -53,7 +53,7 @@
|
||||
"ldap": "^0.7.1",
|
||||
"nightwatch": "^1.3.6",
|
||||
"nightwatch-api": "^3.0.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"qs": "^6.9.1",
|
||||
"rimraf": "^3.0.0",
|
||||
"rollup": "^1.28.0",
|
||||
|
||||
File diff suppressed because one or more lines are too long
34
accounts/pkg/command/rebuild_index.go
Normal file
34
accounts/pkg/command/rebuild_index.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/micro/cli/v2"
|
||||
"github.com/micro/go-micro/v2/client/grpc"
|
||||
merrors "github.com/micro/go-micro/v2/errors"
|
||||
"github.com/owncloud/ocis/accounts/pkg/config"
|
||||
index "github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
)
|
||||
|
||||
// RebuildIndex rebuilds the entire configured index.
|
||||
func RebuildIndex(cdf *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "rebuildIndex",
|
||||
Usage: "Rebuilds the service's index, i.e. deleting and then re-adding all existing documents",
|
||||
Aliases: []string{"rebuild", "ri"},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
idxSvcID := "com.owncloud.api.accounts"
|
||||
idxSvc := index.NewIndexService(idxSvcID, grpc.NewClient())
|
||||
|
||||
_, err := idxSvc.RebuildIndex(context.Background(), &index.RebuildIndexRequest{})
|
||||
if err != nil {
|
||||
fmt.Println(merrors.FromError(err).Detail)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("index rebuilt successfully")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ func Execute() error {
|
||||
InspectAccount(cfg),
|
||||
RemoveAccount(cfg),
|
||||
PrintVersion(cfg),
|
||||
RebuildIndex(cfg),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -77,16 +77,27 @@ type CS3 struct {
|
||||
ProviderAddr string
|
||||
DataURL string
|
||||
DataPrefix string
|
||||
JWTSecret string
|
||||
}
|
||||
|
||||
// ServiceUser defines the user required for EOS
|
||||
// ServiceUser defines the user required for EOS.
|
||||
type ServiceUser struct {
|
||||
UUID string
|
||||
UUID string
|
||||
Username string
|
||||
UID int64
|
||||
GID int64
|
||||
}
|
||||
|
||||
// Index defines config for indexes.
|
||||
type Index struct {
|
||||
UID, GID Bound
|
||||
}
|
||||
|
||||
// Bound defines a lower and upper bound.
|
||||
type Bound struct {
|
||||
Lower, Upper int64
|
||||
}
|
||||
|
||||
// Config merges all Account config parameters.
|
||||
type Config struct {
|
||||
LDAP LDAP
|
||||
@@ -97,6 +108,7 @@ type Config struct {
|
||||
Log Log
|
||||
TokenManager TokenManager
|
||||
Repo Repo
|
||||
Index Index
|
||||
ServiceUser ServiceUser
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,13 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
|
||||
EnvVars: []string{"ACCOUNTS_STORAGE_CS3_DATA_PREFIX"},
|
||||
Destination: &cfg.Repo.CS3.DataPrefix,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "storage-cs3-jwt-secret",
|
||||
Value: "Pive-Fumkiu4",
|
||||
Usage: "Used to create JWT to talk to reva, should equal reva's jwt-secret",
|
||||
EnvVars: []string{"ACCOUNTS_STORAGE_CS3_JWT_SECRET"},
|
||||
Destination: &cfg.Repo.CS3.JWTSecret,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "service-user-uuid",
|
||||
Value: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad",
|
||||
@@ -155,6 +162,34 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
|
||||
EnvVars: []string{"ACCOUNTS_SERVICE_USER_GID"},
|
||||
Destination: &cfg.ServiceUser.GID,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "uid-index-lower-bound",
|
||||
Value: 0,
|
||||
Usage: "define a starting point for the account UID",
|
||||
EnvVars: []string{"ACCOUNTS_UID_INDEX_LOWER_BOUND"},
|
||||
Destination: &cfg.Index.UID.Lower,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "gid-index-lower-bound",
|
||||
Value: 1000,
|
||||
Usage: "define a starting point for the account GID",
|
||||
EnvVars: []string{"ACCOUNTS_GID_INDEX_LOWER_BOUND"},
|
||||
Destination: &cfg.Index.GID.Lower,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "uid-index-upper-bound",
|
||||
Value: 0,
|
||||
Usage: "define an ending point for the account UID",
|
||||
EnvVars: []string{"ACCOUNTS_UID_INDEX_UPPER_BOUND"},
|
||||
Destination: &cfg.Index.UID.Upper,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "gid-index-upper-bound",
|
||||
Value: 1000,
|
||||
Usage: "define an ending point for the account GID",
|
||||
EnvVars: []string{"ACCOUNTS_GID_INDEX_UPPER_BOUND"},
|
||||
Destination: &cfg.Index.GID.Upper,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -551,3 +551,77 @@ func (h *groupsServiceHandler) RemoveMember(ctx context.Context, in *RemoveMembe
|
||||
func (h *groupsServiceHandler) ListMembers(ctx context.Context, in *ListMembersRequest, out *ListMembersResponse) error {
|
||||
return h.GroupsServiceHandler.ListMembers(ctx, in, out)
|
||||
}
|
||||
|
||||
// Api Endpoints for IndexService service
|
||||
|
||||
func NewIndexServiceEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{
|
||||
&api.Endpoint{
|
||||
Name: "IndexService.RebuildIndex",
|
||||
Path: []string{"/api/v0/index/rebuild"},
|
||||
Method: []string{"POST"},
|
||||
Body: "*",
|
||||
Handler: "rpc",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Client API for IndexService service
|
||||
|
||||
type IndexService interface {
|
||||
RebuildIndex(ctx context.Context, in *RebuildIndexRequest, opts ...client.CallOption) (*RebuildIndexResponse, error)
|
||||
}
|
||||
|
||||
type indexService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewIndexService(name string, c client.Client) IndexService {
|
||||
return &indexService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *indexService) RebuildIndex(ctx context.Context, in *RebuildIndexRequest, opts ...client.CallOption) (*RebuildIndexResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "IndexService.RebuildIndex", in)
|
||||
out := new(RebuildIndexResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for IndexService service
|
||||
|
||||
type IndexServiceHandler interface {
|
||||
RebuildIndex(context.Context, *RebuildIndexRequest, *RebuildIndexResponse) error
|
||||
}
|
||||
|
||||
func RegisterIndexServiceHandler(s server.Server, hdlr IndexServiceHandler, opts ...server.HandlerOption) error {
|
||||
type indexService interface {
|
||||
RebuildIndex(ctx context.Context, in *RebuildIndexRequest, out *RebuildIndexResponse) error
|
||||
}
|
||||
type IndexService struct {
|
||||
indexService
|
||||
}
|
||||
h := &indexServiceHandler{hdlr}
|
||||
opts = append(opts, api.WithEndpoint(&api.Endpoint{
|
||||
Name: "IndexService.RebuildIndex",
|
||||
Path: []string{"/api/v0/index/rebuild"},
|
||||
Method: []string{"POST"},
|
||||
Body: "*",
|
||||
Handler: "rpc",
|
||||
}))
|
||||
return s.Handle(s.NewHandler(&IndexService{h}, opts...))
|
||||
}
|
||||
|
||||
type indexServiceHandler struct {
|
||||
IndexServiceHandler
|
||||
}
|
||||
|
||||
func (h *indexServiceHandler) RebuildIndex(ctx context.Context, in *RebuildIndexRequest, out *RebuildIndexResponse) error {
|
||||
return h.IndexServiceHandler.RebuildIndex(ctx, in, out)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -25,51 +26,88 @@ import (
|
||||
|
||||
var service = grpc.Service{}
|
||||
|
||||
const dataPath = "./accounts-store"
|
||||
var dataPath = createTmpDir()
|
||||
|
||||
var newCreatedAccounts = []string{}
|
||||
var newCreatedGroups = []string{}
|
||||
|
||||
var mockedRoleAssignment = map[string]string{}
|
||||
|
||||
var (
|
||||
user1 = proto.Account{
|
||||
Id: "f9149a32-2b8e-4f04-9e8d-937d81712b9a",
|
||||
AccountEnabled: true,
|
||||
IsResourceAccount: true,
|
||||
CreationType: "",
|
||||
DisplayName: "User One",
|
||||
PreferredName: "user1",
|
||||
OnPremisesSamAccountName: "user1",
|
||||
UidNumber: 20009,
|
||||
GidNumber: 30000,
|
||||
Mail: "user1@example.com",
|
||||
Identities: []*proto.Identities{nil},
|
||||
PasswordProfile: &proto.PasswordProfile{Password: "heysdjfsdlk"},
|
||||
MemberOf: []*proto.Group{
|
||||
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"}, // users
|
||||
},
|
||||
}
|
||||
user2 = proto.Account{
|
||||
Id: "e9149a32-2b8e-4f04-9e8d-937d81712b9a",
|
||||
AccountEnabled: true,
|
||||
IsResourceAccount: true,
|
||||
CreationType: "",
|
||||
DisplayName: "User Two",
|
||||
PreferredName: "user2",
|
||||
OnPremisesSamAccountName: "user2",
|
||||
UidNumber: 20010,
|
||||
GidNumber: 30000,
|
||||
Mail: "user2@example.com",
|
||||
Identities: []*proto.Identities{nil},
|
||||
PasswordProfile: &proto.PasswordProfile{Password: "hello123"},
|
||||
MemberOf: []*proto.Group{
|
||||
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"}, // users
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
service = grpc.NewService(
|
||||
grpc.Namespace("com.owncloud.api"),
|
||||
grpc.Name("accounts"),
|
||||
grpc.Address("localhost:9180"),
|
||||
)
|
||||
|
||||
cfg := config.New()
|
||||
cfg.Server.AccountsDataPath = dataPath
|
||||
cfg.Repo.Disk.Path = dataPath
|
||||
var hdlr *svc.Service
|
||||
var err error
|
||||
|
||||
if hdlr, err = svc.New(svc.Logger(command.NewLogger(cfg)), svc.Config(cfg), svc.RoleService(buildRoleServiceMock())); err != nil {
|
||||
log.Fatalf("Could not create new service")
|
||||
}
|
||||
|
||||
err = proto.RegisterAccountsServiceHandler(service.Server(), hdlr)
|
||||
if err != nil {
|
||||
log.Fatal("could not register the Accounts handler")
|
||||
}
|
||||
err = proto.RegisterGroupsServiceHandler(service.Server(), hdlr)
|
||||
if err != nil {
|
||||
log.Fatal("could not register the Groups handler")
|
||||
}
|
||||
|
||||
err = service.Server().Start()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getAccount(user string) *proto.Account {
|
||||
switch user {
|
||||
case "user1":
|
||||
return &proto.Account{
|
||||
Id: "f9149a32-2b8e-4f04-9e8d-937d81712b9a",
|
||||
AccountEnabled: true,
|
||||
IsResourceAccount: true,
|
||||
CreationType: "",
|
||||
DisplayName: "User One",
|
||||
PreferredName: "user1",
|
||||
OnPremisesSamAccountName: "user1",
|
||||
UidNumber: 20009,
|
||||
GidNumber: 30000,
|
||||
Mail: "user1@example.com",
|
||||
Identities: []*proto.Identities{nil},
|
||||
PasswordProfile: &proto.PasswordProfile{Password: "heysdjfsdlk"},
|
||||
MemberOf: []*proto.Group{
|
||||
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"}, // users
|
||||
},
|
||||
}
|
||||
return &user1
|
||||
case "user2":
|
||||
return &proto.Account{
|
||||
Id: "e9149a32-2b8e-4f04-9e8d-937d81712b9a",
|
||||
AccountEnabled: true,
|
||||
IsResourceAccount: true,
|
||||
CreationType: "",
|
||||
DisplayName: "User Two",
|
||||
PreferredName: "user2",
|
||||
OnPremisesSamAccountName: "user2",
|
||||
UidNumber: 20009,
|
||||
GidNumber: 30000,
|
||||
Mail: "user2@example.com",
|
||||
Identities: []*proto.Identities{nil},
|
||||
PasswordProfile: &proto.PasswordProfile{Password: "hello123"},
|
||||
MemberOf: []*proto.Group{
|
||||
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"}, // users
|
||||
},
|
||||
}
|
||||
return &user2
|
||||
default:
|
||||
return &proto.Account{
|
||||
Id: fmt.Sprintf("new-id-%s", user),
|
||||
@@ -154,38 +192,6 @@ func getTestGroups(group string) *proto.Group {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
service = grpc.NewService(
|
||||
grpc.Namespace("com.owncloud.api"),
|
||||
grpc.Name("accounts"),
|
||||
grpc.Address("localhost:9180"),
|
||||
)
|
||||
|
||||
cfg := config.New()
|
||||
cfg.Server.AccountsDataPath = dataPath
|
||||
cfg.Repo.Disk.Path = dataPath
|
||||
var hdlr *svc.Service
|
||||
var err error
|
||||
|
||||
if hdlr, err = svc.New(svc.Logger(command.NewLogger(cfg)), svc.Config(cfg), svc.RoleService(buildRoleServiceMock())); err != nil {
|
||||
log.Fatalf("Could not create new service")
|
||||
}
|
||||
|
||||
err = proto.RegisterAccountsServiceHandler(service.Server(), hdlr)
|
||||
if err != nil {
|
||||
log.Fatal("could not register the Accounts handler")
|
||||
}
|
||||
err = proto.RegisterGroupsServiceHandler(service.Server(), hdlr)
|
||||
if err != nil {
|
||||
log.Fatal("could not register the Groups handler")
|
||||
}
|
||||
|
||||
err = service.Server().Start()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func buildRoleServiceMock() settings.RoleService {
|
||||
return settings.MockRoleService{
|
||||
AssignRoleToUserFunc: func(ctx context.Context, req *settings.AssignRoleToUserRequest, opts ...client.CallOption) (res *settings.AssignRoleToUserResponse, err error) {
|
||||
@@ -208,8 +214,7 @@ func cleanUp(t *testing.T) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
_, err := deleteAccount(t, id)
|
||||
checkError(t, err)
|
||||
_, _ = deleteAccount(t, id)
|
||||
}
|
||||
|
||||
datastore = filepath.Join(dataPath, "groups")
|
||||
@@ -219,8 +224,7 @@ func cleanUp(t *testing.T) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
_, err := deleteGroup(t, id)
|
||||
checkError(t, err)
|
||||
_, _ = deleteGroup(t, id)
|
||||
}
|
||||
|
||||
newCreatedAccounts = []string{}
|
||||
@@ -309,12 +313,6 @@ func assertGroupHasMember(t *testing.T, grp *proto.Group, memberId string) {
|
||||
t.Fatalf("Member with id %s expected to be in group '%s', but not found", memberId, grp.DisplayName)
|
||||
}
|
||||
|
||||
func checkError(t *testing.T, err error) {
|
||||
if err != nil {
|
||||
t.Fatalf("Expected Error to be nil but got %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func createAccount(t *testing.T, user string) (*proto.Account, error) {
|
||||
client := service.Client()
|
||||
cl := proto.NewAccountsService("com.owncloud.api.accounts", client)
|
||||
@@ -368,7 +366,7 @@ func listGroups(t *testing.T) *proto.ListGroupsResponse {
|
||||
cl := proto.NewGroupsService("com.owncloud.api.accounts", client)
|
||||
|
||||
response, err := cl.ListGroups(context.Background(), request)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
return response
|
||||
}
|
||||
|
||||
@@ -390,18 +388,27 @@ func deleteGroup(t *testing.T, id string) (*empty.Empty, error) {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// createTmpDir creates a temporary dir for tests data.
|
||||
func createTmpDir() string {
|
||||
name, err := ioutil.TempDir("/var/tmp", "ocis-accounts-store-")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
// https://github.com/owncloud/ocis/accounts/issues/61
|
||||
func TestCreateAccount(t *testing.T) {
|
||||
|
||||
resp, err := createAccount(t, "user1")
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assertUserExists(t, getAccount("user1"))
|
||||
assert.IsType(t, &proto.Account{}, resp)
|
||||
// Account is not returned in response
|
||||
// assertAccountsSame(t, getAccount("user1"), resp)
|
||||
|
||||
resp, err = createAccount(t, "user2")
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assertUserExists(t, getAccount("user2"))
|
||||
assert.IsType(t, &proto.Account{}, resp)
|
||||
// Account is not returned in response
|
||||
@@ -410,24 +417,25 @@ func TestCreateAccount(t *testing.T) {
|
||||
cleanUp(t)
|
||||
}
|
||||
|
||||
// https://github.com/owncloud/ocis/accounts/issues/62
|
||||
// https://github.com/owncloud/ocis-accounts/issues/62
|
||||
func TestCreateExistingUser(t *testing.T) {
|
||||
createAccount(t, "user1")
|
||||
_, err := createAccount(t, "user1")
|
||||
var err error
|
||||
_, err = createAccount(t, "user1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Should give error but it does not
|
||||
checkError(t, err)
|
||||
_, err = createAccount(t, "user1")
|
||||
assert.Error(t, err)
|
||||
assertUserExists(t, getAccount("user1"))
|
||||
|
||||
cleanUp(t)
|
||||
}
|
||||
|
||||
// All tests fail after running this
|
||||
// https://github.com/owncloud/ocis/accounts/issues/62
|
||||
// https://github.com/owncloud/ocis/accounts-issues/62
|
||||
func TestCreateAccountInvalidUserName(t *testing.T) {
|
||||
|
||||
resp, err := listAccounts(t)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
numAccounts := len(resp.GetAccounts())
|
||||
|
||||
testData := []string{
|
||||
@@ -448,7 +456,7 @@ func TestCreateAccountInvalidUserName(t *testing.T) {
|
||||
|
||||
// resp should have the same number of accounts
|
||||
resp, err = listAccounts(t)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, numAccounts, len(resp.GetAccounts()))
|
||||
|
||||
@@ -456,57 +464,58 @@ func TestCreateAccountInvalidUserName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateAccount(t *testing.T) {
|
||||
_, _ = createAccount(t, "user1")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
userAccount *proto.Account
|
||||
name string
|
||||
userAccount *proto.Account
|
||||
expectedErrOnUpdate error
|
||||
}{
|
||||
{
|
||||
"Update user (demonstration of updatable fields)",
|
||||
&proto.Account{
|
||||
DisplayName: "Alice Hansen",
|
||||
PreferredName: "Wonderful Alice",
|
||||
OnPremisesDistinguishedName: "Alice",
|
||||
UidNumber: 20010,
|
||||
GidNumber: 30001,
|
||||
Mail: "alice@example.com",
|
||||
DisplayName: "Alice Hansen",
|
||||
PreferredName: "Wonderful-Alice",
|
||||
OnPremisesSamAccountName: "Alice",
|
||||
UidNumber: 20010,
|
||||
GidNumber: 30001,
|
||||
Mail: "alice@example.com",
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"Update user with unicode data",
|
||||
&proto.Account{
|
||||
DisplayName: "एलिस हेन्सेन",
|
||||
PreferredName: "अद्भुत एलिस",
|
||||
OnPremisesDistinguishedName: "एलिस",
|
||||
UidNumber: 20010,
|
||||
GidNumber: 30001,
|
||||
Mail: "एलिस@उदाहरण.com",
|
||||
DisplayName: "एलिस हेन्सेन",
|
||||
PreferredName: "अद्भुत-एलिस",
|
||||
OnPremisesSamAccountName: "एलिस",
|
||||
UidNumber: 20010,
|
||||
GidNumber: 30001,
|
||||
Mail: "एलिस@उदाहरण.com",
|
||||
},
|
||||
merrors.BadRequest(".", "preferred_name 'अद्भुत-एलिस' must be at least the local part of an email"),
|
||||
},
|
||||
{
|
||||
"Update user with empty data values",
|
||||
&proto.Account{
|
||||
DisplayName: "",
|
||||
PreferredName: "",
|
||||
OnPremisesDistinguishedName: "",
|
||||
UidNumber: 0,
|
||||
GidNumber: 0,
|
||||
Mail: "",
|
||||
DisplayName: "",
|
||||
PreferredName: "",
|
||||
OnPremisesSamAccountName: "",
|
||||
UidNumber: 0,
|
||||
GidNumber: 0,
|
||||
Mail: "",
|
||||
},
|
||||
merrors.BadRequest(".", "preferred_name '' must be at least the local part of an email"),
|
||||
},
|
||||
{
|
||||
"Update user with strange data",
|
||||
&proto.Account{
|
||||
DisplayName: "12345",
|
||||
PreferredName: "12345",
|
||||
OnPremisesDistinguishedName: "54321",
|
||||
UidNumber: 1000,
|
||||
GidNumber: 1000,
|
||||
// No email validation
|
||||
// https://github.com/owncloud/ocis/accounts/issues/77
|
||||
Mail: "1.2@3.c_@",
|
||||
DisplayName: "12345",
|
||||
PreferredName: "a12345",
|
||||
OnPremisesSamAccountName: "a54321",
|
||||
UidNumber: 1000,
|
||||
GidNumber: 1000,
|
||||
Mail: "1.2@3.c_@",
|
||||
},
|
||||
merrors.BadRequest(".", "mail '1.2@3.c_@' must be a valid email"),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -524,20 +533,25 @@ func TestUpdateAccount(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.userAccount.Id = "f9149a32-2b8e-4f04-9e8d-937d81712b9a"
|
||||
acc, err := createAccount(t, "user1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
tt.userAccount.Id = acc.Id
|
||||
tt.userAccount.AccountEnabled = false
|
||||
tt.userAccount.IsResourceAccount = false
|
||||
resp, err := updateAccount(t, tt.userAccount, updateMask)
|
||||
|
||||
checkError(t, err)
|
||||
|
||||
assert.IsType(t, &proto.Account{}, resp)
|
||||
assertAccountsSame(t, tt.userAccount, resp)
|
||||
assertUserExists(t, tt.userAccount)
|
||||
if tt.expectedErrOnUpdate != nil {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, tt.expectedErrOnUpdate, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, &proto.Account{}, resp)
|
||||
assertAccountsSame(t, tt.userAccount, resp)
|
||||
assertUserExists(t, tt.userAccount)
|
||||
}
|
||||
cleanUp(t)
|
||||
})
|
||||
}
|
||||
|
||||
cleanUp(t)
|
||||
}
|
||||
|
||||
func TestUpdateNonUpdatableFieldsInAccount(t *testing.T) {
|
||||
@@ -554,6 +568,7 @@ func TestUpdateNonUpdatableFieldsInAccount(t *testing.T) {
|
||||
"CreationType",
|
||||
},
|
||||
&proto.Account{
|
||||
Id: user1.Id,
|
||||
CreationType: "Type Test",
|
||||
},
|
||||
},
|
||||
@@ -563,6 +578,7 @@ func TestUpdateNonUpdatableFieldsInAccount(t *testing.T) {
|
||||
"PasswordProfile",
|
||||
},
|
||||
&proto.Account{
|
||||
Id: user1.Id,
|
||||
PasswordProfile: &proto.PasswordProfile{Password: "new password"},
|
||||
},
|
||||
},
|
||||
@@ -572,6 +588,7 @@ func TestUpdateNonUpdatableFieldsInAccount(t *testing.T) {
|
||||
"MemberOf",
|
||||
},
|
||||
&proto.Account{
|
||||
Id: user1.Id,
|
||||
MemberOf: []*proto.Group{
|
||||
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"},
|
||||
},
|
||||
@@ -580,7 +597,6 @@ func TestUpdateNonUpdatableFieldsInAccount(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.userAccount.Id = "f9149a32-2b8e-4f04-9e8d-937d81712b9a"
|
||||
res, err := updateAccount(t, tt.userAccount, tt.updateMask)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected error while updating non updatable field, but found none.")
|
||||
@@ -602,6 +618,8 @@ func TestUpdateNonUpdatableFieldsInAccount(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
cleanUp(t)
|
||||
}
|
||||
|
||||
func TestListAccounts(t *testing.T) {
|
||||
@@ -609,7 +627,7 @@ func TestListAccounts(t *testing.T) {
|
||||
createAccount(t, "user2")
|
||||
|
||||
resp, err := listAccounts(t)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.IsType(t, &proto.ListAccountsResponse{}, resp)
|
||||
assert.Equal(t, 8, len(resp.Accounts))
|
||||
@@ -622,31 +640,128 @@ func TestListAccounts(t *testing.T) {
|
||||
|
||||
func TestListWithoutUserCreation(t *testing.T) {
|
||||
resp, err := listAccounts(t)
|
||||
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Only 5 default users
|
||||
assert.Equal(t, 6, len(resp.Accounts))
|
||||
cleanUp(t)
|
||||
}
|
||||
|
||||
func TestListAccountsWithFilterQuery(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
query string
|
||||
expectedIDs []string
|
||||
}{
|
||||
// FIXME: disabled test scenarios need to be supported when implementing OData support
|
||||
// OData implementation tracked in https://github.com/owncloud/ocis/issues/716
|
||||
//{
|
||||
// name: "ListAccounts with exact match on preferred_name",
|
||||
// query: "preferred_name eq 'user1'",
|
||||
// expectedIDs: []string{user1.Id},
|
||||
//},
|
||||
{
|
||||
name: "ListAccounts with exact match on on_premises_sam_account_name",
|
||||
query: "on_premises_sam_account_name eq 'user1'",
|
||||
expectedIDs: []string{user1.Id},
|
||||
},
|
||||
{
|
||||
name: "ListAccounts with exact match on mail",
|
||||
query: "mail eq 'user1@example.com'",
|
||||
expectedIDs: []string{user1.Id},
|
||||
},
|
||||
//{
|
||||
// name: "ListAccounts with exact match on id",
|
||||
// query: "id eq 'f9149a32-2b8e-4f04-9e8d-937d81712b9a'",
|
||||
// expectedIDs: []string{user1.Id},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts without match on preferred_name",
|
||||
// query: "preferred_name eq 'wololo'",
|
||||
// expectedIDs: []string{},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts with exact match on preferred_name AND mail",
|
||||
// query: "preferred_name eq 'user1' and mail eq 'user1@example.com'",
|
||||
// expectedIDs: []string{user1.Id},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts without match on preferred_name AND mail",
|
||||
// query: "preferred_name eq 'user1' and mail eq 'wololo@example.com'",
|
||||
// expectedIDs: []string{},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts with exact match on preferred_name OR mail, preferred_name exists, mail exists",
|
||||
// query: "preferred_name eq 'user1' or mail eq 'user1@example.com'",
|
||||
// expectedIDs: []string{user1.Id},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts with exact match on preferred_name OR mail, preferred_name exists, mail does not exist",
|
||||
// query: "preferred_name eq 'user1' or mail eq 'wololo@example.com'",
|
||||
// expectedIDs: []string{user1.Id},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts with exact match on preferred_name OR mail, preferred_name does not exists, mail exists",
|
||||
// query: "preferred_name eq 'wololo' or mail eq 'user1@example.com'",
|
||||
// expectedIDs: []string{user1.Id},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts without match on preferred_name OR mail, preferred_name and mail do not exist",
|
||||
// query: "preferred_name eq 'wololo' or mail eq 'wololo@example.com'",
|
||||
// expectedIDs: []string{},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts with multiple matches on preferred_name",
|
||||
// query: "startswith(preferred_name,'user*')",
|
||||
// expectedIDs: []string{user1.Id, user2.Id},
|
||||
//},
|
||||
//{
|
||||
// name: "ListAccounts with multiple matches on on_premises_sam_account_name",
|
||||
// query: "startswith(on_premises_sam_account_name,'user*')",
|
||||
// expectedIDs: []string{user1.Id, user2.Id},
|
||||
//},
|
||||
}
|
||||
|
||||
cl := proto.NewAccountsService("com.owncloud.api.accounts", service.Client())
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.name, func(t *testing.T) {
|
||||
_, err := createAccount(t, "user1")
|
||||
assert.NoError(t, err)
|
||||
_, err = createAccount(t, "user2")
|
||||
assert.NoError(t, err)
|
||||
|
||||
req := &proto.ListAccountsRequest{Query: scenario.query}
|
||||
res, err := cl.ListAccounts(context.Background(), req)
|
||||
assert.NoError(t, err)
|
||||
ids := make([]string, 0)
|
||||
for _, acc := range res.Accounts {
|
||||
ids = append(ids, acc.Id)
|
||||
}
|
||||
assert.Equal(t, scenario.expectedIDs, ids)
|
||||
cleanUp(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccount(t *testing.T) {
|
||||
createAccount(t, "user1")
|
||||
|
||||
req := &proto.GetAccountRequest{Id: getAccount("user1").Id}
|
||||
|
||||
client := service.Client()
|
||||
cl := proto.NewAccountsService("com.owncloud.api.accounts", client)
|
||||
cl := proto.NewAccountsService("com.owncloud.api.accounts", service.Client())
|
||||
|
||||
resp, err := cl.GetAccount(context.Background(), req)
|
||||
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, &proto.Account{}, resp)
|
||||
assertAccountsSame(t, getAccount("user1"), resp)
|
||||
|
||||
cleanUp(t)
|
||||
}
|
||||
|
||||
//TODO: This segfaults! WIP
|
||||
|
||||
func TestDeleteAccount(t *testing.T) {
|
||||
createAccount(t, "user1")
|
||||
createAccount(t, "user2")
|
||||
@@ -657,7 +772,7 @@ func TestDeleteAccount(t *testing.T) {
|
||||
cl := proto.NewAccountsService("com.owncloud.api.accounts", client)
|
||||
|
||||
resp, err := cl.DeleteAccount(context.Background(), req)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, resp, &empty.Empty{})
|
||||
|
||||
// Check the account doesn't exists anymore
|
||||
@@ -675,9 +790,9 @@ func TestListGroups(t *testing.T) {
|
||||
cl := proto.NewGroupsService("com.owncloud.api.accounts", client)
|
||||
|
||||
resp, err := cl.ListGroups(context.Background(), req)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, &proto.ListGroupsResponse{}, resp)
|
||||
assert.Equal(t, len(resp.Groups), 9)
|
||||
assert.Equal(t, 9, len(resp.Groups))
|
||||
|
||||
groups := []string{
|
||||
"sysusers",
|
||||
@@ -718,7 +833,7 @@ func TestGetGroups(t *testing.T) {
|
||||
req := &proto.GetGroupRequest{Id: group.Id}
|
||||
resp, err := cl.GetGroup(context.Background(), req)
|
||||
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, &proto.Group{}, resp)
|
||||
assertGroupsSame(t, group, resp)
|
||||
}
|
||||
@@ -733,7 +848,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
}}
|
||||
|
||||
res, err := createGroup(t, group)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.IsType(t, &proto.Group{}, res)
|
||||
|
||||
@@ -772,12 +887,12 @@ func TestDeleteGroup(t *testing.T) {
|
||||
req := &proto.DeleteGroupRequest{Id: grp1.Id}
|
||||
res, err := cl.DeleteGroup(context.Background(), req)
|
||||
assert.IsType(t, res, &empty.Empty{})
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req = &proto.DeleteGroupRequest{Id: grp2.Id}
|
||||
res, err = cl.DeleteGroup(context.Background(), req)
|
||||
assert.IsType(t, res, &empty.Empty{})
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
groupsResponse := listGroups(t)
|
||||
assertResponseNotContainsGroup(t, groupsResponse, grp1)
|
||||
@@ -870,7 +985,7 @@ func TestAddMember(t *testing.T) {
|
||||
req := &proto.AddMemberRequest{GroupId: grp1.Id, AccountId: account.Id}
|
||||
|
||||
res, err := cl.AddMember(context.Background(), req)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.IsType(t, &proto.Group{}, res)
|
||||
|
||||
@@ -904,7 +1019,7 @@ func TestAddMemberAlreadyInGroup(t *testing.T) {
|
||||
res, err := cl.AddMember(context.Background(), req)
|
||||
|
||||
// Should Give Error
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, &proto.Group{}, res)
|
||||
//assert.Equal(t, proto.Group{}, *res)
|
||||
//assertGroupsSame(t, updatedGroup, res)
|
||||
@@ -975,7 +1090,7 @@ func TestRemoveMember(t *testing.T) {
|
||||
req := &proto.RemoveMemberRequest{GroupId: grp1.Id, AccountId: account.Id}
|
||||
|
||||
res, err := cl.RemoveMember(context.Background(), req)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.IsType(t, &proto.Group{}, res)
|
||||
//assert.Equal(t, proto.Group{}, *res)
|
||||
@@ -1034,7 +1149,7 @@ func TestRemoveMemberNotInGroup(t *testing.T) {
|
||||
res, err := cl.RemoveMember(context.Background(), req)
|
||||
|
||||
// Should give an error
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
assert.IsType(t, &proto.Group{}, res)
|
||||
|
||||
//assert.Error(t, err)
|
||||
@@ -1071,7 +1186,7 @@ func TestListMembers(t *testing.T) {
|
||||
req := &proto.ListMembersRequest{Id: expectedGroup.Id}
|
||||
|
||||
res, err := cl.ListMembers(context.Background(), req)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, len(res.Members), len(expectedGroup.Members))
|
||||
|
||||
@@ -1093,19 +1208,23 @@ func TestListMembers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListMembersEmptyGroup(t *testing.T) {
|
||||
group := &proto.Group{Id: "5d58e5ec-842e-498b-8800-61f2ec6f911c", GidNumber: 30002, OnPremisesSamAccountName: "quantum-group", DisplayName: "Quantum Group", Members: []*proto.Account{}}
|
||||
|
||||
createGroup(t, group)
|
||||
group := &proto.Group{Id: "5d58e5ec-842e-498b-8800-61f2ec6f911c", GidNumber: 60000, OnPremisesSamAccountName: "quantum-group", DisplayName: "Quantum Group", Members: []*proto.Account{}}
|
||||
|
||||
client := service.Client()
|
||||
cl := proto.NewGroupsService("com.owncloud.api.accounts", client)
|
||||
|
||||
request := &proto.CreateGroupRequest{Group: group}
|
||||
_, err := cl.CreateGroup(context.Background(), request)
|
||||
if err == nil {
|
||||
newCreatedGroups = append(newCreatedGroups, group.Id)
|
||||
}
|
||||
|
||||
req := &proto.ListMembersRequest{Id: group.Id}
|
||||
|
||||
res, err := cl.ListMembers(context.Background(), req)
|
||||
listRes, err := cl.ListMembers(context.Background(), req)
|
||||
|
||||
checkError(t, err)
|
||||
assert.Empty(t, res.Members)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, listRes.Members)
|
||||
|
||||
cleanUp(t)
|
||||
}
|
||||
@@ -1120,12 +1239,12 @@ func TestAccountUpdateMask(t *testing.T) {
|
||||
Account: &proto.Account{
|
||||
Id: user1.Id,
|
||||
DisplayName: "ShouldBeUpdated",
|
||||
PreferredName: "ShouldStaySame",
|
||||
PreferredName: "ShouldStaySame And Is Invalid Anyway",
|
||||
}}
|
||||
|
||||
cl := proto.NewAccountsService("com.owncloud.api.accounts", client)
|
||||
res, err := cl.UpdateAccount(context.Background(), req)
|
||||
checkError(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "ShouldBeUpdated", res.DisplayName)
|
||||
assert.Equal(t, user1.PreferredName, res.PreferredName)
|
||||
|
||||
@@ -372,6 +372,120 @@ func RegisterGroupsServiceWeb(r chi.Router, i GroupsServiceHandler, middlewares
|
||||
r.MethodFunc("POST", "/api/v0/groups/{id=*}/members/$ref", handler.ListMembers)
|
||||
}
|
||||
|
||||
type webIndexServiceHandler struct {
|
||||
r chi.Router
|
||||
h IndexServiceHandler
|
||||
}
|
||||
|
||||
func (h *webIndexServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.r.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (h *webIndexServiceHandler) RebuildIndex(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
req := &RebuildIndexRequest{}
|
||||
|
||||
resp := &RebuildIndexResponse{}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.h.RebuildIndex(
|
||||
r.Context(),
|
||||
req,
|
||||
resp,
|
||||
); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(w, r, resp)
|
||||
}
|
||||
|
||||
func RegisterIndexServiceWeb(r chi.Router, i IndexServiceHandler, middlewares ...func(http.Handler) http.Handler) {
|
||||
handler := &webIndexServiceHandler{
|
||||
r: r,
|
||||
h: i,
|
||||
}
|
||||
|
||||
r.MethodFunc("POST", "/api/v0/index/rebuild", handler.RebuildIndex)
|
||||
}
|
||||
|
||||
// RebuildIndexRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of RebuildIndexRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var RebuildIndexRequestJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *RebuildIndexRequest) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := RebuildIndexRequestJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*RebuildIndexRequest)(nil)
|
||||
|
||||
// RebuildIndexRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of RebuildIndexRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var RebuildIndexRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *RebuildIndexRequest) UnmarshalJSON(b []byte) error {
|
||||
return RebuildIndexRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*RebuildIndexRequest)(nil)
|
||||
|
||||
// RebuildIndexResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of RebuildIndexResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var RebuildIndexResponseJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *RebuildIndexResponse) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := RebuildIndexResponseJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*RebuildIndexResponse)(nil)
|
||||
|
||||
// RebuildIndexResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of RebuildIndexResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var RebuildIndexResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *RebuildIndexResponse) UnmarshalJSON(b []byte) error {
|
||||
return RebuildIndexResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*RebuildIndexResponse)(nil)
|
||||
|
||||
// ListAccountsRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of ListAccountsRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
|
||||
@@ -136,6 +136,23 @@ service GroupsService {
|
||||
|
||||
}
|
||||
|
||||
service IndexService {
|
||||
rpc RebuildIndex(RebuildIndexRequest) returns (RebuildIndexResponse) {
|
||||
// All request parameters go into body.
|
||||
option (google.api.http) = {
|
||||
// URLs are broken
|
||||
post: "/api/v0/index/rebuild"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message RebuildIndexRequest {
|
||||
}
|
||||
|
||||
message RebuildIndexResponse {
|
||||
}
|
||||
|
||||
message ListAccountsRequest {
|
||||
// Optional. The maximum number of accounts to return in the response
|
||||
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,13 +0,0 @@
|
||||
package proto
|
||||
|
||||
// BleveAccount wraps the generated Account and adds a bleve type that is used to distinguish documents in the index
|
||||
type BleveAccount struct {
|
||||
Account
|
||||
BleveType string `json:"bleve_type"`
|
||||
}
|
||||
|
||||
// BleveGroup wraps the generated Group and adds a bleve type that is used to distinguish documents in the index
|
||||
type BleveGroup struct {
|
||||
Group
|
||||
BleveType string `json:"bleve_type"`
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/CiscoM31/godata"
|
||||
"github.com/blevesearch/bleve"
|
||||
"github.com/blevesearch/bleve/search/query"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// add (ap)prox filter
|
||||
godata.GlobalFilterTokenizer = FilterTokenizer()
|
||||
godata.GlobalFilterParser.DefineOperator("ap", 2, godata.OpAssociationLeft, 4, false)
|
||||
}
|
||||
|
||||
// BuildBleveQuery converts a GoDataFilterQuery into a bleve query
|
||||
func BuildBleveQuery(r *godata.GoDataFilterQuery) (query.Query, error) {
|
||||
return recursiveBuildQuery(r.Tree)
|
||||
}
|
||||
|
||||
// Builds the filter recursively using DFS
|
||||
func recursiveBuildQuery(n *godata.ParseNode) (query.Query, error) {
|
||||
if n.Token.Type == godata.FilterTokenFunc {
|
||||
switch n.Token.Value {
|
||||
case "startswith":
|
||||
if len(n.Children) != 2 {
|
||||
return nil, errors.New("startswith match must have two children")
|
||||
}
|
||||
if n.Children[0].Token.Type != godata.FilterTokenLiteral {
|
||||
return nil, errors.New("startswith expected a literal as the first param")
|
||||
}
|
||||
if n.Children[1].Token.Type != godata.FilterTokenString {
|
||||
return nil, errors.New("startswith expected a string as the second param")
|
||||
} // remove enclosing ' of string tokens (looks like 'some ol'' string')
|
||||
value := n.Children[1].Token.Value[1 : len(n.Children[1].Token.Value)-1]
|
||||
// unescape '' as '
|
||||
unescaped := strings.ReplaceAll(value, "''", "'")
|
||||
q := bleve.NewPrefixQuery(unescaped)
|
||||
q.SetField(n.Children[0].Token.Value)
|
||||
return q, nil
|
||||
// TODO contains as regex?
|
||||
// TODO endswith as regex?
|
||||
default:
|
||||
return nil, godata.NotImplementedError(n.Token.Value + " is not implemented.")
|
||||
}
|
||||
}
|
||||
if n.Token.Type == godata.FilterTokenLogical {
|
||||
switch n.Token.Value {
|
||||
case "eq":
|
||||
if len(n.Children) != 2 {
|
||||
return nil, errors.New("equality match must have two children")
|
||||
}
|
||||
if n.Children[0].Token.Type != godata.FilterTokenLiteral {
|
||||
return nil, errors.New("equality expected a literal on the lhs")
|
||||
}
|
||||
if n.Children[1].Token.Type == godata.FilterTokenString {
|
||||
// for escape rules see http://docs.oasis-open.org/odata/odata/v4.01/cs01/part2-url-conventions/odata-v4.01-cs01-part2-url-conventions.html#sec_URLComponents
|
||||
// remove enclosing ' of string tokens (looks like 'some ol'' string')
|
||||
value := n.Children[1].Token.Value[1 : len(n.Children[1].Token.Value)-1]
|
||||
// unescape '' as '
|
||||
unescaped := strings.ReplaceAll(value, "''", "'")
|
||||
// use a match query, so the field mapping, e.g. lowercase is applied to the value
|
||||
// remember we defined the field mapping for `preferred_name` to be lowercase
|
||||
// a term query like `preferred_name eq 'Artur'` would use `Artur` to search in the index and come up empty
|
||||
// a match query will apply the field mapping (lowercasing `Artur` to `artur`) before doing the search
|
||||
// TODO there is a mismatch between the LDAP and odata filters:
|
||||
// - LDAP matching rules depend on the attribute: see https://ldapwiki.com/wiki/MatchingRule
|
||||
// - odata has functions like `startswith`, `contains`, `tolower`, `toupper`, `matchesPattern` andy more: see http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_BuiltinQueryFunctions
|
||||
// - ocis-glauth should do the mapping between LDAP and odata filter
|
||||
q := bleve.NewMatchQuery(unescaped)
|
||||
q.SetField(n.Children[0].Token.Value)
|
||||
return q, nil
|
||||
} else if n.Children[1].Token.Type == godata.FilterTokenInteger {
|
||||
v, err := strconv.ParseFloat(n.Children[1].Token.Value, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
incl := true
|
||||
q := bleve.NewNumericRangeInclusiveQuery(&v, &v, &incl, &incl)
|
||||
q.SetField(n.Children[0].Token.Value)
|
||||
return q, nil
|
||||
}
|
||||
return nil, fmt.Errorf("equality expected a string or int on the rhs, got %d", n.Children[1].Token.Type)
|
||||
case "and":
|
||||
q := query.NewConjunctionQuery([]query.Query{})
|
||||
for _, child := range n.Children {
|
||||
subQuery, err := recursiveBuildQuery(child)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if subQuery != nil {
|
||||
q.AddQuery(subQuery)
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
case "or":
|
||||
q := query.NewDisjunctionQuery([]query.Query{})
|
||||
for _, child := range n.Children {
|
||||
subQuery, err := recursiveBuildQuery(child)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if subQuery != nil {
|
||||
q.AddQuery(subQuery)
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
case "Not":
|
||||
if len(n.Children) != 1 {
|
||||
return nil, errors.New("not filter must have only one child")
|
||||
}
|
||||
subQuery, err := recursiveBuildQuery(n.Children[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := query.NewBooleanQuery(nil, nil, []query.Query{subQuery})
|
||||
return q, nil
|
||||
default:
|
||||
return nil, godata.NotImplementedError(n.Token.Value + " is not implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
return nil, godata.NotImplementedError(n.Token.Value + " is not implemented.")
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package provider
|
||||
|
||||
import "github.com/CiscoM31/godata"
|
||||
|
||||
// FilterTokenizer creates a tokenizer capable of tokenizing filter statements
|
||||
// TODO disable tokens we don't handle anyway
|
||||
func FilterTokenizer() *godata.Tokenizer {
|
||||
t := godata.Tokenizer{}
|
||||
t.Add("^[0-9]{4,4}-[0-9]{2,2}-[0-9]{2,2}T[0-9]{2,2}:[0-9]{2,2}(:[0-9]{2,2}(.[0-9]+)?)?(Z|[+-][0-9]{2,2}:[0-9]{2,2})", godata.FilterTokenDateTime)
|
||||
t.Add("^-?[0-9]{4,4}-[0-9]{2,2}-[0-9]{2,2}", godata.FilterTokenDate)
|
||||
t.Add("^[0-9]{2,2}:[0-9]{2,2}(:[0-9]{2,2}(.[0-9]+)?)?", godata.FilterTokenTime)
|
||||
t.Add("^\\(", godata.FilterTokenOpenParen)
|
||||
t.Add("^\\)", godata.FilterTokenCloseParen)
|
||||
t.Add("^/", godata.FilterTokenNav)
|
||||
t.Add("^:", godata.FilterTokenColon)
|
||||
t.Add("^,", godata.FilterTokenComma)
|
||||
t.Add("^(geo.distance|geo.intersects|geo.length)", godata.FilterTokenFunc)
|
||||
t.Add("^(substringof|substring|length|indexof)", godata.FilterTokenFunc)
|
||||
// only change from the global tokenizer is the added ap
|
||||
t.Add("^(eq|ne|gt|ge|lt|le|and|or|not|has|in|ap)", godata.FilterTokenLogical)
|
||||
t.Add("^(add|sub|mul|divby|div|mod)", godata.FilterTokenOp)
|
||||
t.Add("^(contains|endswith|startswith|tolower|toupper|"+
|
||||
"trim|concat|year|month|day|hour|minute|second|fractionalseconds|date|"+
|
||||
"time|totaloffsetminutes|now|maxdatetime|mindatetime|totalseconds|round|"+
|
||||
"floor|ceiling|isof|cast)", godata.FilterTokenFunc)
|
||||
t.Add("^(any|all)", godata.FilterTokenLambda)
|
||||
t.Add("^null", godata.FilterTokenNull)
|
||||
t.Add("^\\$it", godata.FilterTokenIt)
|
||||
t.Add("^\\$root", godata.FilterTokenRoot)
|
||||
t.Add("^-?[0-9]+\\.[0-9]+", godata.FilterTokenFloat)
|
||||
t.Add("^-?[0-9]+", godata.FilterTokenInteger)
|
||||
t.Add("^'(''|[^'])*'", godata.FilterTokenString)
|
||||
t.Add("^(true|false)", godata.FilterTokenBoolean)
|
||||
t.Add("^@*[a-zA-Z][a-zA-Z0-9_.]*", godata.FilterTokenLiteral) // The optional '@' character is used to identify parameter aliases
|
||||
t.Ignore("^ ", godata.FilterTokenWhitespace)
|
||||
|
||||
return &t
|
||||
}
|
||||
@@ -26,6 +26,9 @@ func Server(opts ...Option) grpc.Service {
|
||||
if err := proto.RegisterGroupsServiceHandler(service.Server(), handler); err != nil {
|
||||
options.Logger.Fatal().Err(err).Msg("could not register groups handler")
|
||||
}
|
||||
if err := proto.RegisterIndexServiceHandler(service.Server(), handler); err != nil {
|
||||
options.Logger.Fatal().Err(err).Msg("could not register index handler")
|
||||
}
|
||||
|
||||
service.Init()
|
||||
return service
|
||||
|
||||
@@ -3,19 +3,20 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/CiscoM31/godata"
|
||||
"github.com/blevesearch/bleve"
|
||||
"github.com/owncloud/ocis/ocis-pkg/log"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
p "github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
fieldmask_utils "github.com/mennanov/fieldmask-utils"
|
||||
merrors "github.com/micro/go-micro/v2/errors"
|
||||
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
"github.com/owncloud/ocis/accounts/pkg/provider"
|
||||
"github.com/owncloud/ocis/accounts/pkg/storage"
|
||||
"github.com/owncloud/ocis/ocis-pkg/roles"
|
||||
settings "github.com/owncloud/ocis/settings/pkg/proto/v0"
|
||||
@@ -35,22 +36,6 @@ import (
|
||||
// accLock mutually exclude readers from writers on account files
|
||||
var accLock sync.Mutex
|
||||
|
||||
func (s Service) indexAccount(id string) error {
|
||||
a := &proto.BleveAccount{
|
||||
BleveType: "account",
|
||||
}
|
||||
if err := s.repo.LoadAccount(context.Background(), id, &a.Account); err != nil {
|
||||
s.log.Error().Err(err).Str("account", id).Msg("could not load account")
|
||||
return err
|
||||
}
|
||||
s.log.Debug().Interface("account", a).Msg("found account")
|
||||
if err := s.index.Index(a.Id, a); err != nil {
|
||||
s.log.Error().Err(err).Interface("account", a).Msg("could not index account")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// an auth request is currently hardcoded and has to match this regex
|
||||
// login eq \"teddy\" and password eq \"F&1!b90t111!\"
|
||||
var authQuery = regexp.MustCompile(`^login eq '(.*)' and password eq '(.*)'$`) // TODO how is ' escaped in the password?
|
||||
@@ -74,17 +59,6 @@ func (s Service) expandMemberOf(a *proto.Account) {
|
||||
a.MemberOf = expanded
|
||||
}
|
||||
|
||||
func (s Service) passwordIsValid(hash string, pwd string) (ok bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
s.log.Error().Err(fmt.Errorf("%s", r)).Str("hash", hash).Msg("password lib panicked")
|
||||
}
|
||||
}()
|
||||
|
||||
c := crypt.NewFromHash(hash)
|
||||
return c.Verify(hash, []byte(pwd)) == nil
|
||||
}
|
||||
|
||||
func (s Service) hasAccountManagementPermissions(ctx context.Context) bool {
|
||||
// get roles from context
|
||||
roleIDs, ok := roles.ReadRoleIDsFromContext(ctx)
|
||||
@@ -104,15 +78,12 @@ func (s Service) hasAccountManagementPermissions(ctx context.Context) bool {
|
||||
// serviceUserToIndex temporarily adds a service user to the index, which is supposed to be removed before the lock on the handler function is released
|
||||
func (s Service) serviceUserToIndex() (teardownServiceUser func()) {
|
||||
if s.Config.ServiceUser.Username != "" && s.Config.ServiceUser.UUID != "" {
|
||||
err := s.index.Index(s.Config.ServiceUser.UUID, &proto.BleveAccount{
|
||||
BleveType: "account",
|
||||
Account: s.getInMemoryServiceUser(),
|
||||
})
|
||||
_, err := s.index.Add(s.getInMemoryServiceUser())
|
||||
if err != nil {
|
||||
s.log.Logger.Err(err).Msg("service user was configured but failed to be added to the index")
|
||||
} else {
|
||||
return func() {
|
||||
_ = s.index.Delete(s.Config.ServiceUser.UUID)
|
||||
_ = s.index.Delete(s.getInMemoryServiceUser())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,83 +111,76 @@ func (s Service) ListAccounts(ctx context.Context, in *proto.ListAccountsRequest
|
||||
|
||||
accLock.Lock()
|
||||
defer accLock.Unlock()
|
||||
var password string
|
||||
|
||||
teardownServiceUser := s.serviceUserToIndex()
|
||||
defer teardownServiceUser()
|
||||
|
||||
// check if this looks like an auth request
|
||||
match := authQuery.FindStringSubmatch(in.Query)
|
||||
if len(match) == 3 {
|
||||
in.Query = fmt.Sprintf("on_premises_sam_account_name eq '%s'", match[1]) // todo fetch email? make query configurable
|
||||
password = match[2]
|
||||
if password == "" {
|
||||
return merrors.Unauthorized(s.id, "password must not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
// only search for accounts
|
||||
tq := bleve.NewTermQuery("account")
|
||||
tq.SetField("bleve_type")
|
||||
|
||||
query := bleve.NewConjunctionQuery(tq)
|
||||
|
||||
if in.Query != "" {
|
||||
// parse the query like an odata filter
|
||||
var q *godata.GoDataFilterQuery
|
||||
if q, err = godata.ParseFilterString(in.Query); err != nil {
|
||||
s.log.Error().Err(err).Msg("could not parse query")
|
||||
return merrors.InternalServerError(s.id, "could not parse query: %v", err.Error())
|
||||
match, authRequest := getAuthQueryMatch(in.Query)
|
||||
if authRequest {
|
||||
password := match[2]
|
||||
if len(password) == 0 {
|
||||
return merrors.Unauthorized(s.id, "account not found or invalid credentials")
|
||||
}
|
||||
|
||||
// convert to bleve query
|
||||
bq, err := provider.BuildBleveQuery(q)
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msg("could not build bleve query")
|
||||
return merrors.InternalServerError(s.id, "could not build bleve query: %v", err.Error())
|
||||
ids, err := s.index.FindBy(&proto.Account{}, "OnPremisesSamAccountName", match[1])
|
||||
if err != nil || len(ids) > 1 {
|
||||
return merrors.Unauthorized(s.id, "account not found or invalid credentials")
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
ids, err = s.index.FindBy(&proto.Account{}, "Mail", match[1])
|
||||
if err != nil || len(ids) != 1 {
|
||||
return merrors.Unauthorized(s.id, "account not found or invalid credentials")
|
||||
}
|
||||
}
|
||||
query.AddQuery(bq)
|
||||
}
|
||||
|
||||
s.log.Debug().Interface("query", query).Msg("using query")
|
||||
|
||||
searchRequest := bleve.NewSearchRequest(query)
|
||||
var searchResult *bleve.SearchResult
|
||||
searchResult, err = s.index.Search(searchRequest)
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msg("could not execute bleve search")
|
||||
return merrors.InternalServerError(s.id, "could not execute bleve search: %v", err.Error())
|
||||
}
|
||||
|
||||
s.log.Debug().Interface("result", searchResult).Msg("result")
|
||||
|
||||
out.Accounts = make([]*proto.Account, 0)
|
||||
|
||||
for _, hit := range searchResult.Hits {
|
||||
a := &proto.Account{}
|
||||
if hit.ID == s.Config.ServiceUser.UUID {
|
||||
err = s.repo.LoadAccount(ctx, ids[0], a)
|
||||
if err != nil || a.PasswordProfile == nil || len(a.PasswordProfile.Password) == 0 {
|
||||
return merrors.Unauthorized(s.id, "account not found or invalid credentials")
|
||||
}
|
||||
if !isPasswordValid(s.log, a.PasswordProfile.Password, password) {
|
||||
return merrors.Unauthorized(s.id, "account not found or invalid credentials")
|
||||
}
|
||||
a.PasswordProfile.Password = ""
|
||||
out.Accounts = []*proto.Account{a}
|
||||
return nil
|
||||
}
|
||||
|
||||
if in.Query == "" {
|
||||
err = s.repo.LoadAccounts(ctx, &out.Accounts)
|
||||
if err != nil {
|
||||
s.log.Err(err).Msg("failed to load all accounts from storage")
|
||||
return merrors.InternalServerError(s.id, "failed to load all accounts")
|
||||
}
|
||||
for i := range out.Accounts {
|
||||
a := out.Accounts[i]
|
||||
|
||||
// TODO add groups only if requested
|
||||
// if in.FieldMask ...
|
||||
s.expandMemberOf(a)
|
||||
|
||||
if a.PasswordProfile != nil {
|
||||
a.PasswordProfile.Password = ""
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
searchResults, err := s.findAccountsByQuery(ctx, in.Query)
|
||||
out.Accounts = make([]*proto.Account, 0, len(searchResults))
|
||||
|
||||
for _, hit := range searchResults {
|
||||
a := &proto.Account{}
|
||||
if hit == s.Config.ServiceUser.UUID {
|
||||
acc := s.getInMemoryServiceUser()
|
||||
a = &acc
|
||||
} else if err = s.repo.LoadAccount(ctx, hit.ID, a); err != nil {
|
||||
s.log.Error().Err(err).Str("account", hit.ID).Msg("could not load account, skipping")
|
||||
} else if err = s.repo.LoadAccount(ctx, hit, a); err != nil {
|
||||
s.log.Error().Err(err).Str("account", hit).Msg("could not load account, skipping")
|
||||
continue
|
||||
}
|
||||
var currentHash string
|
||||
if a.PasswordProfile != nil {
|
||||
currentHash = a.PasswordProfile.Password
|
||||
}
|
||||
|
||||
s.debugLogAccount(a).Msg("found account")
|
||||
|
||||
if password != "" {
|
||||
if a.PasswordProfile == nil {
|
||||
s.debugLogAccount(a).Msg("no password profile")
|
||||
return merrors.Unauthorized(s.id, "invalid password")
|
||||
}
|
||||
if !s.passwordIsValid(currentHash, password) {
|
||||
return merrors.Unauthorized(s.id, "invalid password")
|
||||
}
|
||||
}
|
||||
// TODO add groups if requested
|
||||
// if in.FieldMask ...
|
||||
s.expandMemberOf(a)
|
||||
@@ -232,6 +196,10 @@ func (s Service) ListAccounts(ctx context.Context, in *proto.ListAccountsRequest
|
||||
return
|
||||
}
|
||||
|
||||
func (s Service) findAccountsByQuery(ctx context.Context, query string) ([]string, error) {
|
||||
return s.index.Query(&proto.Account{}, query)
|
||||
}
|
||||
|
||||
// GetAccount implements the AccountsServiceHandler interface
|
||||
func (s Service) GetAccount(ctx context.Context, in *proto.GetAccountRequest, out *proto.Account) (err error) {
|
||||
if !s.hasAccountManagementPermissions(ctx) {
|
||||
@@ -277,35 +245,43 @@ func (s Service) CreateAccount(ctx context.Context, in *proto.CreateAccountReque
|
||||
accLock.Lock()
|
||||
defer accLock.Unlock()
|
||||
var id string
|
||||
var acc = in.Account
|
||||
if acc == nil {
|
||||
return merrors.BadRequest(s.id, "account missing")
|
||||
}
|
||||
if acc.Id == "" {
|
||||
acc.Id = uuid.Must(uuid.NewV4()).String()
|
||||
}
|
||||
if !s.isValidUsername(acc.PreferredName) {
|
||||
return merrors.BadRequest(s.id, "preferred_name '%s' must be at least the local part of an email", acc.PreferredName)
|
||||
}
|
||||
if !s.isValidEmail(acc.Mail) {
|
||||
return merrors.BadRequest(s.id, "mail '%s' must be a valid email", acc.Mail)
|
||||
|
||||
if in.Account == nil {
|
||||
return merrors.InternalServerError(s.id, "invalid account: empty")
|
||||
}
|
||||
|
||||
if id, err = cleanupID(acc.Id); err != nil {
|
||||
p.Merge(out, in.Account)
|
||||
|
||||
if out.Id == "" {
|
||||
out.Id = uuid.Must(uuid.NewV4()).String()
|
||||
}
|
||||
if err = validateAccount(s.id, out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if id, err = cleanupID(out.Id); err != nil {
|
||||
return merrors.InternalServerError(s.id, "could not clean up account id: %v", err.Error())
|
||||
}
|
||||
|
||||
if acc.PasswordProfile != nil {
|
||||
if acc.PasswordProfile.Password != "" {
|
||||
exists, err := s.accountExists(ctx, out.PreferredName, out.Mail, out.Id)
|
||||
if err != nil {
|
||||
return merrors.InternalServerError(s.id, "could not check if account exists: %v", err.Error())
|
||||
}
|
||||
if exists {
|
||||
return merrors.BadRequest(s.id, "account already exists")
|
||||
}
|
||||
|
||||
if out.PasswordProfile != nil {
|
||||
if out.PasswordProfile.Password != "" {
|
||||
// encrypt password
|
||||
c := crypt.New(crypt.SHA512)
|
||||
if acc.PasswordProfile.Password, err = c.Generate([]byte(acc.PasswordProfile.Password), nil); err != nil {
|
||||
if out.PasswordProfile.Password, err = c.Generate([]byte(out.PasswordProfile.Password), nil); err != nil {
|
||||
s.log.Error().Err(err).Str("id", id).Msg("could not hash password")
|
||||
return merrors.InternalServerError(s.id, "could not hash password: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err := passwordPoliciesValid(acc.PasswordProfile.PasswordPolicies); err != nil {
|
||||
if err := passwordPoliciesValid(out.PasswordProfile.PasswordPolicies); err != nil {
|
||||
return merrors.BadRequest(s.id, "%s", err)
|
||||
}
|
||||
}
|
||||
@@ -314,27 +290,54 @@ func (s Service) CreateAccount(ctx context.Context, in *proto.CreateAccountReque
|
||||
// TODO groups should be ignored during create, use groups.AddMember? return error?
|
||||
|
||||
// write and index account - note: don't do anything else in between!
|
||||
if err = s.repo.WriteAccount(ctx, acc); err != nil {
|
||||
if err = s.repo.WriteAccount(ctx, out); err != nil {
|
||||
s.log.Error().Err(err).Str("id", id).Msg("could not persist new account")
|
||||
s.debugLogAccount(acc).Msg("could not persist new account")
|
||||
s.debugLogAccount(out).Msg("could not persist new account")
|
||||
return merrors.InternalServerError(s.id, "could not persist new account: %v", err.Error())
|
||||
}
|
||||
if err = s.indexAccount(acc.Id); err != nil {
|
||||
return merrors.InternalServerError(s.id, "could not index new account: %v", err.Error())
|
||||
}
|
||||
s.log.Debug().Interface("account", acc).Msg("account after indexing")
|
||||
indexResults, err := s.index.Add(out)
|
||||
if err != nil {
|
||||
s.rollbackCreateAccount(ctx, out)
|
||||
return merrors.BadRequest(s.id, "Account already exists %v", err.Error())
|
||||
|
||||
if acc.PasswordProfile != nil {
|
||||
acc.PasswordProfile.Password = ""
|
||||
}
|
||||
s.log.Debug().Interface("account", out).Msg("account after indexing")
|
||||
|
||||
for _, r := range indexResults {
|
||||
if r.Field == "UidNumber" {
|
||||
id, err := strconv.Atoi(path.Base(r.Value))
|
||||
if err != nil {
|
||||
s.rollbackCreateAccount(ctx, out)
|
||||
return err
|
||||
}
|
||||
out.UidNumber = int64(id)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
out.Id = acc.Id
|
||||
out.Mail = acc.Mail
|
||||
out.PreferredName = acc.PreferredName
|
||||
out.AccountEnabled = acc.AccountEnabled
|
||||
out.DisplayName = acc.DisplayName
|
||||
out.OnPremisesSamAccountName = acc.OnPremisesSamAccountName
|
||||
if out.GidNumber == 0 {
|
||||
out.GidNumber = userDefaultGID
|
||||
}
|
||||
|
||||
r := proto.ListGroupsResponse{}
|
||||
err = s.ListGroups(ctx, &proto.ListGroupsRequest{}, &r)
|
||||
if err != nil {
|
||||
// rollback account creation
|
||||
return err
|
||||
}
|
||||
|
||||
for _, group := range r.Groups {
|
||||
if group.GidNumber == out.GidNumber {
|
||||
out.MemberOf = append(out.MemberOf, group)
|
||||
}
|
||||
}
|
||||
//acc.MemberOf = append(acc.MemberOf, &group)
|
||||
if err := s.repo.WriteAccount(context.Background(), out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if out.PasswordProfile != nil {
|
||||
out.PasswordProfile.Password = ""
|
||||
}
|
||||
|
||||
// TODO: assign user role to all new users for now, as create Account request does not have any role field
|
||||
@@ -342,7 +345,7 @@ func (s Service) CreateAccount(ctx context.Context, in *proto.CreateAccountReque
|
||||
return merrors.InternalServerError(s.id, "could not assign role to account: roleService not configured")
|
||||
}
|
||||
if _, err = s.RoleService.AssignRoleToUser(ctx, &settings.AssignRoleToUserRequest{
|
||||
AccountUuid: acc.Id,
|
||||
AccountUuid: out.Id,
|
||||
RoleId: settings_svc.BundleUUIDRoleUser,
|
||||
}); err != nil {
|
||||
return merrors.InternalServerError(s.id, "could not assign role to account: %v", err.Error())
|
||||
@@ -351,6 +354,18 @@ func (s Service) CreateAccount(ctx context.Context, in *proto.CreateAccountReque
|
||||
return
|
||||
}
|
||||
|
||||
// rollbackCreateAccount tries to rollback changes made by `CreateAccount` if parts of it failed.
|
||||
func (s Service) rollbackCreateAccount(ctx context.Context, acc *proto.Account) {
|
||||
err := s.index.Delete(acc)
|
||||
if err != nil {
|
||||
s.log.Err(err).Msg("failed to rollback account from indices")
|
||||
}
|
||||
err = s.repo.DeleteAccount(ctx, acc.Id)
|
||||
if err != nil {
|
||||
s.log.Err(err).Msg("failed to rollback account from repo")
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateAccount implements the AccountsServiceHandler interface
|
||||
// read only fields are ignored
|
||||
// TODO how can we unset specific values? using the update mask
|
||||
@@ -373,8 +388,6 @@ func (s Service) UpdateAccount(ctx context.Context, in *proto.UpdateAccountReque
|
||||
return merrors.InternalServerError(s.id, "could not clean up account id: %v", err.Error())
|
||||
}
|
||||
|
||||
path := filepath.Join(s.Config.Server.AccountsDataPath, "accounts", id)
|
||||
|
||||
if err = s.repo.LoadAccount(ctx, id, out); err != nil {
|
||||
if storage.IsNotFoundErr(err) {
|
||||
return merrors.NotFound(s.id, "account not found: %v", err.Error())
|
||||
@@ -396,6 +409,24 @@ func (s Service) UpdateAccount(ctx context.Context, in *proto.UpdateAccountReque
|
||||
return merrors.BadRequest(s.id, "%s", err)
|
||||
}
|
||||
|
||||
if _, exists := validMask.Filter("PreferredName"); exists {
|
||||
if err = validateAccountPreferredName(s.id, in.Account); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, exists := validMask.Filter("OnPremisesSamAccountName"); exists {
|
||||
if err = validateAccountOnPremisesSamAccountName(s.id, in.Account); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, exists := validMask.Filter("Mail"); exists {
|
||||
if in.Account.Mail != "" {
|
||||
if err = validateAccountEmail(s.id, in.Account); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := fieldmask_utils.StructToStruct(validMask, in.Account, out); err != nil {
|
||||
return merrors.InternalServerError(s.id, "%s", err)
|
||||
}
|
||||
@@ -434,13 +465,20 @@ func (s Service) UpdateAccount(ctx context.Context, in *proto.UpdateAccountReque
|
||||
out.ExternalUserStateChangeDateTime = tsnow
|
||||
}
|
||||
|
||||
// We need to reload the old account state to be able to compute the update
|
||||
old := &proto.Account{}
|
||||
if err = s.repo.LoadAccount(ctx, id, old); err != nil {
|
||||
s.log.Error().Err(err).Str("id", out.Id).Msg("could not load old account representation during update, maybe the account got deleted meanwhile?")
|
||||
return merrors.InternalServerError(s.id, "could not load current account for update: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = s.repo.WriteAccount(ctx, out); err != nil {
|
||||
s.log.Error().Err(err).Str("id", out.Id).Msg("could not persist updated account")
|
||||
return merrors.InternalServerError(s.id, "could not persist updated account: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = s.indexAccount(id); err != nil {
|
||||
s.log.Error().Err(err).Str("id", id).Str("path", path).Msg("could not index new account")
|
||||
if err = s.index.Update(old, out); err != nil {
|
||||
s.log.Error().Err(err).Str("id", id).Msg("could not index new account")
|
||||
return merrors.InternalServerError(s.id, "could not index updated account: %v", err.Error())
|
||||
}
|
||||
|
||||
@@ -514,7 +552,7 @@ func (s Service) DeleteAccount(ctx context.Context, in *proto.DeleteAccountReque
|
||||
return merrors.InternalServerError(s.id, "could not remove account: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = s.index.Delete(id); err != nil {
|
||||
if err = s.index.Delete(a); err != nil {
|
||||
s.log.Error().Err(err).Str("id", id).Str("accountId", id).Msg("could not remove account from index")
|
||||
return merrors.InternalServerError(s.id, "could not remove account from index: %v", err.Error())
|
||||
}
|
||||
@@ -523,12 +561,46 @@ func (s Service) DeleteAccount(ctx context.Context, in *proto.DeleteAccountReque
|
||||
return
|
||||
}
|
||||
|
||||
func validateAccount(serviceID string, a *proto.Account) error {
|
||||
if err := validateAccountPreferredName(serviceID, a); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateAccountOnPremisesSamAccountName(serviceID, a); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateAccountEmail(serviceID, a); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAccountPreferredName(serviceID string, a *proto.Account) error {
|
||||
if !isValidUsername(a.PreferredName) {
|
||||
return merrors.BadRequest(serviceID, "preferred_name '%s' must be at least the local part of an email", a.PreferredName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAccountOnPremisesSamAccountName(serviceID string, a *proto.Account) error {
|
||||
if !isValidUsername(a.OnPremisesSamAccountName) {
|
||||
return merrors.BadRequest(serviceID, "on_premises_sam_account_name '%s' must be at least the local part of an email", a.OnPremisesSamAccountName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAccountEmail(serviceID string, a *proto.Account) error {
|
||||
if !isValidEmail(a.Mail) {
|
||||
return merrors.BadRequest(serviceID, "mail '%s' must be a valid email", a.Mail)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// We want to allow email addresses as usernames so they show up when using them in ACLs on storages that allow intergration with our glauth LDAP service
|
||||
// so we are adding a few restrictions from https://stackoverflow.com/questions/6949667/what-are-the-real-rules-for-linux-usernames-on-centos-6-and-rhel-6
|
||||
// names should not start with numbers
|
||||
var usernameRegex = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]*(@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)*$")
|
||||
|
||||
func (s Service) isValidUsername(e string) bool {
|
||||
func isValidUsername(e string) bool {
|
||||
if len(e) < 1 && len(e) > 254 {
|
||||
return false
|
||||
}
|
||||
@@ -538,7 +610,7 @@ func (s Service) isValidUsername(e string) bool {
|
||||
// regex from https://www.w3.org/TR/2016/REC-html51-20161101/sec-forms.html#valid-e-mail-address
|
||||
var emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
|
||||
|
||||
func (s Service) isValidEmail(e string) bool {
|
||||
func isValidEmail(e string) bool {
|
||||
if len(e) < 3 && len(e) > 254 {
|
||||
return false
|
||||
}
|
||||
@@ -613,3 +685,56 @@ func (s Service) debugLogAccount(a *proto.Account) *zerolog.Event {
|
||||
"DeletedDateTime": a.DeletedDateTime,
|
||||
})
|
||||
}
|
||||
|
||||
func (s Service) accountExists(ctx context.Context, username, mail, id string) (exists bool, err error) {
|
||||
var ids []string
|
||||
ids, err = s.index.FindBy(&proto.Account{}, "preferred_name", username)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(ids) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
ids, err = s.index.FindBy(&proto.Account{}, "on_premises_sam_account_name", username)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(ids) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
ids, err = s.index.FindBy(&proto.Account{}, "mail", mail)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(ids) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
a := &proto.Account{}
|
||||
err = s.repo.LoadAccount(ctx, id, a)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if !storage.IsNotFoundErr(err) {
|
||||
return true, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func getAuthQueryMatch(query string) (match []string, authRequest bool) {
|
||||
match = authQuery.FindStringSubmatch(query)
|
||||
return match, len(match) == 3
|
||||
}
|
||||
|
||||
func isPasswordValid(logger log.Logger, hash string, pwd string) (ok bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logger.Error().Err(fmt.Errorf("%s", r)).Str("hash", hash).Msg("password lib panicked")
|
||||
}
|
||||
}()
|
||||
|
||||
c := crypt.NewFromHash(hash)
|
||||
return c.Verify(hash, []byte(pwd)) == nil
|
||||
}
|
||||
|
||||
@@ -2,34 +2,18 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/owncloud/ocis/accounts/pkg/storage"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/CiscoM31/godata"
|
||||
"github.com/blevesearch/bleve"
|
||||
"github.com/gofrs/uuid"
|
||||
p "github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
merrors "github.com/micro/go-micro/v2/errors"
|
||||
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
"github.com/owncloud/ocis/accounts/pkg/provider"
|
||||
"github.com/owncloud/ocis/accounts/pkg/storage"
|
||||
)
|
||||
|
||||
func (s Service) indexGroup(id string) error {
|
||||
g := &proto.BleveGroup{
|
||||
BleveType: "group",
|
||||
}
|
||||
if err := s.repo.LoadGroup(context.Background(), id, &g.Group); err != nil {
|
||||
s.log.Error().Err(err).Str("group", id).Msg("could not load group")
|
||||
return err
|
||||
}
|
||||
s.log.Debug().Interface("group", g).Msg("found group")
|
||||
if err := s.index.Index(g.Id, g); err != nil {
|
||||
s.log.Error().Err(err).Interface("group", g).Msg("could not index group")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Service) expandMembers(g *proto.Group) {
|
||||
if g == nil {
|
||||
return
|
||||
@@ -41,7 +25,7 @@ func (s Service) expandMembers(g *proto.Group) {
|
||||
if err := s.repo.LoadAccount(context.Background(), g.Members[i].Id, a); err == nil {
|
||||
expanded = append(expanded, a)
|
||||
} else {
|
||||
// log errors but continue execution for now
|
||||
// log errors but con/var/tmp/ocis-accounts-store-408341811tinue execution for now
|
||||
s.log.Error().Err(err).Str("id", g.Members[i].Id).Msg("could not load account")
|
||||
}
|
||||
}
|
||||
@@ -67,49 +51,25 @@ func (s Service) deflateMembers(g *proto.Group) {
|
||||
|
||||
// ListGroups implements the GroupsServiceHandler interface
|
||||
func (s Service) ListGroups(c context.Context, in *proto.ListGroupsRequest, out *proto.ListGroupsResponse) (err error) {
|
||||
|
||||
// only search for groups
|
||||
tq := bleve.NewTermQuery("group")
|
||||
tq.SetField("bleve_type")
|
||||
|
||||
query := bleve.NewConjunctionQuery(tq)
|
||||
|
||||
if in.Query != "" {
|
||||
// parse the query like an odata filter
|
||||
var q *godata.GoDataFilterQuery
|
||||
if q, err = godata.ParseFilterString(in.Query); err != nil {
|
||||
s.log.Error().Err(err).Msg("could not parse query")
|
||||
return merrors.InternalServerError(s.id, "could not parse query: %v", err.Error())
|
||||
}
|
||||
|
||||
// convert to bleve query
|
||||
bq, err := provider.BuildBleveQuery(q)
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msg("could not build bleve query")
|
||||
return merrors.InternalServerError(s.id, "could not build bleve query: %v", err.Error())
|
||||
}
|
||||
query.AddQuery(bq)
|
||||
}
|
||||
|
||||
s.log.Debug().Interface("query", query).Msg("using query")
|
||||
|
||||
searchRequest := bleve.NewSearchRequest(query)
|
||||
var searchResult *bleve.SearchResult
|
||||
searchResult, err = s.index.Search(searchRequest)
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msg("could not execute bleve search")
|
||||
return merrors.InternalServerError(s.id, "could not execute bleve search: %v", err.Error())
|
||||
}
|
||||
|
||||
s.log.Debug().Interface("result", searchResult).Msg("result")
|
||||
var searchResults []string
|
||||
|
||||
out.Groups = make([]*proto.Group, 0)
|
||||
if in.Query == "" {
|
||||
searchResults, _ = s.index.FindByPartial(&proto.Group{}, "DisplayName", "*")
|
||||
}
|
||||
|
||||
for _, hit := range searchResult.Hits {
|
||||
/*
|
||||
var startsWithIDQuery = regexp.MustCompile(`^startswith\(id,'(.*)'\)$`)
|
||||
match := startsWithIDQuery.FindStringSubmatch(in.Query)
|
||||
if len(match) == 2 {
|
||||
searchResults = []string{match[1]}
|
||||
}
|
||||
*/
|
||||
|
||||
for _, hit := range searchResults {
|
||||
g := &proto.Group{}
|
||||
if err = s.repo.LoadGroup(c, hit.ID, g); err != nil {
|
||||
s.log.Error().Err(err).Str("group", hit.ID).Msg("could not load group, skipping")
|
||||
if err = s.repo.LoadGroup(c, hit, g); err != nil {
|
||||
s.log.Error().Err(err).Str("group", hit).Msg("could not load group, skipping")
|
||||
continue
|
||||
}
|
||||
s.log.Debug().Interface("group", g).Msg("found group")
|
||||
@@ -150,33 +110,59 @@ func (s Service) GetGroup(c context.Context, in *proto.GetGroupRequest, out *pro
|
||||
|
||||
// CreateGroup implements the GroupsServiceHandler interface
|
||||
func (s Service) CreateGroup(c context.Context, in *proto.CreateGroupRequest, out *proto.Group) (err error) {
|
||||
var id string
|
||||
if in.Group == nil {
|
||||
return merrors.BadRequest(s.id, "account missing")
|
||||
return merrors.InternalServerError(s.id, "invalid group: empty")
|
||||
}
|
||||
if in.Group.Id == "" {
|
||||
in.Group.Id = uuid.Must(uuid.NewV4()).String()
|
||||
p.Merge(out, in.Group)
|
||||
|
||||
if out.Id == "" {
|
||||
out.Id = uuid.Must(uuid.NewV4()).String()
|
||||
}
|
||||
|
||||
if id, err = cleanupID(in.Group.Id); err != nil {
|
||||
if _, err = cleanupID(out.Id); err != nil {
|
||||
return merrors.InternalServerError(s.id, "could not clean up account id: %v", err.Error())
|
||||
}
|
||||
|
||||
// extract member id
|
||||
s.deflateMembers(in.Group)
|
||||
s.deflateMembers(out)
|
||||
|
||||
if err = s.repo.WriteGroup(c, in.Group); err != nil {
|
||||
s.log.Error().Err(err).Interface("group", in.Group).Msg("could not persist new group")
|
||||
if err = s.repo.WriteGroup(c, out); err != nil {
|
||||
s.log.Error().Err(err).Interface("group", out).Msg("could not persist new group")
|
||||
return merrors.InternalServerError(s.id, "could not persist new group: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = s.indexGroup(id); err != nil {
|
||||
indexResults, err := s.index.Add(out)
|
||||
if err != nil {
|
||||
s.rollbackCreateGroup(c, out)
|
||||
return merrors.InternalServerError(s.id, "could not index new group: %v", err.Error())
|
||||
}
|
||||
|
||||
for _, r := range indexResults {
|
||||
if r.Field == "GidNumber" {
|
||||
gid, err := strconv.Atoi(path.Base(r.Value))
|
||||
if err != nil {
|
||||
s.rollbackCreateGroup(c, out)
|
||||
return err
|
||||
}
|
||||
out.GidNumber = int64(gid)
|
||||
return s.repo.WriteGroup(context.Background(), out)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// rollbackCreateGroup tries to rollback changes made by `CreateGroup` if parts of it failed.
|
||||
func (s Service) rollbackCreateGroup(ctx context.Context, group *proto.Group) {
|
||||
err := s.index.Delete(group)
|
||||
if err != nil {
|
||||
s.log.Err(err).Msg("failed to rollback group from indices")
|
||||
}
|
||||
err = s.repo.DeleteGroup(ctx, group.Id)
|
||||
if err != nil {
|
||||
s.log.Err(err).Msg("failed to rollback group from repo")
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateGroup implements the GroupsServiceHandler interface
|
||||
func (s Service) UpdateGroup(c context.Context, in *proto.UpdateGroupRequest, out *proto.Group) (err error) {
|
||||
return merrors.InternalServerError(s.id, "not implemented")
|
||||
@@ -217,7 +203,7 @@ func (s Service) DeleteGroup(c context.Context, in *proto.DeleteGroupRequest, ou
|
||||
return merrors.InternalServerError(s.id, "could not load group: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = s.index.Delete(id); err != nil {
|
||||
if err = s.index.Delete(g); err != nil {
|
||||
s.log.Error().Err(err).Str("id", id).Str("path", path).Msg("could not remove group from index")
|
||||
return merrors.InternalServerError(s.id, "could not remove group from index: %v", err.Error())
|
||||
}
|
||||
|
||||
108
accounts/pkg/service/v0/index.go
Normal file
108
accounts/pkg/service/v0/index.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/owncloud/ocis/accounts/pkg/storage"
|
||||
|
||||
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
"github.com/owncloud/ocis/ocis-pkg/indexer"
|
||||
"github.com/owncloud/ocis/ocis-pkg/indexer/config"
|
||||
"github.com/owncloud/ocis/ocis-pkg/indexer/option"
|
||||
)
|
||||
|
||||
// RebuildIndex deletes all indices (in memory and on storage) and rebuilds them from scratch.
|
||||
func (s Service) RebuildIndex(ctx context.Context, request *proto.RebuildIndexRequest, response *proto.RebuildIndexResponse) error {
|
||||
if err := s.index.Reset(); err != nil {
|
||||
return fmt.Errorf("failed to delete index containers: %w", err)
|
||||
}
|
||||
|
||||
c, err := configFromSvc(s.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := recreateContainers(s.index, c); err != nil {
|
||||
return fmt.Errorf("failed to recreate index containers: %w", err)
|
||||
}
|
||||
|
||||
if err := reindexDocuments(ctx, s.repo, s.index); err != nil {
|
||||
return fmt.Errorf("failed to reindex documents: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// recreateContainers adds all indices to the indexer that we have for this service.
|
||||
func recreateContainers(idx *indexer.Indexer, cfg *config.Config) error {
|
||||
// Accounts
|
||||
if err := idx.AddIndex(&proto.Account{}, "Id", "Id", "accounts", "non_unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idx.AddIndex(&proto.Account{}, "DisplayName", "Id", "accounts", "non_unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := idx.AddIndex(&proto.Account{}, "Mail", "Id", "accounts", "unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idx.AddIndex(&proto.Account{}, "OnPremisesSamAccountName", "Id", "accounts", "unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idx.AddIndex(&proto.Account{}, "PreferredName", "Id", "accounts", "unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idx.AddIndex(&proto.Account{}, "UidNumber", "Id", "accounts", "autoincrement", &option.Bound{
|
||||
Lower: cfg.Index.UID.Lower,
|
||||
Upper: cfg.Index.UID.Upper,
|
||||
}, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Groups
|
||||
if err := idx.AddIndex(&proto.Group{}, "OnPremisesSamAccountName", "Id", "groups", "unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idx.AddIndex(&proto.Group{}, "DisplayName", "Id", "groups", "non_unique", nil, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idx.AddIndex(&proto.Group{}, "GidNumber", "Id", "groups", "autoincrement", &option.Bound{
|
||||
Lower: cfg.Index.GID.Lower,
|
||||
Upper: cfg.Index.GID.Upper,
|
||||
}, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// reindexDocuments loads all existing documents and adds them to the index.
|
||||
func reindexDocuments(ctx context.Context, repo storage.Repo, index *indexer.Indexer) error {
|
||||
accounts := make([]*proto.Account, 0)
|
||||
if err := repo.LoadAccounts(ctx, &accounts); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range accounts {
|
||||
_, err := index.Add(accounts[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
groups := make([]*proto.Group, 0)
|
||||
if err := repo.LoadGroups(ctx, &groups); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range groups {
|
||||
_, err := index.Add(groups[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -3,19 +3,17 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/owncloud/ocis/accounts/pkg/storage"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/blevesearch/bleve"
|
||||
"github.com/blevesearch/bleve/analysis/analyzer/custom"
|
||||
"github.com/blevesearch/bleve/analysis/analyzer/keyword"
|
||||
"github.com/blevesearch/bleve/analysis/analyzer/simple"
|
||||
"github.com/blevesearch/bleve/analysis/analyzer/standard"
|
||||
"github.com/blevesearch/bleve/analysis/token/lowercase"
|
||||
"github.com/blevesearch/bleve/analysis/tokenizer/unicode"
|
||||
"github.com/owncloud/ocis/accounts/pkg/storage"
|
||||
"github.com/owncloud/ocis/ocis-pkg/indexer"
|
||||
idxcfg "github.com/owncloud/ocis/ocis-pkg/indexer/config"
|
||||
idxerrs "github.com/owncloud/ocis/ocis-pkg/indexer/errors"
|
||||
|
||||
mclient "github.com/micro/go-micro/v2/client"
|
||||
"github.com/owncloud/ocis/accounts/pkg/config"
|
||||
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
@@ -25,6 +23,9 @@ import (
|
||||
settings_svc "github.com/owncloud/ocis/settings/pkg/service/v0"
|
||||
)
|
||||
|
||||
// userDefaultGID is the default integer representing the "users" group.
|
||||
const userDefaultGID = 30000
|
||||
|
||||
// New returns a new instance of Service
|
||||
func New(opts ...Option) (s *Service, err error) {
|
||||
options := newOptions(opts...)
|
||||
@@ -72,92 +73,73 @@ func New(opts ...Option) (s *Service, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s Service) buildIndex() (index bleve.Index, err error) {
|
||||
indexDir := filepath.Join(s.Config.Server.AccountsDataPath, "index.bleve")
|
||||
if index, err = bleve.Open(indexDir); err != nil {
|
||||
if err != bleve.ErrorIndexPathDoesNotExist {
|
||||
s.log.Error().Err(err).Msg("failed to read index")
|
||||
return
|
||||
func (s Service) buildIndex() (*indexer.Indexer, error) {
|
||||
var indexcfg *idxcfg.Config
|
||||
|
||||
indexcfg, err := configFromSvc(s.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idx := indexer.CreateIndexer(indexcfg)
|
||||
|
||||
if err := recreateContainers(idx, indexcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
// configFromSvc creates an index config out of a service configuration. This intermediate step exists
|
||||
// because the index config was mapped after the service config.
|
||||
func configFromSvc(cfg *config.Config) (*idxcfg.Config, error) {
|
||||
c := idxcfg.New()
|
||||
|
||||
defer func(cfg *config.Config) {
|
||||
l := log.NewLogger(log.Color(cfg.Log.Color), log.Pretty(cfg.Log.Pretty), log.Level(cfg.Log.Level))
|
||||
if r := recover(); r != nil {
|
||||
l.Error().
|
||||
Str("panic", "recovered from panic while parsing index config from service configuration").
|
||||
Interface("svc_config", cfg).
|
||||
Msg("recovered from panic")
|
||||
}
|
||||
}(cfg)
|
||||
|
||||
indexMapping := bleve.NewIndexMapping()
|
||||
// keep all symbols in terms to allow exact maching, eg. emails
|
||||
indexMapping.DefaultAnalyzer = keyword.Name
|
||||
// TODO don't bother to store fields as we will load the account from disk
|
||||
|
||||
// Reusable mapping for text
|
||||
standardTextFieldMapping := bleve.NewTextFieldMapping()
|
||||
standardTextFieldMapping.Analyzer = standard.Name
|
||||
standardTextFieldMapping.Store = false
|
||||
|
||||
// Reusable mapping for text, uses english stop word removal
|
||||
simpleTextFieldMapping := bleve.NewTextFieldMapping()
|
||||
simpleTextFieldMapping.Analyzer = simple.Name
|
||||
simpleTextFieldMapping.Store = false
|
||||
|
||||
// Reusable mapping for keyword text
|
||||
keywordFieldMapping := bleve.NewTextFieldMapping()
|
||||
keywordFieldMapping.Analyzer = keyword.Name
|
||||
keywordFieldMapping.Store = false
|
||||
|
||||
// Reusable mapping for lowercase text
|
||||
err = indexMapping.AddCustomAnalyzer("lowercase",
|
||||
map[string]interface{}{
|
||||
"type": custom.Name,
|
||||
"tokenizer": unicode.Name,
|
||||
"token_filters": []string{
|
||||
lowercase.Name,
|
||||
if (config.Repo{}) != cfg.Repo {
|
||||
if (config.Disk{}) != cfg.Repo.Disk {
|
||||
c.Repo = idxcfg.Repo{
|
||||
Disk: idxcfg.Disk{
|
||||
Path: cfg.Repo.Disk.Path,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
lowercaseTextFieldMapping := bleve.NewTextFieldMapping()
|
||||
lowercaseTextFieldMapping.Analyzer = "lowercase"
|
||||
lowercaseTextFieldMapping.Store = true
|
||||
|
||||
// accounts
|
||||
accountMapping := bleve.NewDocumentMapping()
|
||||
indexMapping.AddDocumentMapping("account", accountMapping)
|
||||
|
||||
// Text
|
||||
accountMapping.AddFieldMappingsAt("display_name", standardTextFieldMapping)
|
||||
accountMapping.AddFieldMappingsAt("description", standardTextFieldMapping)
|
||||
|
||||
// Lowercase
|
||||
accountMapping.AddFieldMappingsAt("on_premises_sam_account_name", lowercaseTextFieldMapping)
|
||||
accountMapping.AddFieldMappingsAt("preferred_name", lowercaseTextFieldMapping)
|
||||
|
||||
// Keywords
|
||||
accountMapping.AddFieldMappingsAt("mail", keywordFieldMapping)
|
||||
|
||||
// groups
|
||||
groupMapping := bleve.NewDocumentMapping()
|
||||
indexMapping.AddDocumentMapping("group", groupMapping)
|
||||
|
||||
// Text
|
||||
groupMapping.AddFieldMappingsAt("display_name", standardTextFieldMapping)
|
||||
groupMapping.AddFieldMappingsAt("description", standardTextFieldMapping)
|
||||
|
||||
// Lowercase
|
||||
groupMapping.AddFieldMappingsAt("on_premises_sam_account_name", lowercaseTextFieldMapping)
|
||||
|
||||
// Tell blevesearch how to determine the type of the structs that are indexed.
|
||||
// The referenced field needs to match the struct field exactly and it must be public.
|
||||
// See pkg/proto/v0/bleve.go how we wrap the generated Account and Group to add a
|
||||
// BleveType property which is indexed as `bleve_type` so we can also distinguish the
|
||||
// documents in the index by querying for that property.
|
||||
indexMapping.TypeField = "BleveType"
|
||||
|
||||
// for now recreate index on every start
|
||||
if err = os.RemoveAll(indexDir); err != nil {
|
||||
return
|
||||
if (config.CS3{}) != cfg.Repo.CS3 {
|
||||
c.Repo = idxcfg.Repo{
|
||||
CS3: idxcfg.CS3{
|
||||
ProviderAddr: cfg.Repo.CS3.ProviderAddr,
|
||||
DataURL: cfg.Repo.CS3.DataURL,
|
||||
DataPrefix: cfg.Repo.CS3.DataPrefix,
|
||||
JWTSecret: cfg.Repo.CS3.JWTSecret,
|
||||
},
|
||||
}
|
||||
}
|
||||
if index, err = bleve.New(indexDir, indexMapping); err != nil {
|
||||
return nil, err
|
||||
|
||||
if (config.Index{}) != cfg.Index {
|
||||
c.Index = idxcfg.Index{
|
||||
UID: idxcfg.Bound{
|
||||
Lower: cfg.Index.UID.Lower,
|
||||
},
|
||||
GID: idxcfg.Bound{
|
||||
Lower: cfg.Index.GID.Lower,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ServiceUser{}) != cfg.ServiceUser {
|
||||
c.ServiceUser = cfg.ServiceUser
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s Service) createDefaultAccounts() (err error) {
|
||||
@@ -275,8 +257,35 @@ func (s Service) createDefaultAccounts() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.indexAccount(accounts[i].Id); err != nil {
|
||||
return err
|
||||
results, err := s.index.Add(&accounts[i])
|
||||
if err != nil {
|
||||
if idxerrs.IsAlreadyExistsErr(err) {
|
||||
continue
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can be removed again as soon as we respect the predefined UIDs and GIDs from the account. Then no autoincrement is happening, therefore we don't need to update accounts.
|
||||
changed := false
|
||||
for _, r := range results {
|
||||
if r.Field == "UidNumber" || r.Field == "GidNumber" {
|
||||
id, err := strconv.ParseInt(path.Base(r.Value), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r.Field == "UidNumber" {
|
||||
accounts[i].UidNumber = id
|
||||
} else {
|
||||
accounts[i].GidNumber = id
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
if err := s.repo.WriteAccount(context.Background(), &accounts[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,8 +346,28 @@ func (s Service) createDefaultGroups() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.indexGroup(groups[i].Id); err != nil {
|
||||
return err
|
||||
results, err := s.index.Add(&groups[i])
|
||||
if err != nil {
|
||||
if idxerrs.IsAlreadyExistsErr(err) {
|
||||
continue
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can be removed again as soon as we respect the predefined GIDs from the group. Then no autoincrement is happening, therefore we don't need to update groups.
|
||||
for _, r := range results {
|
||||
if r.Field == "GidNumber" {
|
||||
gid, err := strconv.ParseInt(path.Base(r.Value), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groups[i].GidNumber = gid
|
||||
if err := s.repo.WriteGroup(context.Background(), &groups[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -374,7 +403,7 @@ type Service struct {
|
||||
id string
|
||||
log log.Logger
|
||||
Config *config.Config
|
||||
index bleve.Index
|
||||
index *indexer.Indexer
|
||||
RoleService settings.RoleService
|
||||
RoleManager *roles.Manager
|
||||
repo storage.Repo
|
||||
|
||||
1
accounts/pkg/service/v0/staticcheck.conf
Normal file
1
accounts/pkg/service/v0/staticcheck.conf
Normal file
@@ -0,0 +1 @@
|
||||
checks = ["all", "-ST1003", "-ST1000", "-SA1019"]
|
||||
@@ -8,16 +8,20 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
v1beta11 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/pkg/token"
|
||||
"github.com/cs3org/reva/pkg/token/manager/jwt"
|
||||
"github.com/owncloud/ocis/accounts/pkg/config"
|
||||
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
olog "github.com/owncloud/ocis/ocis-pkg/log"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
@@ -73,8 +77,14 @@ func (r CS3Repo) WriteAccount(ctx context.Context, a *proto.Account) (err error)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.dataProvider.put(r.accountURL(a.Id), bytes.NewReader(by), t)
|
||||
return err
|
||||
resp, err := r.dataProvider.put(r.accountURL(a.Id), bytes.NewReader(by), t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = resp.Body.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadAccount loads an account via cs3 by id and writes it to the provided account
|
||||
@@ -84,12 +94,46 @@ func (r CS3Repo) LoadAccount(ctx context.Context, id string, a *proto.Account) (
|
||||
return err
|
||||
}
|
||||
|
||||
return r.loadAccount(id, t, a)
|
||||
}
|
||||
|
||||
// LoadAccounts loads all the accounts from the cs3 api
|
||||
func (r CS3Repo) LoadAccounts(ctx context.Context, a *[]*proto.Account) (err error) {
|
||||
t, err := r.authenticate(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, t)
|
||||
res, err := r.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{
|
||||
Ref: &provider.Reference{
|
||||
Spec: &provider.Reference_Path{Path: path.Join("/meta", accountsFolder)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log := olog.NewLogger(olog.Pretty(r.cfg.Log.Pretty), olog.Color(r.cfg.Log.Color), olog.Level(r.cfg.Log.Level))
|
||||
for i := range res.Infos {
|
||||
acc := &proto.Account{}
|
||||
err := r.loadAccount(filepath.Base(res.Infos[i].Path), t, acc)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("could not load account")
|
||||
continue
|
||||
}
|
||||
*a = append(*a, acc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r CS3Repo) loadAccount(id string, t string, a *proto.Account) error {
|
||||
resp, err := r.dataProvider.get(r.accountURL(id), t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return ¬FoundErr{"account", id}
|
||||
}
|
||||
|
||||
@@ -147,8 +191,14 @@ func (r CS3Repo) WriteGroup(ctx context.Context, g *proto.Group) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.dataProvider.put(r.groupURL(g.Id), bytes.NewReader(by), t)
|
||||
return err
|
||||
resp, err := r.dataProvider.put(r.groupURL(g.Id), bytes.NewReader(by), t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = resp.Body.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadGroup loads a group via cs3 by id and writes it to the provided group
|
||||
@@ -158,6 +208,40 @@ func (r CS3Repo) LoadGroup(ctx context.Context, id string, g *proto.Group) (err
|
||||
return err
|
||||
}
|
||||
|
||||
return r.loadGroup(id, t, g)
|
||||
}
|
||||
|
||||
// LoadGroups loads all the groups from the cs3 api
|
||||
func (r CS3Repo) LoadGroups(ctx context.Context, g *[]*proto.Group) (err error) {
|
||||
t, err := r.authenticate(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, t)
|
||||
res, err := r.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{
|
||||
Ref: &provider.Reference{
|
||||
Spec: &provider.Reference_Path{Path: path.Join("/meta", groupsFolder)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log := olog.NewLogger(olog.Pretty(r.cfg.Log.Pretty), olog.Color(r.cfg.Log.Color), olog.Level(r.cfg.Log.Level))
|
||||
for i := range res.Infos {
|
||||
grp := &proto.Group{}
|
||||
err := r.loadGroup(filepath.Base(res.Infos[i].Path), t, grp)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("could not load account")
|
||||
continue
|
||||
}
|
||||
*g = append(*g, grp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r CS3Repo) loadGroup(id string, t string, g *proto.Group) error {
|
||||
resp, err := r.dataProvider.get(r.groupURL(id), t)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -205,14 +289,30 @@ func (r CS3Repo) DeleteGroup(ctx context.Context, id string) (err error) {
|
||||
}
|
||||
|
||||
func (r CS3Repo) authenticate(ctx context.Context) (token string, err error) {
|
||||
return AuthenticateCS3(ctx, r.cfg.ServiceUser, r.tm)
|
||||
}
|
||||
|
||||
// AuthenticateCS3 mints an auth token for communicating with cs3 storage based on a service user from config
|
||||
func AuthenticateCS3(ctx context.Context, su config.ServiceUser, tm token.Manager) (token string, err error) {
|
||||
u := &user.User{
|
||||
Id: &user.UserId{},
|
||||
Id: &user.UserId{
|
||||
OpaqueId: su.UUID,
|
||||
},
|
||||
Groups: []string{},
|
||||
Opaque: &types.Opaque{
|
||||
Map: map[string]*types.OpaqueEntry{
|
||||
"uid": {
|
||||
Decoder: "plain",
|
||||
Value: []byte(strconv.FormatInt(su.UID, 10)),
|
||||
},
|
||||
"gid": {
|
||||
Decoder: "plain",
|
||||
Value: []byte(strconv.FormatInt(su.GID, 10)),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if r.cfg.ServiceUser.Username != "" {
|
||||
u.Id.OpaqueId = r.cfg.ServiceUser.UUID
|
||||
}
|
||||
return r.tm.MintToken(ctx, u)
|
||||
return tm.MintToken(ctx, u)
|
||||
}
|
||||
|
||||
func (r CS3Repo) accountURL(id string) string {
|
||||
@@ -224,11 +324,16 @@ func (r CS3Repo) groupURL(id string) string {
|
||||
}
|
||||
|
||||
func (r CS3Repo) makeRootDirIfNotExist(ctx context.Context, folder string) error {
|
||||
return MakeDirIfNotExist(ctx, r.storageProvider, folder)
|
||||
}
|
||||
|
||||
// MakeDirIfNotExist will create a root node in the metadata storage. Requires an authenticated context.
|
||||
func MakeDirIfNotExist(ctx context.Context, sp provider.ProviderAPIClient, folder string) error {
|
||||
var rootPathRef = &provider.Reference{
|
||||
Spec: &provider.Reference_Path{Path: path.Join("/meta", folder)},
|
||||
}
|
||||
|
||||
resp, err := r.storageProvider.Stat(ctx, &provider.StatRequest{
|
||||
resp, err := sp.Stat(ctx, &provider.StatRequest{
|
||||
Ref: rootPathRef,
|
||||
})
|
||||
|
||||
@@ -237,7 +342,7 @@ func (r CS3Repo) makeRootDirIfNotExist(ctx context.Context, folder string) error
|
||||
}
|
||||
|
||||
if resp.Status.Code == v1beta11.Code_CODE_NOT_FOUND {
|
||||
_, err := r.storageProvider.CreateContainer(ctx, &provider.CreateContainerRequest{
|
||||
_, err := sp.CreateContainer(ctx, &provider.CreateContainerRequest{
|
||||
Ref: rootPathRef,
|
||||
})
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ var groupLock sync.Mutex
|
||||
|
||||
// DiskRepo provides a local filesystem implementation of the Repo interface
|
||||
type DiskRepo struct {
|
||||
cfg *config.Config
|
||||
log olog.Logger
|
||||
cfg *config.Config
|
||||
log olog.Logger
|
||||
}
|
||||
|
||||
// NewDiskRepo creates a new disk repo
|
||||
@@ -37,8 +37,8 @@ func NewDiskRepo(cfg *config.Config, log olog.Logger) DiskRepo {
|
||||
}
|
||||
}
|
||||
return DiskRepo{
|
||||
cfg: cfg,
|
||||
log: log,
|
||||
cfg: cfg,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,20 @@ func (r DiskRepo) LoadAccount(ctx context.Context, id string, a *proto.Account)
|
||||
return json.Unmarshal(data, a)
|
||||
}
|
||||
|
||||
// LoadAccounts loads all the accounts from the local filesystem
|
||||
func (r DiskRepo) LoadAccounts(ctx context.Context, a *[]*proto.Account) (err error) {
|
||||
root := filepath.Join(r.cfg.Repo.Disk.Path, accountsFolder)
|
||||
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
acc := &proto.Account{}
|
||||
if e := r.LoadAccount(ctx, filepath.Base(path), acc); e != nil {
|
||||
r.log.Err(e).Msg("could not load account")
|
||||
return nil
|
||||
}
|
||||
*a = append(*a, acc)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteAccount from the local filesystem
|
||||
func (r DiskRepo) DeleteAccount(ctx context.Context, id string) (err error) {
|
||||
path := filepath.Join(r.cfg.Repo.Disk.Path, accountsFolder, id)
|
||||
@@ -118,6 +132,20 @@ func (r DiskRepo) LoadGroup(ctx context.Context, id string, g *proto.Group) (err
|
||||
return json.Unmarshal(data, g)
|
||||
}
|
||||
|
||||
// LoadGroups loads all the groups from the local filesystem
|
||||
func (r DiskRepo) LoadGroups(ctx context.Context, g *[]*proto.Group) (err error) {
|
||||
root := filepath.Join(r.cfg.Repo.Disk.Path, groupsFolder)
|
||||
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
grp := &proto.Group{}
|
||||
if e := r.LoadGroup(ctx, filepath.Base(path), grp); e != nil {
|
||||
r.log.Err(e).Msg("could not load group")
|
||||
return nil
|
||||
}
|
||||
*g = append(*g, grp)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteGroup from the local filesystem
|
||||
func (r DiskRepo) DeleteGroup(ctx context.Context, id string) (err error) {
|
||||
path := filepath.Join(r.cfg.Repo.Disk.Path, groupsFolder, id)
|
||||
@@ -127,10 +155,7 @@ func (r DiskRepo) DeleteGroup(ctx context.Context, id string) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
//r.log.Error().Err(err).Str("id", id).Str("path", path).Msg("could not remove group")
|
||||
//return merrors.InternalServerError(r.serviceID, "could not remove group: %v", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// deflateMemberOf replaces the groups of a user with an instance that only contains the id
|
||||
|
||||
@@ -2,20 +2,23 @@ package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
|
||||
)
|
||||
|
||||
const (
|
||||
accountsFolder = "accounts"
|
||||
groupsFolder = "groups"
|
||||
groupsFolder = "groups"
|
||||
)
|
||||
|
||||
// Repo defines the storage operations
|
||||
type Repo interface {
|
||||
WriteAccount(ctx context.Context, a *proto.Account) (err error)
|
||||
LoadAccount(ctx context.Context, id string, a *proto.Account) (err error)
|
||||
LoadAccounts(ctx context.Context, a *[]*proto.Account) (err error)
|
||||
DeleteAccount(ctx context.Context, id string) (err error)
|
||||
WriteGroup(ctx context.Context, g *proto.Group) (err error)
|
||||
LoadGroup(ctx context.Context, id string, g *proto.Group) (err error)
|
||||
LoadGroups(ctx context.Context, g *[]*proto.Group) (err error)
|
||||
DeleteGroup(ctx context.Context, id string) (err error)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ const navItems = [
|
||||
name: 'accounts',
|
||||
path: `/${appInfo.id}/`
|
||||
},
|
||||
menu: 'user'
|
||||
menu: 'apps'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
</oc-grid>
|
||||
</template>
|
||||
<template v-else-if="hasFailed">
|
||||
<oc-alert variation="warning" no-close class="oc-m">
|
||||
<oc-alert variation="warning" no-close class="oc-m" id="accounts-list-loading-failed">
|
||||
<oc-icon name="warning" variation="warning" class="uk-float-left oc-mr-s" />
|
||||
<translate>You don't have permissions to manage accounts.</translate>
|
||||
</oc-alert>
|
||||
</template>
|
||||
<oc-loader v-else />
|
||||
<oc-loader id="accounts-list-loader" v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,14 +25,20 @@ module.exports = {
|
||||
},
|
||||
|
||||
selectRole: function (username, role) {
|
||||
const roleTrigger =
|
||||
util.format(this.elements.rowByUsername.selector, username) +
|
||||
this.elements.rolesDropdownTrigger.selector
|
||||
const roleSelector =
|
||||
util.format(this.elements.rowByUsername.selector, username) +
|
||||
util.format(this.elements.roleInRolesDropdown.selector, role)
|
||||
|
||||
return this
|
||||
.click('@rolesDropdownTrigger')
|
||||
.initAjaxCounters()
|
||||
.waitForElementVisible(roleTrigger)
|
||||
.click(roleTrigger)
|
||||
.waitForElementVisible(roleSelector)
|
||||
.click(roleSelector)
|
||||
.waitForOutstandingAjaxCalls()
|
||||
},
|
||||
|
||||
checkUsersRole: function (username, role) {
|
||||
@@ -114,7 +120,7 @@ module.exports = {
|
||||
locateStrategy: 'xpath'
|
||||
},
|
||||
roleInRolesDropdown: {
|
||||
selector: '//label[contains(@class, "accounts-roles-dropdown-role") and normalize-space()="%s"]',
|
||||
selector: '//label[contains(@class, "accounts-roles-dropdown-role")]/span[normalize-space()="%s"]',
|
||||
locateStrategy: 'xpath'
|
||||
},
|
||||
rolesDropdownTrigger: {
|
||||
@@ -122,11 +128,13 @@ module.exports = {
|
||||
locateStrategy: 'xpath'
|
||||
},
|
||||
loadingAccountsList: {
|
||||
selector: '//div[contains(@class, "oc-loader")]',
|
||||
locateStrategy: 'xpath'
|
||||
selector: '#accounts-list-loader'
|
||||
},
|
||||
loadingAccountsListFailed: {
|
||||
selector: '#accounts-list-loading-failed'
|
||||
},
|
||||
rowCheckbox: {
|
||||
selector: '//input[@class="oc-checkbox"]',
|
||||
selector: '//input[contains(@class, "oc-checkbox")]',
|
||||
locateStrategy: 'xpath'
|
||||
},
|
||||
batchActionDisable: {
|
||||
|
||||
@@ -33,8 +33,7 @@ Then('the displayed role of user {string} should be {string} on the WebUI', func
|
||||
Then('the user should not be able to see the accounts list on the WebUI', async function () {
|
||||
return client.page.accountsPage()
|
||||
.waitForAjaxCallsToStartAndFinish()
|
||||
.waitForElementVisible('@loadingAccountsList')
|
||||
.waitForElementNotPresent('@accountsListTable')
|
||||
.waitForElementVisible('@loadingAccountsListFailed')
|
||||
})
|
||||
|
||||
When('the user disables user/users {string} using the WebUI', function (usernames) {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- https://ocis-server:9200/oidc-callback.html
|
||||
- https://ocis-server:9200/
|
||||
origins:
|
||||
- https://ocis-server:9200
|
||||
|
||||
authorities:
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"server": "https://ocis-server:9200",
|
||||
"theme": "owncloud",
|
||||
"version": "0.1.0",
|
||||
"openIdConnect": {
|
||||
"metadata_url": "https://ocis-server:9200/.well-known/openid-configuration",
|
||||
"authority": "https://ocis-server:9200",
|
||||
"client_id": "phoenix",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile email"
|
||||
},
|
||||
"apps": [
|
||||
"files",
|
||||
"draw-io",
|
||||
"pdf-viewer",
|
||||
"markdown-editor",
|
||||
"media-viewer"
|
||||
],
|
||||
"external_apps": [
|
||||
{
|
||||
"id": "accounts",
|
||||
"path": "https://ocis-server:9200/accounts.js",
|
||||
"config": {
|
||||
"url": "https://ocis-server:9200"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1467,9 +1467,9 @@ binary-extensions@^2.0.0:
|
||||
integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
|
||||
|
||||
bl@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a"
|
||||
integrity sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489"
|
||||
integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
inherits "^2.0.4"
|
||||
@@ -4163,9 +4163,9 @@ lodash.union@^4.6.0:
|
||||
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
|
||||
|
||||
lodash@^4.15.0, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
|
||||
log-symbols@2.2.0:
|
||||
version "2.2.0"
|
||||
@@ -4488,10 +4488,10 @@ node-environment-flags@1.0.5:
|
||||
object.getownpropertydescriptors "^2.0.3"
|
||||
semver "^5.7.0"
|
||||
|
||||
node-fetch@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||
node-fetch@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
node-modules-regexp@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
||||
15
changelog/unreleased/accounts-fs-based-index.md
Normal file
15
changelog/unreleased/accounts-fs-based-index.md
Normal file
@@ -0,0 +1,15 @@
|
||||
Change: Filesystem based index
|
||||
|
||||
Tags: accounts, storage
|
||||
|
||||
We replaced `bleve` with a new filesystem based index implementation. There is an `indexer` which is capable of
|
||||
orchestrating different index types to build indices on documents by field. You can choose from the index types `unique`,
|
||||
`non-unique` or `autoincrement`. Indices can be utilized to run search queries (full matches or globbing) on document
|
||||
fields. The accounts service is using this index internally to run the search queries coming in via `ListAccounts` and
|
||||
`ListGroups` and to generate UIDs for new accounts as well as GIDs for new groups.
|
||||
|
||||
The accounts service can be configured to store the index on the local FS / a NFS (`disk` implementation of the index)
|
||||
or to use an arbitrary storage ( `cs3` implementation of the index). `cs3` is the new default, which is configured to
|
||||
use the `metadata` storage.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/709
|
||||
9
changelog/unreleased/accounts-index-rebuild.md
Normal file
9
changelog/unreleased/accounts-index-rebuild.md
Normal file
@@ -0,0 +1,9 @@
|
||||
Change: Rebuild index command for accounts
|
||||
|
||||
Tags: accounts
|
||||
|
||||
The index for the accounts service can now be rebuilt by running the cli command `./bin/ocis accounts rebuild`.
|
||||
It deletes all configured indices and rebuilds them from the documents found on storage. For this we also introduced
|
||||
a `LoadAccounts` and `LoadGroups` function on storage for loading all existing documents.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/748
|
||||
7
changelog/unreleased/cs3-index-lowerbound.md
Normal file
7
changelog/unreleased/cs3-index-lowerbound.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Bugfix: Lower Bound was not working for the cs3 api index implementation
|
||||
|
||||
Tags: accounts
|
||||
|
||||
Lower bound working on the cs3 index implementation
|
||||
|
||||
https://github.com/owncloud/ocis/pull/741
|
||||
@@ -0,0 +1,7 @@
|
||||
Bugfix: Fix id or username query handling
|
||||
|
||||
Tags: accounts
|
||||
|
||||
The code was stopping execution when encountering an error while loading an account by id. But for or queries we can continue execution.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/745
|
||||
7
changelog/unreleased/glauth-micro-client
Normal file
7
changelog/unreleased/glauth-micro-client
Normal file
@@ -0,0 +1,7 @@
|
||||
Bugfix: Use micro default client
|
||||
|
||||
Tags: glauth
|
||||
|
||||
We found a file descriptor leak in the glauth connections to the accounts service. Fixed it by using the micro default client.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/718
|
||||
7
changelog/unreleased/konnectd-consent-page
Normal file
7
changelog/unreleased/konnectd-consent-page
Normal file
@@ -0,0 +1,7 @@
|
||||
Change: Properly style konnectd consent page
|
||||
|
||||
Tags: konnectd
|
||||
|
||||
After bringing our theme into konnectd, we've had to adjust the styles of the consent page so the text is visible and button reflects our theme.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/754
|
||||
9
changelog/unreleased/konnectd-switchacc-consent.md
Normal file
9
changelog/unreleased/konnectd-switchacc-consent.md
Normal file
@@ -0,0 +1,9 @@
|
||||
Bugfix: Allow consent-prompt with switch-account
|
||||
|
||||
Multiple prompt values are allowed and this change fixes the check for
|
||||
select_account if it was used together with other prompt values. Where
|
||||
select_account previously was ignored, it is now processed as required,
|
||||
fixing the use case when a RP wants to trigger select_account first
|
||||
while at the same time wants also to request interactive consent.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/788
|
||||
8
changelog/unreleased/mint-token-with-uid.md
Normal file
8
changelog/unreleased/mint-token-with-uid.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Bugfix: Mint token with uid and gid
|
||||
|
||||
Tags: accounts
|
||||
|
||||
The eos driver expects the uid and gid from the opaque map of a user. While the proxy does mint tokens correctly, the accounts service wasn't.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/737
|
||||
|
||||
5
changelog/unreleased/move-indexer-to-ocis-pkg.md
Normal file
5
changelog/unreleased/move-indexer-to-ocis-pkg.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Change: Move the indexer package from ocis/accounts to ocis/ocis-pkg
|
||||
|
||||
We are making that change for semantic reasons. So consumers of any index don't necessarily need to know of the accounts service.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/794
|
||||
9
changelog/unreleased/ocs-map-userid-to-username.md
Normal file
9
changelog/unreleased/ocs-map-userid-to-username.md
Normal file
@@ -0,0 +1,9 @@
|
||||
Change: Remove username field in OCS
|
||||
|
||||
Tags: ocs
|
||||
|
||||
We use the incoming userid as both the `id` and the `on_premises_sam_account_name` for new accounts in the accounts
|
||||
service. The userid in OCS requests is in fact the username, not our internal account id. We need to enforce the userid
|
||||
as our internal account id though, because the account id is part of various `path` formats.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/709
|
||||
7
changelog/unreleased/phoenix-default-apps.md
Normal file
7
changelog/unreleased/phoenix-default-apps.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Change: Default apps in ownCloud Web
|
||||
|
||||
Tags: web
|
||||
|
||||
We changed the default apps for ownCloud Web to be only files and media-viewer. Markdown-editor and draw-io have been removed as defaults.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/688
|
||||
7
changelog/unreleased/prevent-duplicate-accounts.md
Normal file
7
changelog/unreleased/prevent-duplicate-accounts.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Bugfix: Don't create account if id/mail/username already taken
|
||||
|
||||
Tags: accounts
|
||||
|
||||
We don't allow anymore to create a new account if the provided id/mail/username is already taken.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/709
|
||||
7
changelog/unreleased/themed-kopano
Normal file
7
changelog/unreleased/themed-kopano
Normal file
@@ -0,0 +1,7 @@
|
||||
Change: Bring oC theme
|
||||
|
||||
Tags: konnectd
|
||||
|
||||
We've styled our konnectd login page to reflect ownCloud theme.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/698
|
||||
5
changelog/unreleased/update-glauth
Normal file
5
changelog/unreleased/update-glauth
Normal file
@@ -0,0 +1,5 @@
|
||||
Enhancement: Update glauth to dev 4f029234b2308
|
||||
|
||||
Includes a bugfix, don't mix graph and provisioning api.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/786
|
||||
27
changelog/unreleased/update-konnectd.md
Normal file
27
changelog/unreleased/update-konnectd.md
Normal file
@@ -0,0 +1,27 @@
|
||||
Enhancement: Update konnectd to v0.33.8
|
||||
|
||||
This update adds options which allow the configuration of oidc-token expiration
|
||||
parameters: KONNECTD_ACCESS_TOKEN_EXPIRATION, KONNECTD_ID_TOKEN_EXPIRATION and
|
||||
KONNECTD_REFRESH_TOKEN_EXPIRATION.
|
||||
|
||||
Other changes from upstream:
|
||||
|
||||
- Generate random endsession state for external authority
|
||||
- Update dependencies in Dockerfile
|
||||
- Set prompt=None to avoid loops with external authority
|
||||
- Update Jenkins reporting plugin from checkstyle to recordIssues
|
||||
- Remove extra kty key from JWKS top level document
|
||||
- Fix regression which encodes URL fragments twice
|
||||
- Avoid generating fragmet/query URLs with wrong order
|
||||
- Return state for oidc endsession response redirects
|
||||
- Use server provided username to avoid case mismatch
|
||||
- Use signed-out-uri if set as fallback for goodbye redirect on saml slo
|
||||
- Add checks to ensure post_logout_redirect_uri is not empty
|
||||
- Fix SAML2 logout request parsing
|
||||
- Cure panic when no state is found in saml esr
|
||||
- Use SAML IdP Issuer value from meta data entityID
|
||||
- Allow configuration of expiration of oidc access, id and refresh tokens
|
||||
- Implement trampolin for external OIDC authority end session
|
||||
- Update ca-certificates version
|
||||
|
||||
https://github.com/owncloud/ocis/pull/744
|
||||
8
changelog/unreleased/update-phoenix-0.20.0
Normal file
8
changelog/unreleased/update-phoenix-0.20.0
Normal file
@@ -0,0 +1,8 @@
|
||||
Change: Update phoenix to v0.20.0
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.20.0. Please refer to the changelog (linked) for details on the phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/674
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.20.0
|
||||
8
changelog/unreleased/update-phoenix-0.21.0
Normal file
8
changelog/unreleased/update-phoenix-0.21.0
Normal file
@@ -0,0 +1,8 @@
|
||||
Change: Update phoenix to v0.21.0
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.21.0. Please refer to the changelog (linked) for details on the phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/728
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.21.0
|
||||
8
changelog/unreleased/update-phoenix-0.22.0
Normal file
8
changelog/unreleased/update-phoenix-0.22.0
Normal file
@@ -0,0 +1,8 @@
|
||||
Change: Update phoenix to v0.22.0
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.22.0. Please refer to the changelog (linked) for details on the phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/757
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.22.0
|
||||
8
changelog/unreleased/update-phoenix-0.23.0
Normal file
8
changelog/unreleased/update-phoenix-0.23.0
Normal file
@@ -0,0 +1,8 @@
|
||||
Change: Update phoenix to v0.23.0
|
||||
|
||||
Tags: web
|
||||
|
||||
We updated phoenix to v0.23.0. Please refer to the changelog (linked) for details on the phoenix release.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/785
|
||||
https://github.com/owncloud/phoenix/releases/tag/v0.23.0
|
||||
6
changelog/unreleased/update-reva-to-cdb3d6688da5.md
Normal file
6
changelog/unreleased/update-reva-to-cdb3d6688da5.md
Normal file
@@ -0,0 +1,6 @@
|
||||
Enhancement: Update reva to cdb3d6688da5
|
||||
|
||||
* let the gateway filter invalid references
|
||||
|
||||
https://github.com/owncloud/ocis/pull/748
|
||||
https://github.com/cs3org/reva/pull/1274
|
||||
6
changelog/unreleased/update-reva-to-dd3a8c0f38.md
Normal file
6
changelog/unreleased/update-reva-to-dd3a8c0f38.md
Normal file
@@ -0,0 +1,6 @@
|
||||
Enhancement: Update reva to dd3a8c0f38
|
||||
|
||||
* fixes etag propagation in the ocis driver
|
||||
|
||||
https://github.com/owncloud/ocis/pull/725
|
||||
https://github.com/cs3org/reva/pull/1264
|
||||
5
changelog/unreleased/update-storage-env-vars.md
Normal file
5
changelog/unreleased/update-storage-env-vars.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Change: Clarify storage driver env vars
|
||||
|
||||
After renaming ocsi-reva to storage and combining the storage and data providers some env vars were confusingly named `STORAGE_STORAGE_...`. We are changing the prefix for driver related env vars to `STORAGE_DRIVER_...`. This makes changing the storage driver using eg.: `STORAGE_HOME_DRIVER=eos` and setting driver options using `STORAGE_DRIVER_EOS_LAYOUT=...` less confusing.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/729
|
||||
53
deployments/examples/ocis_external_konnectd/README.md
Normal file
53
deployments/examples/ocis_external_konnectd/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Deployment scenario ocis with external konnectd service on separate node and traefik as reverse proxy
|
||||
|
||||
## Setup on ocis server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example sub folder for ocisnode to /opt
|
||||
|
||||
`cp deployment/examples/ocis_external_konnectd/ocisnode /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN and IDP_DOMAIN in .env with your-ocis.domain.com and your-idp.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/ocisnode/.env`
|
||||
|
||||
`sed -i 's/idp.domain.com/your-idp.domain.com/g' /opt/ocisnode/.env`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/ocisnode`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
## Setup on idp server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example sub folder for idpnode to /opt
|
||||
|
||||
`cp deployment/examples/ocis_external_konnectd/idpnode /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN and IDP_DOMAIN in .env with your-ocis.domain.com and your-idp.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/idpnode/.env`
|
||||
|
||||
`sed -i 's/idp.domain.com/your-idp.domain.com/g' /opt/idpnode/.env`
|
||||
|
||||
* Overwrite redirect uri with your-ocis.domain.com in identifier-registration.yml
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/idpnode/config/identifier-registration.yml`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/idpnode`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
2
deployments/examples/ocis_external_konnectd/idpnode/.env
Normal file
2
deployments/examples/ocis_external_konnectd/idpnode/.env
Normal file
@@ -0,0 +1,2 @@
|
||||
OCIS_DOMAIN=ocis.domain.com
|
||||
IDP_DOMAIN=idp.domain.com
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- http://ocis.domain.com/
|
||||
- https://ocis.domain.com/
|
||||
- http://ocis.domain.com/oidc-callback.html
|
||||
- https://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/oidc-silent-redirect.html
|
||||
- https://ocis.domain.com/oidc-silent-redirect.html
|
||||
origins:
|
||||
- http://ocis.domain.com
|
||||
- https://ocis.domain.com
|
||||
@@ -0,0 +1,67 @@
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.2"
|
||||
container_name: "traefik"
|
||||
networks:
|
||||
- idpnet
|
||||
command:
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.idp.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.idp.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.idp.acme.email=postmaster@${IDP_DOMAIN}"
|
||||
- "--certificatesresolvers.idp.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "letsencrypt:/letsencrypt"
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
|
||||
konnectd:
|
||||
container_name: konnectd
|
||||
image: owncloud/ocis-konnectd:latest
|
||||
networks:
|
||||
- idpnet
|
||||
ports:
|
||||
- "9130:9130"
|
||||
volumes:
|
||||
- ./config:/etc/ocis
|
||||
environment:
|
||||
OCIS_LOG_LEVEL: debug
|
||||
KONNECTD_ISS: https://${IDP_DOMAIN}
|
||||
KONNECTD_IDENTIFIER_REGISTRATION_CONF: "/etc/ocis/identifier-registration.yml"
|
||||
KONNECTD_LOG_LEVEL: debug
|
||||
KONNECTD_TLS: '0'
|
||||
LDAP_URI: ldap://${OCIS_DOMAIN}:9125
|
||||
LDAP_BINDDN: cn=konnectd,ou=sysusers,dc=example,dc=org
|
||||
LDAP_BINDPW: konnectd
|
||||
LDAP_BASEDN: ou=users,dc=example,dc=org
|
||||
LDAP_SCOPE: sub
|
||||
LDAP_LOGIN_ATTRIBUTE: cn
|
||||
LDAP_EMAIL_ATTRIBUTE: mail
|
||||
LDAP_NAME_ATTRIBUTE=: n
|
||||
LDAP_UUID_ATTRIBUTE: uid
|
||||
LDAP_UUID_ATTRIBUTE_TYPE: text
|
||||
LDAP_FILTER: (objectClass=posixaccount)
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.idp.loadbalancer.server.port=9200"
|
||||
- "traefik.docker.network=idpnet"
|
||||
- "traefik.port=9130"
|
||||
- "traefik.protocol=https"
|
||||
# ssl config
|
||||
- "traefik.http.routers.idp.rule=Host(`${IDP_DOMAIN}`)"
|
||||
- "traefik.http.routers.idp.entrypoints=websecure"
|
||||
- "traefik.http.routers.idp.tls.certresolver=idp"
|
||||
# http -> https forwarding
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.idp-redirs.rule=Host(`${IDP_DOMAIN}`)"
|
||||
- "traefik.http.routers.idp-redirs.entrypoints=web"
|
||||
- "traefik.http.routers.idp-redirs.middlewares=redirect-to-https"
|
||||
@@ -0,0 +1,2 @@
|
||||
OCIS_DOMAIN=ocis.domain.com
|
||||
IDP_DOMAIN=idp.domain.com
|
||||
@@ -0,0 +1,68 @@
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.2"
|
||||
container_name: "traefik"
|
||||
networks:
|
||||
- ocisnet
|
||||
command:
|
||||
- "--api.insecure=true"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.ocis.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.ocis.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.ocis.acme.email=postmaster@${OCIS_DOMAIN}"
|
||||
- "--certificatesresolvers.ocis.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "letsencrypt:/letsencrypt"
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
|
||||
ocis:
|
||||
container_name: ocis
|
||||
image: owncloud/ocis:latest
|
||||
tty: true
|
||||
privileged: true
|
||||
stdin_open: true
|
||||
ports:
|
||||
- 9200:9200
|
||||
- 9125:9125
|
||||
hostname: ocis
|
||||
networks:
|
||||
- ocisnet
|
||||
environment:
|
||||
OCIS_DOMAIN: ${OCIS_DOMAIN}
|
||||
PROXY_OIDC_ISSUER: https://${IDP_DOMAIN}
|
||||
PROXY_OIDC_INSECURE: "true"
|
||||
PROXY_TLS: "false"
|
||||
GRAPH_OIDC_ENDPOINT: https://${IDP_DOMAIN}
|
||||
REVA_OIDC_ISSUER: https://${IDP_DOMAIN}
|
||||
REVA_LDAP_IDP: https://${IDP_DOMAIN}
|
||||
PHOENIX_OIDC_AUTHORITY: https://${IDP_DOMAIN}
|
||||
PHOENIX_OIDC_METADATA_URL: https://${IDP_DOMAIN}/.well-known/openid-configuration
|
||||
PHOENIX_WEB_CONFIG_SERVER: https://${OCIS_DOMAIN}
|
||||
OCIS_LOG_LEVEL: debug
|
||||
REVA_TRANSFER_EXPIRES: 86400
|
||||
REVA_FRONTEND_URL: https://${OCIS_DOMAIN}
|
||||
REVA_DATAGATEWAY_URL: https://${OCIS_DOMAIN}/data
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.ocis.loadbalancer.server.port=9200"
|
||||
- "traefik.docker.network=ocisnet"
|
||||
- "traefik.protocol=https"
|
||||
# ssl config
|
||||
- "traefik.http.routers.idp.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
- "traefik.http.routers.ocis.entrypoints=websecure"
|
||||
- "traefik.http.routers.ocis.tls.certresolver=idp"
|
||||
# http -> https forwarding
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.ocis-redirs.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
- "traefik.http.routers.ocis-redirs.entrypoints=web"
|
||||
- "traefik.http.routers.ocis-redirs.middlewares=redirect-to-https"
|
||||
3
deployments/examples/ocis_oc10_backend/.env
Normal file
3
deployments/examples/ocis_oc10_backend/.env
Normal file
@@ -0,0 +1,3 @@
|
||||
COMPOSE_PROJECT_NAME=bridge
|
||||
OCIS_DOMAIN=ocis.domain.com
|
||||
OC10_DOMAIN=oc10.domain.com
|
||||
30
deployments/examples/ocis_oc10_backend/README.md
Normal file
30
deployments/examples/ocis_oc10_backend/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Deployment scenario ocis with oc10 backend and traefik as reverse proxy
|
||||
|
||||
## Setup on server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example folder to /opt
|
||||
`cp deployment/examples/ocis_oc10_backend /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN and OC10_DOMAIN in .env with your-ocis.domain.com and your-oc10.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/ocis_oc10_backend/.env`
|
||||
|
||||
`sed -i 's/oc10.domain.com/your-oc10.domain.com/g' /opt/ocis_oc10_backend/.env`
|
||||
|
||||
* Overwrite redirect uris with your-ocis.domain.com and your-oc10.domain.com in identifier-registration.yml
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/ocis_oc10_backend/ocis/identifier-registration.yml`
|
||||
|
||||
`sed -i 's/oc10.domain.com/your-oc10.domain.com/g' /opt/ocis_oc10_backend/ocis/identifier-registration.yml`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/ocis_oc10_backend`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
171
deployments/examples/ocis_oc10_backend/docker-compose.yml
Normal file
171
deployments/examples/ocis_oc10_backend/docker-compose.yml
Normal file
@@ -0,0 +1,171 @@
|
||||
version: '3.7'
|
||||
|
||||
volumes:
|
||||
files:
|
||||
driver: local
|
||||
mysql:
|
||||
driver: local
|
||||
backup:
|
||||
driver: local
|
||||
redis:
|
||||
driver: local
|
||||
tmp:
|
||||
driver: local
|
||||
letsencrypt:
|
||||
driver: local
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: "traefik:v2.2"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--serverstransport.insecureskipverify=true"
|
||||
# Ocis certificate resolver
|
||||
- "--certificatesresolvers.ocis.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.ocis.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.ocis.acme.email=user@${OCIS_DOMAIN}"
|
||||
- "--certificatesresolvers.ocis.acme.storage=/letsencrypt/acme-ocis.json"
|
||||
# OC10 certificate resolver
|
||||
- "--certificatesresolvers.oc10.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.oc10.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.oc10.acme.email=user@${OCIS_DOMAIN}"
|
||||
- "--certificatesresolvers.oc10.acme.storage=/letsencrypt/acme-oc10.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "letsencrypt:/letsencrypt"
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
|
||||
owncloud:
|
||||
build:
|
||||
context: ./oc10
|
||||
dockerfile: Dockerfile
|
||||
expose:
|
||||
- "8080"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
environment:
|
||||
OWNCLOUD_DOMAIN: ${OC10_DOMAIN}
|
||||
OWNCLOUD_DB_TYPE: mysql
|
||||
OWNCLOUD_DB_NAME: owncloud
|
||||
OWNCLOUD_DB_USERNAME: owncloud
|
||||
OWNCLOUD_DB_PASSWORD: owncloud
|
||||
OWNCLOUD_DB_HOST: db
|
||||
OWNCLOUD_ADMIN_USERNAME: admin
|
||||
OWNCLOUD_ADMIN_PASSWORD: admin
|
||||
OWNCLOUD_MYSQL_UTF8MB4: "true"
|
||||
OWNCLOUD_REDIS_ENABLED: "true"
|
||||
OWNCLOUD_REDIS_HOST: redis
|
||||
OWNCLOUD_DEBUG: "true"
|
||||
OWNCLOUD_TRUSTED_PROXIES: ${OC10_DOMAIN}
|
||||
OWNCLOUD_OVERWRITE_PROTOCOL: https
|
||||
OWNCLOUD_OVERWRITE_HOST: ${OC10_DOMAIN}
|
||||
OWNCLOUD_APPS_ENABLE: "openidconnect,oauth2,user_ldap,graphapi"
|
||||
OWNCLOUD_LOG_LEVEL: 0
|
||||
volumes:
|
||||
- files:/mnt/data
|
||||
- tmp:/tmp/shared
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.oc10.loadbalancer.server.port=8080"
|
||||
- "traefik.docker.network=ocisnet"
|
||||
- "traefik.protocol=https"
|
||||
# ssl config
|
||||
- "traefik.http.routers.oc10.rule=Host(`${OC10_DOMAIN}`)"
|
||||
- "traefik.http.routers.oc10.entrypoints=websecure"
|
||||
- "traefik.http.routers.oc10.tls.certresolver=oc10"
|
||||
# http -> https forwarding
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.oc10-redirs.rule=Host(`${OC10_DOMAIN}`)"
|
||||
- "traefik.http.routers.oc10-redirs.entrypoints=web"
|
||||
- "traefik.http.routers.oc10-redirs.middlewares=redirect-to-https"
|
||||
|
||||
ocis:
|
||||
image: owncloud/ocis:latest
|
||||
ports:
|
||||
- 9200:9200
|
||||
environment:
|
||||
OCIS_DOMAIN: ${OCIS_DOMAIN}
|
||||
PROXY_CONFIG_FILE: "/config/proxy-config.json"
|
||||
PROXY_TLS: "false"
|
||||
PROXY_OIDC_ISSUER: https://${OCIS_DOMAIN}
|
||||
PROXY_OIDC_INSECURE: "true"
|
||||
PROXY_AUTOPROVISION_ACCOUNTS: "true"
|
||||
KONNECTD_ISS: https://${OCIS_DOMAIN}
|
||||
KONNECTD_IDENTIFIER_REGISTRATION_CONF: "/config/identifier-registration.yml"
|
||||
KONNECTD_TLS: 0
|
||||
KONNECTD_SIGNING_KID: super
|
||||
GRAPH_OIDC_ENDPOINT: https://${OC10_DOMAIN}/apps/graphapi/v1.0
|
||||
PHOENIX_OIDC_AUTHORITY: https://${OCIS_DOMAIN}
|
||||
PHOENIX_OIDC_METADATA_URL: https://${OCIS_DOMAIN}/.well-known/openid-configuration
|
||||
PHOENIX_WEB_CONFIG_SERVER: https://${OCIS_DOMAIN}
|
||||
PHOENIX_WEB_CONFIG: "/config/web/config.json"
|
||||
STORAGE_OIDC_ISSUER: https://${OCIS_DOMAIN}
|
||||
STORAGE_TRANSFER_EXPIRES: 86400
|
||||
STORAGE_FRONTEND_URL: https://${OCIS_DOMAIN}
|
||||
STORAGE_DATAGATEWAY_URL: https://${OCIS_DOMAIN}/data
|
||||
STORAGE_LDAP_IDP: https://${OCIS_DOMAIN}
|
||||
GLAUTH_BACKEND_DATASTORE: owncloud
|
||||
GLAUTH_BACKEND_SERVERS: https://${OC10_DOMAIN}/apps/graphapi/v1.0
|
||||
GLAUTH_BACKEND_BASEDN: dc=example,dc=org
|
||||
LDAP_URI: ldap://localhost:9125
|
||||
LDAP_BINDDN: "cn=admin,dc=example,dc=org"
|
||||
LDAP_BINDPW: "admin"
|
||||
LDAP_BASEDN: "dc=example,dc=org"
|
||||
LDAP_SCOPE: sub
|
||||
LDAP_LOGIN_ATTRIBUTE: uid
|
||||
LDAP_EMAIL_ATTRIBUTE: mail
|
||||
LDAP_NAME_ATTRIBUTE: givenName
|
||||
LDAP_UUID_ATTRIBUTE: uid
|
||||
LDAP_UUID_ATTRIBUTE_TYPE: text
|
||||
LDAP_FILTER: "(objectClass=posixaccount)"
|
||||
volumes:
|
||||
- ./ocis:/config
|
||||
- ./ocis/proxy-config.json:/etc/ocis/proxy.json
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.ocis.loadbalancer.server.port=9200"
|
||||
- "traefik.docker.network=ocisnet"
|
||||
- "traefik.protocol=https"
|
||||
# ssl config
|
||||
- "traefik.http.routers.ocis.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
- "traefik.http.routers.ocis.entrypoints=websecure"
|
||||
- "traefik.http.routers.ocis.tls.certresolver=ocis"
|
||||
# http -> https forwarding
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.ocis-redirs.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
- "traefik.http.routers.ocis-redirs.entrypoints=web"
|
||||
- "traefik.http.routers.ocis-redirs.middlewares=redirect-to-https"
|
||||
|
||||
db:
|
||||
image: webhippie/mariadb:latest
|
||||
restart: always
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: owncloud
|
||||
MARIADB_USERNAME: owncloud
|
||||
MARIADB_PASSWORD: owncloud
|
||||
MARIADB_DATABASE: owncloud
|
||||
MARIADB_MAX_ALLOWED_PACKET: 128M
|
||||
MARIADB_INNODB_LOG_FILE_SIZE: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/bin/healthcheck"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- mysql:/var/lib/mysql
|
||||
- backup:/var/lib/backup
|
||||
|
||||
redis:
|
||||
image: webhippie/redis:latest
|
||||
environment:
|
||||
- REDIS_DATABASES=1
|
||||
volumes:
|
||||
- redis:/var/lib/redis
|
||||
3
deployments/examples/ocis_oc10_backend/oc10/Dockerfile
Normal file
3
deployments/examples/ocis_oc10_backend/oc10/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM owncloud/server:10.6.0-beta1
|
||||
ADD apps/graphapi-0.1.0.tar.gz /var/www/owncloud/apps/
|
||||
COPY overlay /
|
||||
Binary file not shown.
@@ -0,0 +1,555 @@
|
||||
<?php
|
||||
|
||||
function getConfigFromEnv() {
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
|
||||
$domain = trim(
|
||||
explode(
|
||||
",",
|
||||
$_SERVER['HTTP_X_FORWARDED_HOST']
|
||||
)[0]
|
||||
);
|
||||
} else if (isset($_SERVER['SERVER_NAME'])) {
|
||||
$domain = $_SERVER['SERVER_NAME'];
|
||||
} else {
|
||||
$domain = 'localhost';
|
||||
}
|
||||
|
||||
$config = [
|
||||
'apps_paths' => [
|
||||
0 => [
|
||||
"path" => OC::$SERVERROOT . "/apps",
|
||||
"url" => "/apps",
|
||||
"writable" => false
|
||||
],
|
||||
1 => [
|
||||
"path" => OC::$SERVERROOT . "/custom",
|
||||
"url" => "/custom",
|
||||
"writable" => true
|
||||
]
|
||||
],
|
||||
|
||||
'trusted_domains' => [
|
||||
0 => $domain
|
||||
],
|
||||
'openid-connect' => [
|
||||
'provider-url' => 'https://${OCIS_DOMAIN}',
|
||||
'client-id' => 'oc10',
|
||||
'client-secret' => 'super',
|
||||
'loginButtonName' => 'OpenId Connect',
|
||||
'search-attribute' => 'preferred_username',
|
||||
'mode' => 'userid',
|
||||
],
|
||||
'datadirectory' => getenv('OWNCLOUD_VOLUME_FILES'),
|
||||
'dbtype' => getenv('OWNCLOUD_DB_TYPE'),
|
||||
'dbhost' => getenv('OWNCLOUD_DB_HOST'),
|
||||
'dbname' => getenv('OWNCLOUD_DB_NAME'),
|
||||
'dbuser' => getenv('OWNCLOUD_DB_USERNAME'),
|
||||
'dbpassword' => getenv('OWNCLOUD_DB_PASSWORD'),
|
||||
'dbtableprefix' => getenv('OWNCLOUD_DB_PREFIX'),
|
||||
|
||||
'phoenix.baseUrl' => 'https://${OCIS_DOMAIN}',
|
||||
'cors.allowed-domains' => ['https://${OCIS_DOMAIN}'],
|
||||
|
||||
'log_type' => 'owncloud',
|
||||
|
||||
'supportedDatabases' => [
|
||||
'sqlite',
|
||||
'mysql',
|
||||
'pgsql',
|
||||
],
|
||||
|
||||
'upgrade.disable-web' => true,
|
||||
];
|
||||
|
||||
if (getenv('OWNCLOUD_CORS_ALLOWED_DOMAINS') != '') {
|
||||
$config['cors.allowed-domains'] = explode(',', getenv('OWNCLOUD_CORS_ALLOWED_DOMAINS'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_VERSION_HIDE') != '') {
|
||||
$config['version.hide'] = getenv('OWNCLOUD_VERSION_HIDE') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SHOW_SERVER_HOSTNAME') != '') {
|
||||
$config['show_server_hostname'] = getenv('OWNCLOUD_SHOW_SERVER_HOSTNAME') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_DEFAULT_LANGUAGE') != '') {
|
||||
$config['default_language'] = getenv('OWNCLOUD_DEFAULT_LANGUAGE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_DEFAULT_APP') != '') {
|
||||
$config['defaultapp'] = getenv('OWNCLOUD_DEFAULT_APP');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_KNOWLEDGEBASE_ENABLED') != '') {
|
||||
$config['knowledgebaseenabled'] = getenv('OWNCLOUD_KNOWLEDGEBASE_ENABLED') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_ENABLE_AVATARS') != '') {
|
||||
$config['enable_avatars'] = getenv('OWNCLOUD_ENABLE_AVATARS') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_ALLOW_USER_TO_CHANGE_DISPLAY_NAME') != '') {
|
||||
$config['allow_user_to_change_display_name'] = getenv('OWNCLOUD_ALLOW_USER_TO_CHANGE_DISPLAY_NAME') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_REMEMBER_LOGIN_COOKIE_LIFETIME') != '') {
|
||||
$config['remember_login_cookie_lifetime'] = (int) getenv('OWNCLOUD_REMEMBER_LOGIN_COOKIE_LIFETIME');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SESSION_LIFETIME') != '') {
|
||||
$config['session_lifetime'] = (int) getenv('OWNCLOUD_SESSION_LIFETIME');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SESSION_KEEPALIVE') != '') {
|
||||
$config['session_keepalive'] = getenv('OWNCLOUD_SESSION_KEEPALIVE') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_TOKEN_AUTH_ENFORCED') != '') {
|
||||
$config['token_auth_enforced'] = getenv('OWNCLOUD_TOKEN_AUTH_ENFORCED') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_CSRF_DISABLED') != '') {
|
||||
$config['csrf.disabled'] = getenv('OWNCLOUD_CSRF_DISABLED') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SKELETON_DIRECTORY') != '') {
|
||||
$config['skeletondirectory'] = getenv('OWNCLOUD_SKELETON_DIRECTORY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOST_PASSWORD_LINK') != '') {
|
||||
$config['lost_password_link'] = getenv('OWNCLOUD_LOST_PASSWORD_LINK');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_ACCOUNTS_ENABLE_MEDIAL_SEARCH') != '') {
|
||||
$config['accounts.enable_medial_search'] = getenv('OWNCLOUD_ACCOUNTS_ENABLE_MEDIAL_SEARCH') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_USER_SEARCH_MIN_LENGTH') != '') {
|
||||
$config['user.search_min_length'] = (int) getenv('OWNCLOUD_USER_SEARCH_MIN_LENGTH');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_DOMAIN') != '') {
|
||||
$config['mail_domain'] = getenv('OWNCLOUD_MAIL_DOMAIN');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_FROM_ADDRESS') != '') {
|
||||
$config['mail_from_address'] = getenv('OWNCLOUD_MAIL_FROM_ADDRESS');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_DEBUG') != '') {
|
||||
$config['mail_smtpdebug'] = getenv('OWNCLOUD_MAIL_SMTP_DEBUG') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_MODE') != '') {
|
||||
$config['mail_smtpmode'] = getenv('OWNCLOUD_MAIL_SMTP_MODE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_HOST') != '') {
|
||||
$config['mail_smtphost'] = getenv('OWNCLOUD_MAIL_SMTP_HOST');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_PORT') != '') {
|
||||
$config['mail_smtpport'] = (int) getenv('OWNCLOUD_MAIL_SMTP_PORT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_TIMEOUT') != '') {
|
||||
$config['mail_smtptimeout'] = (int) getenv('OWNCLOUD_MAIL_SMTP_TIMEOUT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_SECURE') != '') {
|
||||
$config['mail_smtpsecure'] = getenv('OWNCLOUD_MAIL_SMTP_SECURE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_AUTH') != '') {
|
||||
$config['mail_smtpauth'] = getenv('OWNCLOUD_MAIL_SMTP_AUTH') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_AUTH_TYPE') != '') {
|
||||
$config['mail_smtpauthtype'] = getenv('OWNCLOUD_MAIL_SMTP_AUTH_TYPE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_NAME') != '') {
|
||||
$config['mail_smtpname'] = getenv('OWNCLOUD_MAIL_SMTP_NAME');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAIL_SMTP_PASSWORD') != '') {
|
||||
$config['mail_smtppassword'] = getenv('OWNCLOUD_MAIL_SMTP_PASSWORD');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_OVERWRITE_HOST') != '') {
|
||||
$config['overwritehost'] = getenv('OWNCLOUD_OVERWRITE_HOST');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_OVERWRITE_PROTOCOL') != '') {
|
||||
$config['overwriteprotocol'] = getenv('OWNCLOUD_OVERWRITE_PROTOCOL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_OVERWRITE_WEBROOT') != '') {
|
||||
$config['overwritewebroot'] = getenv('OWNCLOUD_OVERWRITE_WEBROOT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_OVERWRITE_COND_ADDR') != '') {
|
||||
$config['overwritecondaddr'] = getenv('OWNCLOUD_OVERWRITE_COND_ADDR');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_OVERWRITE_CLI_URL') != '') {
|
||||
$config['overwrite.cli.url'] = getenv('OWNCLOUD_OVERWRITE_CLI_URL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_HTACCESS_REWRITE_BASE') != '') {
|
||||
$config['htaccess.RewriteBase'] = getenv('OWNCLOUD_HTACCESS_REWRITE_BASE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PROXY') != '') {
|
||||
$config['proxy'] = getenv('OWNCLOUD_PROXY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PROXY_USERPWD') != '') {
|
||||
$config['proxyuserpwd'] = getenv('OWNCLOUD_PROXY_USERPWD');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_TRASHBIN_RETENTION_OBLIGATION') != '') {
|
||||
$config['trashbin_retention_obligation'] = getenv('OWNCLOUD_TRASHBIN_RETENTION_OBLIGATION');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_TRASHBIN_PURGE_LIMIT') != '') {
|
||||
$config['trashbin_purge_limit'] = (int) getenv('OWNCLOUD_TRASHBIN_PURGE_LIMIT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_VERSIONS_RETENTION_OBLIGATION') != '') {
|
||||
$config['versions_retention_obligation'] = getenv('OWNCLOUD_VERSIONS_RETENTION_OBLIGATION');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_UPDATE_CHECKER') != '') {
|
||||
$config['updatechecker'] = getenv('OWNCLOUD_UPDATE_CHECKER') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_UPDATER_SERVER_URL') != '') {
|
||||
$config['updater.server.url'] = getenv('OWNCLOUD_UPDATER_SERVER_URL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_HAS_INTERNET_CONNECTION') != '') {
|
||||
$config['has_internet_connection'] = getenv('OWNCLOUD_HAS_INTERNET_CONNECTION') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_CHECK_FOR_WORKING_WELLKNOWN_SETUP') != '') {
|
||||
$config['check_for_working_wellknown_setup'] = getenv('OWNCLOUD_CHECK_FOR_WORKING_WELLKNOWN_SETUP') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_OPERATION_MODE') != '') {
|
||||
$config['operation.mode'] = getenv('OWNCLOUD_OPERATION_MODE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOG_FILE') != '') {
|
||||
$config['logfile'] = getenv('OWNCLOUD_LOG_FILE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOG_LEVEL') != '') {
|
||||
$config['loglevel'] = (int) getenv('OWNCLOUD_LOG_LEVEL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOG_DATE_FORMAT') != '') {
|
||||
$config['logdateformat'] = getenv('OWNCLOUD_LOG_DATE_FORMAT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOG_TIMEZONE') != '') {
|
||||
$config['logtimezone'] = getenv('OWNCLOUD_LOG_TIMEZONE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_CRON_LOG') != '') {
|
||||
$config['cron_log'] = getenv('OWNCLOUD_CRON_LOG') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOG_ROTATE_SIZE') != '') {
|
||||
$config['log_rotate_size'] = (int) getenv('OWNCLOUD_LOG_ROTATE_SIZE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_ENABLE_PREVIEWS') != '') {
|
||||
$config['enable_previews'] = getenv('OWNCLOUD_ENABLE_PREVIEWS') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PREVIEW_MAX_X') != '') {
|
||||
$config['preview_max_x'] = (int) getenv('OWNCLOUD_PREVIEW_MAX_X');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PREVIEW_MAX_Y') != '') {
|
||||
$config['preview_max_y'] = (int) getenv('OWNCLOUD_PREVIEW_MAX_Y');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PREVIEW_MAX_SCALE_FACTOR') != '') {
|
||||
$config['preview_max_scale_factor'] = (int) getenv('OWNCLOUD_PREVIEW_MAX_SCALE_FACTOR');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PREVIEW_MAX_FILESIZE_IMAGE') != '') {
|
||||
$config['preview_max_filesize_image'] = getenv('OWNCLOUD_PREVIEW_MAX_FILESIZE_IMAGE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PREVIEW_LIBREOFFICE_PATH') != '') {
|
||||
$config['preview_libreoffice_path'] = getenv('OWNCLOUD_PREVIEW_LIBREOFFICE_PATH');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PREVIEW_OFFICE_CL_PARAMETERS') != '') {
|
||||
$config['preview_office_cl_parameters'] = getenv('OWNCLOUD_PREVIEW_OFFICE_CL_PARAMETERS');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_ENABLED_PREVIEW_PROVIDERS') != '') {
|
||||
$config['enabledPreviewProviders'] = explode(',', getenv('OWNCLOUD_ENABLED_PREVIEW_PROVIDERS'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_COMMENTS_MANAGER_FACTORY') != '') {
|
||||
$config['comments.managerFactory'] = getenv('OWNCLOUD_COMMENTS_MANAGER_FACTORY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SYSTEMTAGS_MANAGER_FACTORY') != '') {
|
||||
$config['systemtags.managerFactory'] = getenv('OWNCLOUD_SYSTEMTAGS_MANAGER_FACTORY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAINTENANCE') != '') {
|
||||
$config['maintenance'] = getenv('OWNCLOUD_MAINTENANCE') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SINGLEUSER') != '') {
|
||||
$config['singleuser'] = getenv('OWNCLOUD_SINGLEUSER');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_ENABLE_CERTIFICATE_MANAGEMENT') != '') {
|
||||
$config['enable_certificate_management'] = getenv('OWNCLOUD_ENABLE_CERTIFICATE_MANAGEMENT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MEMCACHE_LOCAL') != '') {
|
||||
$config['memcache.local'] = getenv('OWNCLOUD_MEMCACHE_LOCAL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_CACHE_PATH') != '') {
|
||||
$config['cache_path'] = getenv('OWNCLOUD_CACHE_PATH');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_CACHE_CHUNK_GC_TTL') != '') {
|
||||
$config['cache_chunk_gc_ttl'] = (int) getenv('OWNCLOUD_CACHE_CHUNK_GC_TTL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_DAV_CHUNK_BASE_DIR') != '') {
|
||||
$config['dav.chunk_base_dir'] = getenv('OWNCLOUD_DAV_CHUNK_BASE_DIR');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SHARING_MANAGER_FACTORY') != '') {
|
||||
$config['sharing.managerFactory'] = getenv('OWNCLOUD_SHARING_MANAGER_FACTORY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SHARING_FEDERATION_ALLOW_HTTP_FALLBACK') != '') {
|
||||
$config['sharing.federation.allowHttpFallback'] = getenv('OWNCLOUD_SHARING_FEDERATION_ALLOW_HTTP_FALLBACK') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SQLITE_JOURNAL_MODE') != '') {
|
||||
$config['sqlite.journal_mode'] = getenv('OWNCLOUD_SQLITE_JOURNAL_MODE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MYSQL_UTF8MB4') != '') {
|
||||
$config['mysql.utf8mb4'] = getenv('OWNCLOUD_MYSQL_UTF8MB4') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_TEMP_DIRECTORY') != '') {
|
||||
$config['tempdirectory'] = getenv('OWNCLOUD_TEMP_DIRECTORY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_HASHING_COST') != '') {
|
||||
$config['hashingCost'] = (int) getenv('OWNCLOUD_HASHING_COST');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_BLACKLISTED_FILES') != '') {
|
||||
$config['blacklisted_files'] = explode(',', getenv('OWNCLOUD_BLACKLISTED_FILES'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_EXCLUDED_DIRECTORIES') != '') {
|
||||
$config['excluded_directories'] = explode(',', getenv('OWNCLOUD_EXCLUDED_DIRECTORIES'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_INTEGRITY_EXCLUDED_FILES') != '') {
|
||||
$config['integrity.excluded.files'] = explode(',', getenv('OWNCLOUD_INTEGRITY_EXCLUDED_FILES'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_INTEGRITY_IGNORE_MISSING_APP_SIGNATURE') != '') {
|
||||
$config['integrity.ignore.missing.app.signature'] = explode(',', getenv('OWNCLOUD_INTEGRITY_IGNORE_MISSING_APP_SIGNATURE'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SHARE_FOLDER') != '') {
|
||||
$config['share_folder'] = getenv('OWNCLOUD_SHARE_FOLDER');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_CIPHER') != '') {
|
||||
$config['cipher'] = getenv('OWNCLOUD_CIPHER');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MINIMUM_SUPPORTED_DESKTOP_VERSION') != '') {
|
||||
$config['minimum.supported.desktop.version'] = getenv('OWNCLOUD_MINIMUM_SUPPORTED_DESKTOP_VERSION');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_QUOTA_INCLUDE_EXTERNAL_STORAGE') != '') {
|
||||
$config['quota_include_external_storage'] = getenv('OWNCLOUD_QUOTA_INCLUDE_EXTERNAL_STORAGE') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_FILESYSTEM_CHECK_CHANGES') != '') {
|
||||
$config['filesystem_check_changes'] = (int) getenv('OWNCLOUD_FILESYSTEM_CHECK_CHANGES');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_PART_FILE_IN_STORAGE') != '') {
|
||||
$config['part_file_in_storage'] = getenv('OWNCLOUD_PART_FILE_IN_STORAGE') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MOUNT_FILE') != '') {
|
||||
$config['mount_file'] = getenv('OWNCLOUD_MOUNT_FILE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_FILESYSTEM_CACHE_READONLY') != '') {
|
||||
$config['filesystem_cache_readonly'] = getenv('OWNCLOUD_FILESYSTEM_CACHE_READONLY') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SECRET') != '') {
|
||||
$config['secret'] = getenv('OWNCLOUD_SECRET');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_TRUSTED_PROXIES') != '') {
|
||||
$config['trusted_proxies'] = explode(',', getenv('OWNCLOUD_TRUSTED_PROXIES'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_FORWARDED_FOR_HEADERS') != '') {
|
||||
$config['forwarded_for_headers'] = explode(',', getenv('OWNCLOUD_FORWARDED_FOR_HEADERS'));
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MAX_FILESIZE_ANIMATED_GIFS_PUBLIC_SHARING') != '') {
|
||||
$config['max_filesize_animated_gifs_public_sharing'] = (int) getenv('OWNCLOUD_MAX_FILESIZE_ANIMATED_GIFS_PUBLIC_SHARING');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_FILELOCKING_ENABLED') != '') {
|
||||
$config['filelocking.enabled'] = getenv('OWNCLOUD_FILELOCKING_ENABLED') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_FILELOCKING_TTL') != '') {
|
||||
$config['filelocking.ttl'] = getenv('OWNCLOUD_FILELOCKING_TTL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MEMCACHE_LOCKING') != '') {
|
||||
$config['memcache.locking'] = getenv('OWNCLOUD_MEMCACHE_LOCKING');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_UPGRADE_AUTOMATIC_APP_UPDATES') != '') {
|
||||
$config['upgrade.automatic-app-update'] = getenv('OWNCLOUD_UPGRADE_AUTOMATIC_APP_UPDATES') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_DEBUG') != '') {
|
||||
$config['debug'] = getenv('OWNCLOUD_DEBUG') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_FILES_EXTERNAL_ALLOW_NEW_LOCAL') != '') {
|
||||
$config['files_external_allow_create_new_local'] = getenv('OWNCLOUD_FILES_EXTERNAL_ALLOW_NEW_LOCAL') == 'true';
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_SMB_LOGGING_ENABLE') != '') {
|
||||
$config['smb.logging.enable'] = getenv('OWNCLOUD_SMB_LOGGING_ENABLE');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_DAV_ENABLE_ASYNC') != '') {
|
||||
$config['dav.enable.async'] = getenv('OWNCLOUD_DAV_ENABLE_ASYNC');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LICENSE_KEY') != '') {
|
||||
$config['license-key'] = getenv('OWNCLOUD_LICENSE_KEY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MARKETPLACE_KEY') != '') {
|
||||
$config['marketplace.key'] = getenv('OWNCLOUD_MARKETPLACE_KEY');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_MARKETPLACE_CA') != '') {
|
||||
$config['marketplace.ca'] = getenv('OWNCLOUD_MARKETPLACE_CA');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_APPSTORE_URL') != '') {
|
||||
$config['appstoreurl'] = getenv('OWNCLOUD_APPSTORE_URL');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_LOGIN_ALTERNATIVES') != '') {
|
||||
$rows = explode(',', getenv('OWNCLOUD_LOGIN_ALTERNATIVES'));
|
||||
|
||||
foreach ($rows as $key => $value) {
|
||||
parse_str($value, $opts);
|
||||
$config['login.alternatives'][$key] = $opts;
|
||||
}
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case getenv('OWNCLOUD_REDIS_ENABLED') && getenv('OWNCLOUD_REDIS_ENABLED') == 'true':
|
||||
$config = array_merge_recursive($config, [
|
||||
'memcache.distributed' => '\OC\Memcache\Redis',
|
||||
'memcache.locking' => '\OC\Memcache\Redis',
|
||||
]);
|
||||
switch (true) {
|
||||
case getenv('OWNCLOUD_REDIS_SEEDS') != '':
|
||||
$config['redis.cluster']['seeds'] = explode(',', getenv('OWNCLOUD_REDIS_SEEDS'));
|
||||
|
||||
if (getenv('OWNCLOUD_REDIS_TIMEOUT') != '') {
|
||||
$config['redis.cluster']['timeout'] = (float) getenv('OWNCLOUD_REDIS_TIMEOUT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_REDIS_READ_TIMEOUT') != '') {
|
||||
$config['redis.cluster']['read_timeout'] = (float) getenv('OWNCLOUD_REDIS_READ_TIMEOUT');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_REDIS_FAILOVER_MODE') != '') {
|
||||
switch (getenv('OWNCLOUD_REDIS_FAILOVER_MODE')) {
|
||||
case 'FAILOVER_NONE':
|
||||
$config['redis.cluster']['failover_mode'] = \RedisCluster::FAILOVER_NONE;
|
||||
case 'FAILOVER_ERROR':
|
||||
$config['redis.cluster']['failover_mode'] = \RedisCluster::FAILOVER_ERROR;
|
||||
case 'FAILOVER_DISTRIBUTE':
|
||||
$config['redis.cluster']['failover_mode'] = \RedisCluster::FAILOVER_DISTRIBUTE;
|
||||
}
|
||||
}
|
||||
|
||||
case getenv('OWNCLOUD_REDIS_HOST') != '':
|
||||
$config['redis']['host'] = getenv('OWNCLOUD_REDIS_HOST');
|
||||
$config['redis']['port'] = getenv('OWNCLOUD_REDIS_PORT');
|
||||
|
||||
if (getenv('OWNCLOUD_REDIS_DB') != '') {
|
||||
$config['redis']['dbindex'] = getenv('OWNCLOUD_REDIS_DB');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_REDIS_PASSWORD') != '') {
|
||||
$config['redis']['password'] = getenv('OWNCLOUD_REDIS_PASSWORD');
|
||||
}
|
||||
|
||||
if (getenv('OWNCLOUD_REDIS_TIMEOUT') != '') {
|
||||
$config['redis']['timeout'] = (float) getenv('OWNCLOUD_REDIS_TIMEOUT');
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case getenv('OWNCLOUD_MEMCACHED_ENABLED') && getenv('OWNCLOUD_MEMCACHED_ENABLED') == 'true':
|
||||
$config = array_merge_recursive($config, [
|
||||
'memcache.distributed' => '\OC\Memcache\Memcached',
|
||||
'memcache.locking' => '\OC\Memcache\Memcached',
|
||||
|
||||
'memcached_servers' => [
|
||||
[
|
||||
getenv('OWNCLOUD_MEMCACHED_HOST'),
|
||||
getenv('OWNCLOUD_MEMCACHED_PORT'),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
if (getenv('OWNCLOUD_MEMCACHED_OPTIONS') != '') {
|
||||
parse_str(getenv('OWNCLOUD_MEMCACHED_OPTIONS'), $opts);
|
||||
|
||||
foreach($opts as $key => $value) {
|
||||
$config['memcached_options'][constant($key)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
$CONFIG = getConfigFromEnv();
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- http://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/
|
||||
- https://ocis.domain.com/
|
||||
- https://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/oidc-silent-redirect.html
|
||||
- https://ocis.domain.com/oidc-silent-redirect.html
|
||||
origins:
|
||||
- http://ocis.domain.com
|
||||
- https://ocis.domain.com
|
||||
|
||||
- id: oc10
|
||||
name: OC10
|
||||
application_type: web
|
||||
secret: super
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- https://oc10.domain.com/apps/openidconnect/redirect/
|
||||
- https://oc10.domain.com/apps/openidconnect/redirect
|
||||
origins:
|
||||
- http://oc10.domain.com
|
||||
- https://oc10.domain.com
|
||||
|
||||
- id: ocis-explorer.js
|
||||
name: OCIS Graph Explorer
|
||||
trusted: yes
|
||||
application_type: web
|
||||
insecure: yes
|
||||
|
||||
- id: xdXOt13JKxym1B1QcEncf2XDkLAexMBFwiT9j6EfhhHFJhs2KM9jbjTmf8JBXE69
|
||||
secret: UBntmLjC2yYCeHwsyj73Uwo9TAaecAetRwMw0xYcvNL9yRdLSUi0hUAHfvCHFeFh
|
||||
application_type: native
|
||||
insecure: true
|
||||
|
||||
- id: e4rAsNUSIUs0lF4nbv9FmCeUkTlV9GdgTLDH1b5uie7syb90SzEVrbN7HIpmWJeD
|
||||
secret: dInFYGV33xKzhbRmpqQltYNdfLdJIfJ9L5ISoKhNoT9qZftpdWSP71VrpGR9pmoD
|
||||
application_type: native
|
||||
redirect_uris:
|
||||
- oc://android.owncloud.com
|
||||
|
||||
- id: mxd5OQDk6es5LzOzRvidJNfXLUZS2oN3oUFeXPP8LpPrhx3UroJFduGEYIBOxkY1
|
||||
secret: KFeFWWEZO9TkisIQzR3fo7hfiMXlOpaqP8CFuTbSHzV1TUuGECglPxpiVKJfOXIx
|
||||
application_type: native
|
||||
redirect_uris:
|
||||
- oc://ios.owncloud.com
|
||||
- oc.ios://ios.owncloud.com
|
||||
|
||||
|
||||
# - id: playground-trusted.js
|
||||
# name: Trusted OIDC Playground
|
||||
# trusted: yes
|
||||
# application_type: web
|
||||
# redirect_uris:
|
||||
# - https://my-host:8509/
|
||||
# origins:
|
||||
# - https://my-host:8509
|
||||
|
||||
# - id: playground-trusted.js
|
||||
# name: Trusted Insecure OIDC Playground
|
||||
# trusted: yes
|
||||
# application_type: web
|
||||
# insecure: yes
|
||||
|
||||
# - id: client-with-keys
|
||||
# secret: super
|
||||
# application_type: native
|
||||
# redirect_uris:
|
||||
# - http://localhost
|
||||
# trusted_scopes:
|
||||
# - konnect/guestok
|
||||
# - kopano/kwm
|
||||
# jwks:
|
||||
# keys:
|
||||
# - kty: EC
|
||||
# use: sig
|
||||
# kid: client-with-keys-key-1
|
||||
# crv: P-256
|
||||
# x: RTZpWoRbjwX1YavmSHVBj6Cy3Yzdkkp6QLvTGB22D0c
|
||||
# y: jeavjwcX0xlDSchFcBMzXSU7wGs2VPpNxWCwmxFvmF0
|
||||
# request_object_signing_alg: ES256
|
||||
|
||||
# - id: first
|
||||
# secret: lala
|
||||
# application_type: native
|
||||
# redirect_uris:
|
||||
# - my://app
|
||||
|
||||
# - id: second
|
||||
# secret: lulu
|
||||
# application_type: native
|
||||
# redirect_uris:
|
||||
# - http://localhost
|
||||
|
||||
# External authority registry.
|
||||
authorities:
|
||||
# - id: my-univention
|
||||
# name: Univention
|
||||
# client_id: kopano-konnect
|
||||
# authority_type: oidc
|
||||
# jwks:
|
||||
# keys:
|
||||
# - kty: EC
|
||||
# use: sig
|
||||
# kid: example-key-1
|
||||
# crv: P-256
|
||||
# x: RTZpWoRbjwX1YavmSHVBj6Cy3Yzdkkp6QLvTGB22D0c
|
||||
# y: jeavjwcX0xlDSchFcBMzXSU7wGs2VPpNxWCwmxFvmF0
|
||||
# default: yes
|
||||
# authorization_endpoint: https://my-univention/signin/v1/identifier/_/authorize
|
||||
# response_type: id_token
|
||||
# scopes:
|
||||
# - openid
|
||||
# - profile
|
||||
# identity_claim_name: preferred_username
|
||||
# identity_aliases:
|
||||
# external-user-a: local-user-a
|
||||
# external-user-b: local-user-b
|
||||
# identity_alias_required: true
|
||||
133
deployments/examples/ocis_oc10_backend/ocis/proxy-config.json
Normal file
133
deployments/examples/ocis_oc10_backend/ocis/proxy-config.json
Normal file
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"HTTP": {
|
||||
"Namespace": "works.owncloud"
|
||||
},
|
||||
"policy_selector": {
|
||||
"migration": {
|
||||
"acc_found_policy" : "reva",
|
||||
"acc_not_found_policy": "oc10",
|
||||
"unauthenticated_policy": "oc10"
|
||||
}
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"name": "reva",
|
||||
"routes": [
|
||||
{
|
||||
"endpoint": "/",
|
||||
"backend": "http://localhost:9100"
|
||||
},
|
||||
{
|
||||
"endpoint": "/.well-known/",
|
||||
"backend": "http://localhost:9130"
|
||||
},
|
||||
{
|
||||
"endpoint": "/konnect/",
|
||||
"backend": "http://localhost:9130"
|
||||
},
|
||||
{
|
||||
"endpoint": "/signin/",
|
||||
"backend": "http://localhost:9130"
|
||||
},
|
||||
{
|
||||
"endpoint": "/ocs/",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"endpoint": "/ocs/v[12].php/cloud/user",
|
||||
"backend": "http://localhost:9110"
|
||||
},
|
||||
{
|
||||
"endpoint": "/remote.php/",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"endpoint": "/dav/",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"endpoint": "/webdav/",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"endpoint": "/status.php",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"endpoint": "/index.php/",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"endpoint": "/data",
|
||||
"backend": "http://localhost:9140"
|
||||
},
|
||||
{
|
||||
"endpoint": "/api/v0/accounts",
|
||||
"backend": "http://localhost:9181"
|
||||
},
|
||||
{
|
||||
"endpoint": "/accounts.js",
|
||||
"backend": "http://localhost:9181"
|
||||
},
|
||||
{
|
||||
"endpoint": "/api/v0/settings",
|
||||
"backend": "http://localhost:9190"
|
||||
},
|
||||
{
|
||||
"endpoint": "/settings.js",
|
||||
"backend": "http://localhost:9190"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "oc10",
|
||||
"routes": [
|
||||
{
|
||||
"endpoint": "/",
|
||||
"backend": "http://localhost:9100"
|
||||
},
|
||||
{
|
||||
"endpoint": "/.well-known/",
|
||||
"backend": "http://localhost:9130"
|
||||
},
|
||||
{
|
||||
"endpoint": "/konnect/",
|
||||
"backend": "http://localhost:9130"
|
||||
},
|
||||
{
|
||||
"endpoint": "/signin/",
|
||||
"backend": "http://localhost:9130"
|
||||
},
|
||||
{
|
||||
"endpoint": "/ocs/",
|
||||
"backend": "http://owncloud:8080",
|
||||
"apache-vhost": true
|
||||
},
|
||||
{
|
||||
"endpoint": "/remote.php/",
|
||||
"backend": "http://owncloud:8080",
|
||||
"apache-vhost": true
|
||||
},
|
||||
{
|
||||
"endpoint": "/dav/",
|
||||
"backend": "http://owncloud:8080",
|
||||
"apache-vhost": true
|
||||
},
|
||||
{
|
||||
"endpoint": "/webdav/",
|
||||
"backend": "http://owncloud:8080",
|
||||
"apache-vhost": true
|
||||
},
|
||||
{
|
||||
"endpoint": "/status.php",
|
||||
"backend": "http://owncloud:8080"
|
||||
},
|
||||
{
|
||||
"endpoint": "/index.php/",
|
||||
"backend": "http://owncloud:8080"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
49
deployments/examples/ocis_oc10_backend/ocis/web/config.json
Normal file
49
deployments/examples/ocis_oc10_backend/ocis/web/config.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"server": "https://${OCIS_DOMAIN}",
|
||||
"theme": "owncloud",
|
||||
"version": "0.1.0",
|
||||
"openIdConnect": {
|
||||
"metadata_url": "https://${OCIS_DOMAIN}/.well-known/openid-configuration",
|
||||
"authority": "https://${OCIS_DOMAIN}",
|
||||
"client_id": "phoenix",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile email"
|
||||
},
|
||||
"applications": [
|
||||
{
|
||||
"title": {
|
||||
"en": "Classic Design",
|
||||
"de": "Klassisches ownCloud"
|
||||
},
|
||||
"icon": "switch_ui",
|
||||
"url": "https://${OC10_DOMAIN}",
|
||||
"target": "_self"
|
||||
},
|
||||
{
|
||||
"title": {"en": "Classic Settings"},
|
||||
"icon": "application",
|
||||
"url": "https://${OC10_DOMAIN}/index.php/settings/personal",
|
||||
"target": "_self",
|
||||
"menu": "user"
|
||||
}
|
||||
],
|
||||
"apps": [
|
||||
"files",
|
||||
"draw-io",
|
||||
"markdown-editor",
|
||||
"media-viewer"
|
||||
],
|
||||
"options": {
|
||||
"hideSearchBar": false
|
||||
},
|
||||
"external_apps": [
|
||||
{
|
||||
"id": "accounts",
|
||||
"path": "/accounts.js"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"path": "/settings.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
1
deployments/examples/ocis_traefik/.env
Normal file
1
deployments/examples/ocis_traefik/.env
Normal file
@@ -0,0 +1 @@
|
||||
OCIS_DOMAIN=ocis.domain.com
|
||||
27
deployments/examples/ocis_traefik/README.md
Normal file
27
deployments/examples/ocis_traefik/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Deployment scenario ocis with traefik
|
||||
|
||||
## Setup on server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example folder to /opt
|
||||
|
||||
`cp deployment/examples/ocis_traefik /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN in .env with your.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your.domain.com/g' /opt/ocis_traefik/.env`
|
||||
|
||||
* Overwrite redirect uri with your.domain.com in identifier-registration.yml
|
||||
|
||||
`sed -i 's/ocis.domain.com/your.domain.com/g' /opt/ocis_traefik/config/identifier-registration.yml`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/ocis_traefik`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- http://ocis.domain.com/
|
||||
- https://ocis.domain.com/
|
||||
- http://ocis.domain.com/oidc-callback.html
|
||||
- https://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/oidc-silent-redirect.html
|
||||
- https://ocis.domain.com/oidc-silent-redirect.html
|
||||
origins:
|
||||
- http://ocis.domain.com
|
||||
- https://ocis.domain.com
|
||||
73
deployments/examples/ocis_traefik/docker-compose.yml
Normal file
73
deployments/examples/ocis_traefik/docker-compose.yml
Normal file
@@ -0,0 +1,73 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.2"
|
||||
container_name: "traefik"
|
||||
networks:
|
||||
- ocisnet
|
||||
command:
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--serverstransport.insecureskipverify=true"
|
||||
# Ocis certificate resolver
|
||||
- "--certificatesresolvers.ocis.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.ocis.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.ocis.acme.email=user@${OCIS_DOMAIN}"
|
||||
- "--certificatesresolvers.ocis.acme.storage=/letsencrypt/acme-ocis.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "letsencrypt:/letsencrypt"
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
|
||||
ocis:
|
||||
container_name: ocis
|
||||
image: owncloud/ocis:latest
|
||||
ports:
|
||||
- 9200:9200
|
||||
hostname: ocis
|
||||
networks:
|
||||
- ocisnet
|
||||
volumes:
|
||||
- ./config:/etc/ocis
|
||||
environment:
|
||||
OCIS_DOMAIN: ${OCIS_DOMAIN}
|
||||
PROXY_TLS: "false"
|
||||
PROXY_HTTP_ADDR: 0.0.0.0:9200
|
||||
PROXY_OIDC_ISSUER: https://${OCIS_DOMAIN}
|
||||
PROXY_OIDC_INSECURE: "true"
|
||||
KONNECTD_ISS: https://${OCIS_DOMAIN}
|
||||
KONNECTD_IDENTIFIER_REGISTRATION_CONF: "/etc/ocis/identifier-registration.yml"
|
||||
KONNECTD_TLS: 1
|
||||
GRAPH_OIDC_ENDPOINT: https://${OCIS_DOMAIN}
|
||||
PHOENIX_OIDC_AUTHORITY: https://${OCIS_DOMAIN}
|
||||
PHOENIX_OIDC_METADATA_URL: https://${OCIS_DOMAIN}/.well-known/openid-configuration
|
||||
PHOENIX_WEB_CONFIG_SERVER: https://${OCIS_DOMAIN}
|
||||
STORAGE_OIDC_ISSUER: https://${OCIS_DOMAIN}
|
||||
STORAGE_TRANSFER_EXPIRES: 86400
|
||||
STORAGE_FRONTEND_URL: https://${OCIS_DOMAIN}
|
||||
STORAGE_DATAGATEWAY_URL: https://${OCIS_DOMAIN}/data
|
||||
STORAGE_LDAP_IDP: https://${OCIS_DOMAIN}
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.ocis.loadbalancer.server.port=9200"
|
||||
- "traefik.docker.network=ocisnet"
|
||||
- "traefik.protocol=https"
|
||||
# ssl config
|
||||
- "traefik.http.routers.ocis.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
- "traefik.http.routers.ocis.entrypoints=websecure"
|
||||
- "traefik.http.routers.ocis.tls.certresolver=ocis"
|
||||
# http -> https forwarding
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.ocis-redirs.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
- "traefik.http.routers.ocis-redirs.entrypoints=web"
|
||||
- "traefik.http.routers.ocis-redirs.middlewares=redirect-to-https"
|
||||
|
||||
networks:
|
||||
ocisnet:
|
||||
@@ -57,5 +57,12 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the grpc server. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-accounts server --help
|
||||
accounts server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
accounts version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
@@ -42,7 +42,7 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the http and debug server on two addresses within a single process. The http server is serving the general webservice while the debug server is used for health check, readiness check and to server the metrics mentioned below. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-konnectd server --help
|
||||
konnectd server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Health
|
||||
@@ -50,9 +50,16 @@ ocis-konnectd server --help
|
||||
The health command is used to execute a health check, if the exit code equals zero the service should be up and running, if the exist code is greater than zero the service is not in a healthy state. Generally this command is used within our Docker containers, it could also be used within Kubernetes.
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-konnectd health --help
|
||||
konnectd health --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
konnectd version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
## Metrics
|
||||
|
||||
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `KONNECTD_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9134/metrics`.
|
||||
|
||||
@@ -190,7 +190,7 @@ If you prefer to configure the service with commandline flags you can see the av
|
||||
: Version, defaults to `0.1.0`
|
||||
|
||||
--web-config-app
|
||||
: Provide multiple apps, defaults to `""`. Usage: `phoenix --web-config-app files --web-config-app pdf-viewer`
|
||||
: Provide multiple apps, defaults to `""`. Usage: `phoenix --web-config-app files --web-config-app media-viewer`
|
||||
|
||||
--oidc-metadata-url
|
||||
: OpenID Connect metadata URL, defaults to `http://localhost:9130/.well-known/openid-configuration`
|
||||
|
||||
@@ -42,7 +42,7 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the http and debug server on two addresses within a single process. The http server is serving the general webservice while the debug server is used for health check, readiness check and to server the metrics mentioned below. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-ocs server --help
|
||||
ocs server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Health
|
||||
@@ -50,9 +50,16 @@ ocis-ocs server --help
|
||||
The health command is used to execute a health check, if the exit code equals zero the service should be up and running, if the exist code is greater than zero the service is not in a healthy state. Generally this command is used within our Docker containers, it could also be used within Kubernetes.
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-ocs health --help
|
||||
ocs health --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocs version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
## Metrics
|
||||
|
||||
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `OCS_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9114/metrics`.
|
||||
|
||||
@@ -42,5 +42,12 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the http server. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-proxy server --help
|
||||
proxy server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
proxy version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
@@ -160,7 +160,7 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the http and debug server on two addresses within a single process. The http server is serving the general webservice while the debug server is used for health check, readiness check and to server the metrics mentioned below. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-settings server --help
|
||||
settings server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Health
|
||||
@@ -168,9 +168,16 @@ ocis-settings server --help
|
||||
The health command is used to execute a health check, if the exit code equals zero the service should be up and running, if the exist code is greater than zero the service is not in a healthy state. Generally this command is used within our Docker containers, it could also be used within Kubernetes.
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-settings health --help
|
||||
settings health --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
settings version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
## Metrics
|
||||
|
||||
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `SETTINGS_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9194/metrics`.
|
||||
|
||||
@@ -11,35 +11,35 @@ This service provides an ocis extension that wraps [reva](https://github.com/cs3
|
||||
|
||||
It uses the port range 9140-9179 to preconfigure several services.
|
||||
|
||||
| port | service |
|
||||
+------+---------+
|
||||
| 9109 | health? |
|
||||
| 9140 | frontend |
|
||||
| 9141 | frontend debug |
|
||||
| 9142 | gateway |
|
||||
| 9143 | gateway debug |
|
||||
| 9144 | users |
|
||||
| 9145 | users debug |
|
||||
| 9146 | authbasic |
|
||||
| 9147 | authbasic debug |
|
||||
| 9148 | authbearer |
|
||||
| 9149 | authbearer debug |
|
||||
| 9150 | sharing |
|
||||
| 9151 | sharing debug |
|
||||
| 9152 | storage root |
|
||||
| 9153 | storage root debug |
|
||||
| 9154 | storage home |
|
||||
| 9155 | storage home debug |
|
||||
| 9156 | storage home data |
|
||||
| 9157 | storage home data debug |
|
||||
| 9158 | storage eos |
|
||||
| 9159 | storage eos debug |
|
||||
| 9160 | storage eos data |
|
||||
| 9161 | storage eos data debug |
|
||||
| 9162 | storage oc |
|
||||
| 9163 | storage oc debug |
|
||||
| 9164 | storage oc data |
|
||||
| 9165 | storage oc data debug |
|
||||
| port | service |
|
||||
|-----------|-----------------------------------------------|
|
||||
| 9109 | health? |
|
||||
| 9140 | frontend |
|
||||
| 9141 | frontend debug |
|
||||
| 9142 | gateway |
|
||||
| 9143 | gateway debug |
|
||||
| 9144 | users |
|
||||
| 9145 | users debug |
|
||||
| 9146 | authbasic |
|
||||
| 9147 | authbasic debug |
|
||||
| 9148 | authbearer |
|
||||
| 9149 | authbearer debug |
|
||||
| 9150 | sharing |
|
||||
| 9151 | sharing debug |
|
||||
| 9152 | storage root |
|
||||
| 9153 | storage root debug |
|
||||
| 9154 | storage home |
|
||||
| 9155 | storage home debug |
|
||||
| 9156 | storage home data |
|
||||
| 9157 | storage home data debug |
|
||||
| 9158 | storage eos |
|
||||
| 9159 | storage eos debug |
|
||||
| 9160 | storage eos data |
|
||||
| 9161 | storage eos data debug |
|
||||
| 9162 | storage oc |
|
||||
| 9163 | storage oc debug |
|
||||
| 9164 | storage oc data |
|
||||
| 9165 | storage oc data debug |
|
||||
| 9166-9177 | reserved for s3, wnd, custom + data providers |
|
||||
| 9178 | storage public link |
|
||||
| 9179 | storage public link data |
|
||||
| 9178 | storage public link |
|
||||
| 9179 | storage public link data |
|
||||
@@ -158,11 +158,11 @@ For a simple docker-compose setup, you can create a volume which will be used by
|
||||
The CERN eos storage has evolved with ownCloud and natively supports id based lookup, ETag propagation, subtree size accounting, sharing, trash and versions. To use it you need to change the default configuration of the `storage storage-home` command (or have a look at the Makefile ̀ eos-start` target):
|
||||
|
||||
```
|
||||
export STORAGE_STORAGE_HOME_DRIVER=eos
|
||||
export STORAGE_STORAGE_EOS_NAMESPACE=/eos
|
||||
export STORAGE_STORAGE_EOS_MASTER_URL="root://eos-mgm1.eoscluster.cern.ch:1094"
|
||||
export STORAGE_STORAGE_EOS_ENABLE_HOME=true
|
||||
export STORAGE_STORAGE_EOS_LAYOUT="dockertest/{{.Username}}"
|
||||
export STORAGE_HOME_DRIVER=eos
|
||||
export STORAGE_DRIVER_EOS_NAMESPACE=/eos
|
||||
export STORAGE_DRIVER_EOS_MASTER_URL="root://eos-mgm1.eoscluster.cern.ch:1094"
|
||||
export STORAGE_DRIVER_EOS_ENABLE_HOME=true
|
||||
export STORAGE_DRIVER_EOS_LAYOUT="dockertest/{{.Username}}"
|
||||
```
|
||||
|
||||
Running it locally also requires the `eos` and `xrootd` binaries. Running it using `make eos-start` will use CentOS based containers that already have the necessary packages installed.
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
---
|
||||
title: "Testing"
|
||||
date: 2018-05-02T00:00:00+00:00
|
||||
weight: 37
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/extensions/storage
|
||||
geekdocFilePath: testing.md
|
||||
---
|
||||
|
||||
|
||||
## API Acceptance tests
|
||||
|
||||
We are using the ownCloud 10 API acceptance testsuite against ocis. To set this up you need the owncloud 10 core repo, a ldap server that the acceptance tests can use to manage users, a redis server for file-versions and the ocis-reva code.
|
||||
|
||||
### Getting the tests
|
||||
|
||||
All you need to do to get the acceptance tests is check out the core repo:
|
||||
```
|
||||
git clone https://github.com/owncloud/core.git
|
||||
```
|
||||
|
||||
### Run a ldap server in a docker container
|
||||
|
||||
The ownCloud 10 acceptance tests will need write permission. You can start a suitable ldap server in a docker container with:
|
||||
|
||||
```
|
||||
docker run --hostname ldap.my-company.com \
|
||||
-e LDAP_TLS_VERIFY_CLIENT=never \
|
||||
-e LDAP_DOMAIN=owncloud.com \
|
||||
-e LDAP_ORGANISATION=ownCloud \
|
||||
-e LDAP_ADMIN_PASSWORD=admin \
|
||||
--name docker-slapd \
|
||||
-p 127.0.0.1:389:389 \
|
||||
-p 636:636 -d osixia/openldap
|
||||
```
|
||||
### Run a redis server in a docker container
|
||||
|
||||
File versions need a redis server. Start one with docker by using:
|
||||
|
||||
`docker run -e REDIS_DATABASES=1 -p 6379:6379 -d webhippie/redis:latest`
|
||||
|
||||
### Run ocis-reva with that ldap server
|
||||
|
||||
`storage` provides multiple subcommands. To configure them all via env vars you can export these environment variables.
|
||||
|
||||
```
|
||||
export STORAGE_USERS_DRIVER=ldap
|
||||
export STORAGE_LDAP_HOSTNAME=localhost
|
||||
export STORAGE_LDAP_PORT=636
|
||||
export STORAGE_LDAP_BASE_DN='dc=owncloud,dc=com'
|
||||
export STORAGE_LDAP_USERFILTER='(&(objectclass=posixAccount)(cn=%s))'
|
||||
export STORAGE_LDAP_GROUPFILTER='(&(objectclass=posixGroup)(cn=%s))'
|
||||
export STORAGE_LDAP_BIND_DN='cn=admin,dc=owncloud,dc=com'
|
||||
export STORAGE_LDAP_BIND_PASSWORD=admin
|
||||
export STORAGE_LDAP_SCHEMA_UID=uid
|
||||
export STORAGE_LDAP_SCHEMA_MAIL=mail
|
||||
export STORAGE_LDAP_SCHEMA_DISPLAYNAME=displayName
|
||||
export STORAGE_LDAP_SCHEMA_CN=cn
|
||||
export STORAGE_FRONTEND_URL=http://localhost:9140 # needed because the proxy is not started
|
||||
export STORAGE_DATAGATEWAY_URL=http://localhost:9140/data # needed because the proxy is not started
|
||||
```
|
||||
|
||||
Then you need to start the ocis-reva services
|
||||
```
|
||||
bin/storage frontend & \
|
||||
bin/storage gateway & \
|
||||
bin/storage auth-basic & \
|
||||
bin/storage auth-bearer & \
|
||||
bin/storage sharing & \
|
||||
bin/storage storage-home & \
|
||||
bin/storage storage-home-data & \
|
||||
bin/storage storage-oc & \
|
||||
bin/storage storage-oc-data & \
|
||||
bin/storage users &
|
||||
```
|
||||
|
||||
### Run the API acceptance tests
|
||||
|
||||
In the ownCloud 10 core repo run
|
||||
|
||||
```
|
||||
make test-acceptance-api \
|
||||
TEST_SERVER_URL=https://localhost:9200 \
|
||||
TEST_EXTERNAL_USER_BACKENDS=true \
|
||||
TEST_OCIS=true \
|
||||
OCIS_REVA_DATA_ROOT=/var/tmp/ocis/owncloud/ \
|
||||
BEHAT_FILTER_TAGS='~@notToImplementOnOCIS&&~@toImplementOnOCIS&&~@preview-extension-required' \
|
||||
SKELETON_DIR=apps/testing/data/apiSkeleton
|
||||
```
|
||||
|
||||
Make sure to adjust the settings `TEST_SERVER_URL`,`OCIS_REVA_DATA_ROOT` and `SKELETON_DIR` according to your environment.
|
||||
|
||||
This will run all tests that are relevant to OCIS.
|
||||
|
||||
To run a single test add `BEHAT_FEATURE=<feature file>` and specify the path to the feature file and an optional line number. For example: `BEHAT_FEATURE='tests/acceptance/features/apiWebdavUpload1/uploadFile.feature:12'`
|
||||
|
||||
### use existing tests for BDD
|
||||
|
||||
As a lot of scenarios are written for oC10, we can use those tests for Behaviour driven development in ocis.
|
||||
Every scenario that does not work in OCIS with OC storage, is listed in `tests/acceptance/expected-failures-on-OC-storage.txt` with a link to the related issue.
|
||||
Similarly, scenarios that do not work in OCIS with EOS storage are listed in `tests/acceptance/expected-failures-on-EOS-storage.txt`.
|
||||
Scenarios from the oC10 API acceptance tests are run in the ordinary acceptance test pipeline in CI. The scenarios that fail are checked against the
|
||||
expected failures. If there are any differences then the CI pipeline fails.
|
||||
|
||||
Additionally, some issues have scenarios that demonstrate the current buggy behaviour in ocis(reva).
|
||||
Those scenarios are in this ocis-reva repository in `tests/acceptance/features/apiOcisSpecific`.
|
||||
Have a look into the [documentation](https://doc.owncloud.com/server/developer_manual/testing/acceptance-tests.html#writing-scenarios-for-bugs) to understand why we are writing those tests.
|
||||
Also, ocis behaves partly differently with EOS-Storage and OC-Storage. There are scenarios that do not work in OCIS when run on EOS-storage, but works when on OC-Storage, and vice-versa. For those kind of scenarios, ` @skipOnOcis-EOS-Storage` and `@skipOnOcis-OC-Storage` tags are used. For instance, for a scenario that fails on EOS-Storage but passes on OC-Storage, we use `@skipOnOcis-EOS-Storage` tag to let it run on OC-Storage, where it works as expected, instead of skipping the test completely.
|
||||
|
||||
If you want to work on a specific issue
|
||||
|
||||
1. adjust the core commit id to the latest commit in core so that CI will run the latest test code and scenarios from core.
|
||||
For that change `coreCommit` in the `config` section:
|
||||
|
||||
config = {
|
||||
'apiTests': {
|
||||
'coreBranch': 'master',
|
||||
'coreCommit': 'a06b1bd5ba8e5244bfaf7fa04f441961e6fb0daa',
|
||||
'numberOfParts': 2
|
||||
}
|
||||
}
|
||||
|
||||
2. locally run each of the tests marked with that issue in the expected failures file:
|
||||
|
||||
E.g.:
|
||||
```
|
||||
make test-acceptance-api \
|
||||
TEST_SERVER_URL=https://localhost:9200 \
|
||||
TEST_EXTERNAL_USER_BACKENDS=true \
|
||||
TEST_OCIS=true \
|
||||
OCIS_REVA_DATA_ROOT=/var/tmp/ocis/owncloud/ \
|
||||
BEHAT_FEATURE='tests/acceptance/features/apiComments/comments.feature:123'
|
||||
```
|
||||
|
||||
3. the tests will fail, try to understand how and why they are failing
|
||||
4. fix the code
|
||||
5. go back to 2. and repeat till the tests are passing.
|
||||
6. remove those tests from the expected failures file.
|
||||
7. run each of the local tests that were demonstrating the **buggy** behavior. They should fail.
|
||||
8. delete each of the local tests that were demonstrating the **buggy** behavior.
|
||||
9. make a PR that has the fixed code, relevant lines removed from the expected failures file and bug demonstration tests deleted.
|
||||
|
||||
If the changes also affect the `ocis` repository make sure the changes get ported over there.
|
||||
That will need the fixed code in `storage` to be applied to `ocis` along with the test-related changes.
|
||||
|
||||
### Notes
|
||||
- in a normal case the test-code cleans up users after the test-run, but if a test-run is interrupted (e.g. by CTRL+C) users might have been left on the LDAP server. In that case rerunning the tests requires wiping the users in the ldap server, otherwise the tests will fail when trying to populate the users. This can be done by simply running `docker stop docker-slapd && docker rm docker-slapd` and [restarting the LDAP server container](#run-a-ldap-server-in-a-docker-container)
|
||||
- the tests usually create users in the OU `TestUsers` with usernames specified in the feature file. If not defined in the feature file, most users have the password `123456`, defined by `regularUserPassword` in `behat.yml`, but other passwords are also used, see [`\FeatureContext::getPasswordForUser()`](https://github.com/owncloud/core/blob/master/tests/acceptance/features/bootstrap/FeatureContext.php#L386) for mapping and [`\FeatureContext::__construct`](https://github.com/owncloud/core/blob/master/tests/acceptance/features/bootstrap/FeatureContext.php#L1668) for the password definitions.
|
||||
@@ -160,7 +160,7 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the http and debug server on two addresses within a single process. The http server is serving the general webservice while the debug server is used for health check, readiness check and to server the metrics mentioned below. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-store server --help
|
||||
store server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Health
|
||||
@@ -168,9 +168,16 @@ ocis-store server --help
|
||||
The health command is used to execute a health check, if the exit code equals zero the service should be up and running, if the exist code is greater than zero the service is not in a healthy state. Generally this command is used within our Docker containers, it could also be used within Kubernetes.
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-store health --help
|
||||
store health --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
store version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
## Metrics
|
||||
|
||||
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `STORE_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9460/metrics`.
|
||||
|
||||
@@ -189,6 +189,13 @@ The health command is used to execute a health check, if the exit code equals ze
|
||||
{{ Name }} health --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
{{ Name }} version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
## Metrics
|
||||
|
||||
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `THUMBNAILS_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9114/metrics`.
|
||||
|
||||
@@ -157,7 +157,7 @@ The program provides a few sub-commands on execution. The available configuratio
|
||||
The server command is used to start the http and debug server on two addresses within a single process. The http server is serving the general webservice while the debug server is used for health check, readiness check and to server the metrics mentioned below. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-webdav server --help
|
||||
webdav server --help
|
||||
{{< / highlight >}}
|
||||
|
||||
#### Health
|
||||
@@ -165,9 +165,16 @@ ocis-webdav server --help
|
||||
The health command is used to execute a health check, if the exit code equals zero the service should be up and running, if the exist code is greater than zero the service is not in a healthy state. Generally this command is used within our Docker containers, it could also be used within Kubernetes.
|
||||
|
||||
{{< highlight txt >}}
|
||||
ocis-webdav health --help
|
||||
webdav health --help
|
||||
{{< / highlight >}}
|
||||
|
||||
### Version
|
||||
The version command lists the versions of all running instances. For further help please execute:
|
||||
|
||||
{{< highlight txt >}}
|
||||
webdav version --help
|
||||
{{< /highlight >}}
|
||||
|
||||
### Metrics
|
||||
|
||||
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `WEBDAV_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9119/metrics`.
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
---
|
||||
title: "Configuration"
|
||||
date: "2020-10-05T21:19:39+0200"
|
||||
weight: 20
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/ocis
|
||||
geekdocFilePath: configuration.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Configuration
|
||||
|
||||
oCIS Single Binary is not responsible for configuring extensions. Instead, each extension could either be configured by environment variables, cli flags or config files.
|
||||
|
||||
Each extension has its dedicated documentation page (e.g. https://owncloud.github.io/extensions/ocis_proxy/configuration) which lists all possible configurations. Config files and environment variables are picked up if you use the `./bin/ocis server` command within the oCIS single binary. Command line flags must be set explicitly on the extensions subcommands.
|
||||
|
||||
### Configuration using config files
|
||||
|
||||
Out of the box extensions will attempt to read configuration details from:
|
||||
|
||||
```console
|
||||
/etc/ocis
|
||||
$HOME/.ocis
|
||||
./config
|
||||
```
|
||||
|
||||
For this configuration to be picked up, have a look at your extension `root` command and look for which default config name it has assigned. *i.e: ocis-proxy reads `proxy.json | yaml | toml ...`*.
|
||||
|
||||
So far we support the file formats `JSON` and `YAML`, if you want to get a full example configuration just take a look at [our repository](https://github.com/owncloud/ocis/tree/master/config), there you can always see the latest configuration format. These example configurations include all available options and the default values. The configuration file will be automatically loaded if it's placed at `/etc/ocis/ocis.yml`, `${HOME}/.ocis/ocis.yml` or `$(pwd)/config/ocis.yml`.
|
||||
|
||||
### Envrionment variables
|
||||
|
||||
If you prefer to configure the service with environment variables you can see the available variables below.
|
||||
|
||||
### Commandline flags
|
||||
|
||||
If you prefer to configure the service with commandline flags you can see the available variables below. Command line flags are only working when calling the subcommand directly.
|
||||
|
||||
## Root Command
|
||||
|
||||
ownCloud Infinite Scale Stack
|
||||
|
||||
Usage: `ocis [global options] command [command options] [arguments...]`
|
||||
|
||||
--config-file | $OCIS_CONFIG_FILE
|
||||
: Path to config file.
|
||||
|
||||
--log-level | $OCIS_LOG_LEVEL
|
||||
: Set logging level. Default: `info`.
|
||||
|
||||
--log-pretty | $OCIS_LOG_PRETTY
|
||||
: Enable pretty logging. Default: `true`.
|
||||
|
||||
--log-color | $OCIS_LOG_COLOR
|
||||
: Enable colored logging. Default: `true`.
|
||||
|
||||
## Sub Commands
|
||||
|
||||
### ocis kill
|
||||
|
||||
Kill an extension by name
|
||||
|
||||
Usage: `ocis kill [command options] [arguments...]`
|
||||
|
||||
### ocis server
|
||||
|
||||
Start fullstack server
|
||||
|
||||
Usage: `ocis server [command options] [arguments...]`
|
||||
|
||||
--tracing-enabled | $OCIS_TRACING_ENABLED
|
||||
: Enable sending traces.
|
||||
|
||||
--tracing-type | $OCIS_TRACING_TYPE
|
||||
: Tracing backend type. Default: `jaeger`.
|
||||
|
||||
--tracing-endpoint | $OCIS_TRACING_ENDPOINT
|
||||
: Endpoint for the agent. Default: `localhost:6831`.
|
||||
|
||||
--tracing-collector | $OCIS_TRACING_COLLECTOR
|
||||
: Endpoint for the collector. Default: `http://localhost:14268/api/traces`.
|
||||
|
||||
--tracing-service | $OCIS_TRACING_SERVICE
|
||||
: Service name for tracing. Default: `ocis`.
|
||||
|
||||
--debug-addr | $OCIS_DEBUG_ADDR
|
||||
: Address to bind debug server. Default: `0.0.0.0:9010`.
|
||||
|
||||
--debug-token | $OCIS_DEBUG_TOKEN
|
||||
: Token to grant metrics access.
|
||||
|
||||
--debug-pprof | $OCIS_DEBUG_PPROF
|
||||
: Enable pprof debugging.
|
||||
|
||||
--debug-zpages | $OCIS_DEBUG_ZPAGES
|
||||
: Enable zpages debugging.
|
||||
|
||||
--http-addr | $OCIS_HTTP_ADDR
|
||||
: Address to bind http server. Default: `0.0.0.0:9000`.
|
||||
|
||||
--http-root | $OCIS_HTTP_ROOT
|
||||
: Root path of http server. Default: `/`.
|
||||
|
||||
--grpc-addr | $OCIS_GRPC_ADDR
|
||||
: Address to bind grpc server. Default: `0.0.0.0:9001`.
|
||||
|
||||
### ocis run
|
||||
|
||||
Runs an extension
|
||||
|
||||
Usage: `ocis run [command options] [arguments...]`
|
||||
|
||||
### ocis health
|
||||
|
||||
Check health status
|
||||
|
||||
Usage: `ocis health [command options] [arguments...]`
|
||||
|
||||
--debug-addr | $OCIS_DEBUG_ADDR
|
||||
: Address to debug endpoint. Default: `0.0.0.0:9010`.
|
||||
|
||||
### ocis list
|
||||
|
||||
Lists running ocis extensions
|
||||
|
||||
Usage: `ocis list [command options] [arguments...]`
|
||||
|
||||
### List of available Extension subcommands
|
||||
|
||||
There are more subcommands to start the individual extensions. Please check the documentation about their usage and options in the dedicated section of the documentation.
|
||||
|
||||
#### ocis konnectd
|
||||
|
||||
Start konnectd server
|
||||
|
||||
#### ocis storage-frontend
|
||||
|
||||
Start storage frontend
|
||||
|
||||
#### ocis accounts
|
||||
|
||||
Start accounts server
|
||||
|
||||
#### ocis storage-storage-root
|
||||
|
||||
Start storage root storage
|
||||
|
||||
#### ocis storage-gateway
|
||||
|
||||
Start storage gateway
|
||||
|
||||
#### ocis storage-storage-home
|
||||
|
||||
Start storage storage service for home mount
|
||||
|
||||
#### ocis storage-storage-public-link
|
||||
|
||||
Start storage public link storage
|
||||
|
||||
#### ocis store
|
||||
|
||||
Start a go-micro store
|
||||
|
||||
#### ocis glauth
|
||||
|
||||
Start glauth server
|
||||
|
||||
#### ocis storage-auth-bearer
|
||||
|
||||
Start storage auth-bearer service
|
||||
|
||||
#### ocis storage-sharing
|
||||
|
||||
Start storage sharing service
|
||||
|
||||
#### ocis webdav
|
||||
|
||||
Start webdav server
|
||||
|
||||
#### ocis storage-storage-oc-data
|
||||
|
||||
Start storage storage data provider for oc mount
|
||||
|
||||
#### ocis thumbnails
|
||||
|
||||
Start thumbnails server
|
||||
|
||||
#### ocis proxy
|
||||
|
||||
Start proxy server
|
||||
|
||||
#### ocis settings
|
||||
|
||||
Start settings server
|
||||
|
||||
#### ocis storage-auth-basic
|
||||
|
||||
Start storage auth-basic service
|
||||
|
||||
#### ocis storage-storage-metadata
|
||||
|
||||
Start storage storage service for metadata mount
|
||||
|
||||
#### ocis ocs
|
||||
|
||||
Start ocs server
|
||||
|
||||
#### ocis storage-storage-eos
|
||||
|
||||
Start storage storage service for eos mount
|
||||
|
||||
#### ocis storage-storage-eos-data
|
||||
|
||||
Start storage storage data provider for eos mount
|
||||
|
||||
#### ocis storage-storage-home-data
|
||||
|
||||
Start storage storage data provider for home mount
|
||||
|
||||
#### ocis storage-storage-oc
|
||||
|
||||
Start storage storage service for oc mount
|
||||
|
||||
#### ocis storage-users
|
||||
|
||||
Start storage users service
|
||||
|
||||
#### ocis phoenix
|
||||
|
||||
Start phoenix server
|
||||
|
||||
@@ -3,14 +3,14 @@ title: "Deployment"
|
||||
date: 2020-10-01T20:35:00+01:00
|
||||
weight: -10
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/deployment
|
||||
geekdocEditPath: edit/master/docs/ocis/deployment
|
||||
geekdocFilePath: _index.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Deployments Scenarios and Examples
|
||||
This section handles deployments and operations for admins. If you are looking for a development setup, start with
|
||||
This section handles deployments and operations for admins. If you are looking for a development setup, start with
|
||||
|
||||
### Setup oCIS
|
||||
oCIS deployments are super simple, yet there are many configrations possible for advanced setups.
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Basic Remote Setup"
|
||||
date: 2020-02-27T20:35:00+01:00
|
||||
weight: 16
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocEditPath: edit/master/docs/ocis/deployment
|
||||
geekdocFilePath: basic-remote-setup.md
|
||||
---
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Bridge"
|
||||
date: 2020-02-27T20:35:00+01:00
|
||||
weight: 30
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocEditPath: edit/master/docs/ocis/deployment
|
||||
geekdocFilePath: bridge.md
|
||||
---
|
||||
|
||||
@@ -64,7 +64,7 @@ Enter host password for user 'admin':
|
||||
|
||||
### Start ocis-glauth
|
||||
|
||||
We are going to use the above ownCloud 10 and graphapi app to turn it into the datastore for an LDAP proxy.
|
||||
We are going to use the above ownCloud 10 and graphapi app to turn it into the datastore for an LDAP proxy.
|
||||
|
||||
#### Grab it!
|
||||
|
||||
@@ -250,5 +250,5 @@ In the above configuration replace
|
||||
## Next steps
|
||||
|
||||
Aside from the above todos these are the next stepo
|
||||
- tie it all together behind `ocis-proxy`
|
||||
- tie it all together behind `ocis-proxy`
|
||||
- create an `ocis bridge` command that runs all the ocis services in one step with a properly preconfigured `ocis-konnectd` `identifier-registration.yaml` file for `phoenix` and the owncloud 10 `openidconnect` app, as well as a randomized `--signing-kid`.
|
||||
|
||||
194
docs/ocis/deployment/ocis_external_konnectd.md
Normal file
194
docs/ocis/deployment/ocis_external_konnectd.md
Normal file
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: "ocis with konnectd on external node deployment scenario"
|
||||
date: 2020-10-12T14:39:00+01:00
|
||||
weight: 26
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/ocis/deployment
|
||||
geekdocFilePath: ocis_external_konnectd.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
This scenario shows how to setup ocis with konnectd as idp running on a separate node. Both node are having separate domains pointing on the servers.
|
||||
|
||||
## Overview
|
||||
|
||||
* ocis and konnectd running on linux nodes behind traefik as reverse proxy
|
||||
* Cloudflare DNS is resolving the domains
|
||||
* Letsencrypt provides ssl certificates for the domains
|
||||
* Traefik docker container terminates ssl and forwards http requests to the services
|
||||
|
||||
## Nodes
|
||||
|
||||
### Requirements
|
||||
|
||||
* Server running Ubuntu 20.04 is public availible with a static ip address
|
||||
* Two A-records for both domains are pointing on the servers ip address
|
||||
* Create user
|
||||
|
||||
`$ sudo adduser username`
|
||||
|
||||
* Add user to sudo group
|
||||
|
||||
`$ sudo usermod -aG sudo username`
|
||||
|
||||
* Add users pub key to `~/.ssh/authorized_keys`
|
||||
* Setup ssh to permit authorisation only by ssh key
|
||||
* Install docker
|
||||
|
||||
`$ sudo apt install docker.io`
|
||||
|
||||
* Add user to docker group
|
||||
|
||||
`$ sudo usermod -aG docker username`
|
||||
|
||||
* Install docker-compose via
|
||||
|
||||
`$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose`
|
||||
|
||||
(docker compose version 1.27.4 as of today)
|
||||
* Make docker-compose executable
|
||||
|
||||
`$ sudo chmod +x /usr/local/bin/docker-compose`
|
||||
|
||||
* Environment variables for OCIS Stack are provided by .env file
|
||||
|
||||
### Setup on ocis server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example sub folder for ocisnode to /opt
|
||||
|
||||
`cp deployment/examples/ocis_external_konnectd/ocisnode /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN and IDP_DOMAIN in .env with your-ocis.domain.com and your-idp.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/ocisnode/.env`
|
||||
|
||||
`sed -i 's/idp.domain.com/your-idp.domain.com/g' /opt/ocisnode/.env`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/ocisnode`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
### Setup on idp server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example sub folder for idpnode to /opt
|
||||
|
||||
`cp deployment/examples/ocis_external_konnectd/idpnode /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN and IDP_DOMAIN in .env with your-ocis.domain.com and your-idp.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/idpnode/.env`
|
||||
|
||||
`sed -i 's/idp.domain.com/your-idp.domain.com/g' /opt/idpnode/.env`
|
||||
|
||||
* Overwrite redirect uri with your-ocis.domain.com in identifier-registration.yml
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/idpnode/config/identifier-registration.yml`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/idpnode`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
### Stack
|
||||
|
||||
On both nodes, a traefik dokcer container is terminating ssl and forwards the http requests to the services. The nodes are named according to their services.
|
||||
|
||||
### Config
|
||||
|
||||
#### Repository structure
|
||||
|
||||
```bash
|
||||
ocis_external_konnectd # rootfolder
|
||||
└───ocisnode
|
||||
│ │ docker-compose.yml
|
||||
│ │ .env
|
||||
│
|
||||
└───idpnode
|
||||
│ docker-compose.yml
|
||||
│ .env
|
||||
└───config
|
||||
│ identifier-registration.yml
|
||||
```
|
||||
|
||||
Both subfolders contain the dockr-compose files including additionaly conf files if required. The content of both folders has to be deployed on each node.
|
||||
|
||||
#### Traefik
|
||||
|
||||
Traefik is set up similar to the traefik example on both nodes.
|
||||
The certificate resolvers are named similar to their services and behave exactly like in the other examples.
|
||||
|
||||
#### Konnectd
|
||||
|
||||
Konnectd as Openid provider needs the redirect url's to point to ocis.
|
||||
|
||||
```yaml
|
||||
---
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- http://ocis.domain.com/
|
||||
- https://ocis.domain.com/
|
||||
- http://ocis.domain.com/oidc-callback.html
|
||||
- https://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/oidc-silent-redirect.html
|
||||
- https://ocis.domain.com/oidc-silent-redirect.html
|
||||
origins:
|
||||
- http://ocis.domain.com
|
||||
- https://ocis.domain.com
|
||||
```
|
||||
|
||||
Behind traefik, http is used to communicate between the services. Setting KONNECTD_TLS enforces it.
|
||||
|
||||
```yaml
|
||||
KONNECTD_TLS: '0'
|
||||
```
|
||||
|
||||
In order to resolve users from glauth service on ocis node, Konnectd needs ldap settings to work properly.
|
||||
|
||||
```yaml
|
||||
LDAP_URI: ldap://${OCIS_DOMAIN}:9125
|
||||
LDAP_BINDDN: cn=konnectd,ou=sysusers,dc=example,dc=org
|
||||
LDAP_BINDPW: konnectd
|
||||
LDAP_BASEDN: ou=users,dc=example,dc=org
|
||||
LDAP_SCOPE: sub
|
||||
LDAP_LOGIN_ATTRIBUTE: cn
|
||||
LDAP_EMAIL_ATTRIBUTE: mail
|
||||
LDAP_NAME_ATTRIBUTE=: n
|
||||
LDAP_UUID_ATTRIBUTE: uid
|
||||
LDAP_UUID_ATTRIBUTE_TYPE: text
|
||||
LDAP_FILTER: (objectClass=posixaccount)
|
||||
```
|
||||
|
||||
#### ocis
|
||||
|
||||
On the ocis node, the setting is following a standard scenario, except, that port 9125 needs to be exposed for the idp node to resolve ldap querries from Konnectd.
|
||||
|
||||
```yaml
|
||||
ocis:
|
||||
...
|
||||
ports:
|
||||
- 9200:9200
|
||||
- 9125:9125
|
||||
...
|
||||
```
|
||||
289
docs/ocis/deployment/ocis_oc10_backend.md
Normal file
289
docs/ocis/deployment/ocis_oc10_backend.md
Normal file
@@ -0,0 +1,289 @@
|
||||
---
|
||||
title: "ocis frontend with oc10 backend deployment scenario"
|
||||
date: 2020-10-12T14:04:00+01:00
|
||||
weight: 25
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/ocis/deployment
|
||||
geekdocFilePath: ocis_frontend_oc10_backend.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
This deployment scenario shows how to use ocis as frontend for a existing owncloud 10 installation.
|
||||
ocis will allow owncloud 10 users to log in and work with their files.
|
||||
|
||||
## Overview
|
||||
|
||||
### Node Setup
|
||||
|
||||
* ocis and oc10 running as docker containers behind traefik as reverse proxy
|
||||
* Cloudflare DNS is resolving one domain for ocis and one for oc10
|
||||
* Letsencrypt is providing valid ssl certificate for both domains
|
||||
|
||||
## Node Deployment
|
||||
|
||||
### Requirements
|
||||
|
||||
* Server running Ubuntu 20.04 is public availible with a static ip address
|
||||
* Two A-records for both domains are pointing on the servers ip address
|
||||
* Create user
|
||||
|
||||
`$ sudo adduser username`
|
||||
|
||||
* Add user to sudo group
|
||||
|
||||
`$ sudo usermod -aG sudo username`
|
||||
|
||||
* Add users pub key to `~/.ssh/authorized_keys`
|
||||
* Setup ssh to permit authorisation only by ssh key
|
||||
* Install docker
|
||||
|
||||
`$ sudo apt install docker.io`
|
||||
|
||||
* Add user to docker group
|
||||
|
||||
`$ sudo usermod -aG docker username`
|
||||
|
||||
* Install docker-compose via
|
||||
|
||||
`$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose`
|
||||
|
||||
(docker compose version 1.27.4 as of today)
|
||||
* Make docker-compose executable
|
||||
|
||||
`$ sudo chmod +x /usr/local/bin/docker-compose`
|
||||
|
||||
* Environment variables for OCIS Stack are provided by .env file
|
||||
|
||||
### Setup on server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example folder to /opt
|
||||
`cp deployment/examples/ocis_oc10_backend /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN and OC10_DOMAIN in .env with your-ocis.domain.com and your-oc10.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/ocis_oc10_backend/.env`
|
||||
|
||||
`sed -i 's/oc10.domain.com/your-oc10.domain.com/g' /opt/ocis_oc10_backend/.env`
|
||||
|
||||
* Overwrite redirect uris with your-ocis.domain.com and your-oc10.domain.com in identifier-registration.yml
|
||||
|
||||
`sed -i 's/ocis.domain.com/your-ocis.domain.com/g' /opt/ocis_oc10_backend/ocis/identifier-registration.yml`
|
||||
|
||||
`sed -i 's/oc10.domain.com/your-oc10.domain.com/g' /opt/ocis_oc10_backend/ocis/identifier-registration.yml`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/ocis_oc10_backend`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
### Stack
|
||||
|
||||
The application stack is separated in docker containers. One is a traefik proxy which is terminating ssl and forwards the https requests to the internal docker network. Additional, traefik is creating two certificates that are stored in the file `letsencrypt/acme.json` of the users home directory. In a local setup, this traefik is not included.
|
||||
The next container is the ocis server which is exposing the webservice on port 9200 to traefic and provides the oidc provider konnectd to owncloud.
|
||||
oc10 is running as a three container setup out of owncloud-server, a db container and a redis container as memcache storage.
|
||||
|
||||
### Config
|
||||
|
||||
#### Repository structure
|
||||
|
||||
```bash
|
||||
ocis_oc10_backend # rootfolder
|
||||
│ .env
|
||||
│ docker-compose.yml
|
||||
│
|
||||
└───ocis #ocis related config files
|
||||
│ │ identifier-registration.yml
|
||||
│ │ proxy-config.json
|
||||
│
|
||||
└───oc10 #owncloud 10 related files
|
||||
│ Dockerfile
|
||||
│
|
||||
└───apps
|
||||
│ graphapi-0.1.0.tar.gz
|
||||
```
|
||||
|
||||
#### Traefik
|
||||
|
||||
In this deployment scenario, traefik requests letsencrypt to issue 2 ssl certificates, so two certificate resolver are needed. These are named according to the services, ocis for the ocis container and oc10 for the oc10 container.
|
||||
|
||||
```yaml
|
||||
...
|
||||
traefik:
|
||||
image: "traefik:v2.2"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
...
|
||||
# Ocis certificate resolver
|
||||
- "--certificatesresolvers.ocis.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.ocis.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.ocis.acme.email=user@${OCIS_DOMAIN}"
|
||||
- "--certificatesresolvers.ocis.acme.storage=/letsencrypt/acme-ocis.json"
|
||||
# OC10 certificate resolver
|
||||
- "--certificatesresolvers.oc10.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.oc10.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.oc10.acme.email=user@${OCIS_DOMAIN}"
|
||||
- "--certificatesresolvers.oc10.acme.storage=/letsencrypt/acme-oc10.json"
|
||||
...
|
||||
```
|
||||
|
||||
Both container's traefik labels have to match with the correct resolvers and domains
|
||||
|
||||
```yaml
|
||||
ocis:
|
||||
...
|
||||
labels:
|
||||
...
|
||||
- "traefik.http.routers.ocis.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
...
|
||||
```
|
||||
|
||||
```yaml
|
||||
oc10:
|
||||
...
|
||||
labels:
|
||||
...
|
||||
- "traefik.http.routers.oc10.rule=Host(`${OC10_DOMAIN}`)"
|
||||
...
|
||||
```
|
||||
|
||||
A folder for letsencypt to store the certificate needs to be created
|
||||
`$ mkdir ~/letsencrypt`
|
||||
This folder is bind to the docker container and the certificate is persistently stored into it.
|
||||
|
||||
#### ocis
|
||||
|
||||
Since ssl shall be terminated from traefik and inside of the docker network the services shall comunicate via http, `PROXY_TLS: "false"` as environment parameter for ocis has to be set.
|
||||
|
||||
For ocis 2 config files are provided.
|
||||
|
||||
```bash
|
||||
│
|
||||
└───ocis #ocis related config files
|
||||
│ │ identifier-registration.yml
|
||||
│ │ proxy-config.json
|
||||
```
|
||||
|
||||
Changes need to be done in identifier-registration.yml to match the domains
|
||||
Phoenix client needs the redirects uri's set to the ocis domain while oc10 client needs them to point on the owncloud domain
|
||||
|
||||
```yaml
|
||||
---
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- http://ocis.domain.com/
|
||||
- https://ocis.domain.com/
|
||||
- http://ocis.domain.com/oidc-callback.html
|
||||
- https://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/oidc-silent-redirect.html
|
||||
- https://ocis.domain.com/oidc-silent-redirect.html
|
||||
origins:
|
||||
- http://ocis.domain.com
|
||||
- https://ocis.domain.com
|
||||
|
||||
- id: oc10
|
||||
name: OC10
|
||||
application_type: web
|
||||
secret: super
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- https://oc10.domain.com/apps/openidconnect/redirect/
|
||||
- https://oc10.domain.com/apps/openidconnect/redirect
|
||||
origins:
|
||||
- http://oc10.domain.com
|
||||
- https://oc10.domain.com
|
||||
```
|
||||
|
||||
The second file is proxy-config.json which configures the ocis internal service proxy routes. The policy_selector selector needs to be changed to forward to the related backend. ocis proxy makes the decision in this scenario to which backend the request needs to be forwarded based on the user storage.
|
||||
|
||||
```yaml
|
||||
{
|
||||
"HTTP": {
|
||||
"Namespace": "works.owncloud"
|
||||
},
|
||||
"policy_selector": {
|
||||
"migration": {
|
||||
"acc_found_policy" : "reva",
|
||||
"acc_not_found_policy": "oc10",
|
||||
"unauthenticated_policy": "oc10"
|
||||
}
|
||||
"policies": [
|
||||
{
|
||||
"name": "reva",
|
||||
"routes": [
|
||||
{
|
||||
"endpoint": "/",
|
||||
"backend": "http://localhost:9100"
|
||||
},
|
||||
{
|
||||
....
|
||||
```
|
||||
|
||||
Glauth needs to be configured to utilize oc10 as primary user backend.
|
||||
|
||||
```yaml
|
||||
GLAUTH_BACKEND_DATASTORE: owncloud
|
||||
GLAUTH_BACKEND_SERVERS: https://${OC10_DOMAIN}/apps/graphapi/v1.0
|
||||
GLAUTH_BACKEND_BASEDN: dc=example,dc=org
|
||||
STORAGE_STORAGE_METADATA_PROVIDER_DRIVER: owncloud
|
||||
STORAGE_STORAGE_METADATA_DATA_PROVIDER_DRIVER: owncloud
|
||||
ACCOUNTS_STORAGE_DISK_PATH: /var/tmp/ocis-accounts # Accounts fails to start when cs3 backend is used atm
|
||||
```
|
||||
|
||||
To allow konnectd to glauth, ldap needs to be configured have to be set.
|
||||
|
||||
```yaml
|
||||
# Konnectd ldap setup
|
||||
LDAP_URI: ldap://localhost:9125
|
||||
LDAP_BINDDN: "cn=admin,dc=example,dc=org"
|
||||
LDAP_BINDPW: "admin"
|
||||
LDAP_BASEDN: "dc=example,dc=org"
|
||||
LDAP_SCOPE: sub
|
||||
LDAP_LOGIN_ATTRIBUTE: uid
|
||||
LDAP_EMAIL_ATTRIBUTE: mail
|
||||
LDAP_NAME_ATTRIBUTE: givenName
|
||||
LDAP_UUID_ATTRIBUTE: uid
|
||||
LDAP_UUID_ATTRIBUTE_TYPE: text
|
||||
LDAP_FILTER: "(objectClass=posixaccount)"
|
||||
```
|
||||
|
||||
#### oc10
|
||||
|
||||
Owncloud 10 needs the graph api extensions to work in this setup. This extension is needed for Glauth to get oc10 users. It's necessary to add a image build step which extends owncloud/server:latest docker image with the app. The app is provided as tarball in the folder oc10/apps
|
||||
|
||||
```bash
|
||||
└───oc10
|
||||
│ │ Dockerfile
|
||||
│ │
|
||||
│ └───apps
|
||||
│ │ │ graphapi-0.1.0.tar.gz
|
||||
```
|
||||
|
||||
The docker files is pretty simple
|
||||
|
||||
```Dockerfile
|
||||
|
||||
# Take the latest owncloud/server image as base
|
||||
FROM owncloud/server:latest
|
||||
|
||||
# Add the provided tarballs into oc10's apps folder
|
||||
ADD apps/graphapi-0.1.0.tar.gz /var/www/owncloud/apps/
|
||||
```
|
||||
|
||||
The build is triggered by the terminal command `docker-compose build` from the root folder.
|
||||
|
||||
Constraints: In this setup it's mandatory that the user has an email adress set in oc10.
|
||||
148
docs/ocis/deployment/ocis_traefik.md
Normal file
148
docs/ocis/deployment/ocis_traefik.md
Normal file
@@ -0,0 +1,148 @@
|
||||
---
|
||||
title: "ocis with traefik deployment scenario"
|
||||
date: 2020-10-12T14:04:00+01:00
|
||||
weight: 24
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/ocis/deployment
|
||||
geekdocFilePath: ocis_traefik.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Overview
|
||||
|
||||
* ocis running on a hcloud node behind traefik as reverse proxy
|
||||
* Cloudflare DNS is resolving the domain
|
||||
* Letsencrypt provides a ssl certificate for the domain
|
||||
* Traefik docker container terminates ssl and forwards http requests to ocis
|
||||
|
||||
## Node
|
||||
|
||||
### Requirements
|
||||
|
||||
* Server running Ubuntu 20.04 is public availible with a static ip address
|
||||
* Two A-records for both domains are pointing on the servers ip address
|
||||
* Create user
|
||||
|
||||
`$ sudo adduser username`
|
||||
|
||||
* Add user to sudo group
|
||||
|
||||
`$ sudo usermod -aG sudo username`
|
||||
|
||||
* Add users pub key to `~/.ssh/authorized_keys`
|
||||
* Setup ssh to permit authorisation only by ssh key
|
||||
* Install docker
|
||||
|
||||
`$ sudo apt install docker.io`
|
||||
|
||||
* Add user to docker group
|
||||
|
||||
`$ sudo usermod -aG docker username`
|
||||
|
||||
* Install docker-compose via
|
||||
|
||||
`$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose`
|
||||
|
||||
(docker compose version 1.27.4 as of today)
|
||||
* Make docker-compose executable
|
||||
|
||||
`$ sudo chmod +x /usr/local/bin/docker-compose`
|
||||
|
||||
* Environment variables for OCIS Stack are provided by .env file
|
||||
|
||||
### Setup on server
|
||||
|
||||
* Clone ocis repository
|
||||
|
||||
`git clone https://github.com/owncloud/ocis.git`
|
||||
|
||||
* Copy example folder to /opt
|
||||
|
||||
`cp deployment/examples/ocis_traefik /opt/`
|
||||
|
||||
* Overwrite OCIS_DOMAIN in .env with your.domain.com
|
||||
|
||||
`sed -i 's/ocis.domain.com/your.domain.com/g' /opt/ocis_traefik/.env`
|
||||
|
||||
* Overwrite redirect uri with your.domain.com in identifier-registration.yml
|
||||
|
||||
`sed -i 's/ocis.domain.com/your.domain.com/g' /opt/ocis_traefik/config/identifier-registration.yml`
|
||||
|
||||
* Change into deployment folder
|
||||
|
||||
`cd /opt/ocis_traefik`
|
||||
|
||||
* Start application stack
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
### Stack
|
||||
|
||||
The application stack contains two containers. The first one is a traefik proxy which is terminating ssl and forwards the requests to the internal docker network. Additional, traefik is creating a certificate that is stored in `acme.json` in the folder `letsencrypt` inside the users home directory.
|
||||
The second one is th ocis server which is exposing the webservice on port 9200 to traefic.
|
||||
|
||||
### Config
|
||||
|
||||
Edit docker-compose.yml file to fit your domain setup
|
||||
|
||||
```yaml
|
||||
...
|
||||
traefik:
|
||||
image: "traefik:v2.2"
|
||||
...
|
||||
labels:
|
||||
...
|
||||
# Email address is neccesary for certificate creation
|
||||
- "--certificatesresolvers.ocisresolver.acme.email=username@${OCIS_DOMAIN}"
|
||||
...
|
||||
```
|
||||
|
||||
```yaml
|
||||
ocis:
|
||||
container_name: ocis
|
||||
...
|
||||
labels:
|
||||
...
|
||||
# This is the domain for which traefik is creating the certificate from letsencrypt
|
||||
- "traefik.http.routers.ocis.rule=Host(`${OCIS_DOMAIN}`)"
|
||||
...
|
||||
```
|
||||
|
||||
In this example, ssl is terminated from traefik while inside of the docker network the services are comunicating via http. For this `PROXY_TLS: "false"` as environment parameter for ocis has to be set.
|
||||
|
||||
For ocis to work properly it's neccesary to provide one config file.
|
||||
Change identifier-registration.yml to match your domain.
|
||||
|
||||
```yaml
|
||||
---
|
||||
# OpenID Connect client registry.
|
||||
clients:
|
||||
- id: phoenix
|
||||
name: OCIS
|
||||
application_type: web
|
||||
insecure: yes
|
||||
trusted: yes
|
||||
redirect_uris:
|
||||
- http://ocis.domain.com/
|
||||
- https://ocis.domain.com/
|
||||
- http://ocis.domain.com/oidc-callback.html
|
||||
- https://ocis.domain.com/oidc-callback.html
|
||||
- http://ocis.domain.com/oidc-silent-redirect.html
|
||||
- https://ocis.domain.com/oidc-silent-redirect.html
|
||||
origins:
|
||||
- http://ocis.domain.com
|
||||
- https://ocis.domain.com
|
||||
```
|
||||
|
||||
To make it availible for ocis inside of the container, `config` hast to be mounted as volume.
|
||||
|
||||
```yaml
|
||||
...
|
||||
volumes:
|
||||
- ./config:/etc/ocis
|
||||
environment:
|
||||
...
|
||||
KONNECTD_IDENTIFIER_REGISTRATION_CONF: "/etc/ocis/identifier-registration.yml"
|
||||
...
|
||||
```
|
||||
@@ -3,7 +3,7 @@ title: "Development"
|
||||
date: 2020-10-01T20:35:00+01:00
|
||||
weight: -12
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/development
|
||||
geekdocEditPath: edit/master/docs/ocis/development
|
||||
geekdocFilePath: _index.md
|
||||
---
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Build the documentation"
|
||||
date: 2020-07-27T08:39:38+00:00
|
||||
weight: 99
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/docs/development
|
||||
geekdocEditPath: edit/master/docs/ocis/development
|
||||
geekdocFilePath: building-docs.md
|
||||
---
|
||||
|
||||
@@ -26,11 +26,11 @@ hugo -D server
|
||||
|
||||
Then open "http://localhost:1313/"
|
||||
|
||||
When making changes to the docs, run
|
||||
When making changes to the docs, run
|
||||
|
||||
```bash
|
||||
rsync -ax --delete ../docs/ content/
|
||||
```
|
||||
```
|
||||
|
||||
in the hugo folder and the server will pick up the changes and reload the page automatically.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user