Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • dariah-de/textgridrep/repdav
1 result
Show changes
Commits on Source (9)
...@@ -7,16 +7,18 @@ workflow: ...@@ -7,16 +7,18 @@ workflow:
rules: rules:
- if: $CI_MERGE_REQUEST_IID - if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG
stages: stages:
- test - test
- release - release
- build - build
- deploy
variables: variables:
harbor_registry: "harbor.gwdg.de" harbor_registry: "harbor.gwdg.de"
harbor_repo: "sub-fe" harbor_repo: "sub-fe"
project_name: "repdav"
lint dockerfile: lint dockerfile:
stage: test stage: test
...@@ -40,7 +42,7 @@ lint dockerfile: ...@@ -40,7 +42,7 @@ lint dockerfile:
release: release:
stage: release stage: release
image: docker.io/node:16.14 image: docker.io/node:18.12
before_script: before_script:
- npm ci --unsafe-perm - npm ci --unsafe-perm
script: script:
...@@ -66,8 +68,49 @@ build container image: ...@@ -66,8 +68,49 @@ build container image:
--build-arg build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
--build-arg vcs_ref=${CI_COMMIT_SHORT_SHA} --build-arg vcs_ref=${CI_COMMIT_SHORT_SHA}
--build-arg version=${version} --build-arg version=${version}
--destination $CI_REGISTRY_IMAGE/repdav:$version --destination $CI_REGISTRY_IMAGE/$project_name:$version
--destination $harbor_registry/$harbor_repo/repdav:$version --destination $harbor_registry/$harbor_repo/$project_name:$version
rules: rules:
# prevent job creation on release commits to $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE =~ /^chore\(release\):/
when: never
- if: $CI_MERGE_REQUEST_IID - if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG
generate app sbom:
stage: deploy
image: docker.io/node:18.12
before_script:
- npm ci --ignore-scripts
- npm run build
script:
- npx cdxgen
--type nodejs
--required-only
--server-url https://deps.sub.uni-goettingen.de
--api-key ${DEPS_UPLOAD_TOKEN}
--project-name ${project_name}
--project-version ${CI_COMMIT_TAG}
rules:
- if: $CI_COMMIT_TAG
generate container sbom:
stage: deploy
image: docker.io/alpine:3.16
before_script:
- apk add curl
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
script:
- syft --output cyclonedx-json --file bom.json
$CI_REGISTRY_IMAGE/${project_name}:${CI_COMMIT_TAG}
- 'curl -X POST "https://deps.sub.uni-goettingen.de/api/v1/bom"
--header "accept: application/json"
--header "X-Api-Key: ${DEPS_UPLOAD_TOKEN}"
--header "Content-Type: multipart/form-data"
--form "autoCreate=true"
--form "projectName=${project_name}-container"
--form "projectVersion=${CI_COMMIT_TAG}"
--form "bom=@bom.json"'
rules:
- if: $CI_COMMIT_TAG
# [1.2.0](https://gitlab.gwdg.de/dariah-de/textgridrep/repdav/compare/1.1.3...1.2.0) (2023-01-09)
### Features
* **textgrid_dav_provider:** initialize textgrid config with "tg_host" from wsgidav environ ([fab21bc](https://gitlab.gwdg.de/dariah-de/textgridrep/repdav/commit/fab21bcf60737f8d710f3e8419195ba10d20139f))
## [1.1.3](https://gitlab.gwdg.de/dariah-de/textgridrep/repdav/compare/1.1.2...1.1.3) (2022-11-29) ## [1.1.3](https://gitlab.gwdg.de/dariah-de/textgridrep/repdav/compare/1.1.2...1.1.3) (2022-11-29)
......
...@@ -11,14 +11,11 @@ services: ...@@ -11,14 +11,11 @@ services:
build: build:
context: . context: .
ports: ports:
- ${port:-8080}:${port:-8080} - ${REPDAV_PORT:-8080}:${REPDAV_PORT:-8080}
environment: environment:
host: ${host:-0.0.0.0} REPDAV_HOST: ${REPDAV_HOST:-0.0.0.0}
port: ${port:-8080} REPDAV_PORT: ${REPDAV_PORT:-8080}
sentry_dsn: ${sentry_dsn} SENTRY_DSN: ${SENTRY_DSN}
tg_auth_wsdl: "https://textgridlab.org/1.0/tgauth/wsdl/tgextra.wsdl" TEXTGRID_HOST: ${TEXTGRID_HOST}
tg_auth_address: "https://textgridlab.org/1.0/tgauth/tgextra.php"
tg_nav_address: "https://textgridlab.org/1.0/tgsearch/navigation/"
tg_host: "https://textgridlab.org/"
volumes: volumes:
- $PWD/src:/app - $PWD/src:/app
Source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
"name": "repdav", "name": "repdav",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@semantic-release/changelog": "^6.0.1", "@appthreat/cdxgen": "^6.0.0",
"@semantic-release/changelog": "^6.0.2",
"@semantic-release/git": "^10.0.1", "@semantic-release/git": "^10.0.1",
"@semantic-release/gitlab": "^7.0.4", "@semantic-release/gitlab": "^9.5.1",
"semantic-release": "^19.0.2" "semantic-release": "^19.0.5"
}, },
"release": { "release": {
"branches": [ "branches": [
...@@ -38,7 +39,8 @@ ...@@ -38,7 +39,8 @@
{ {
"assets": [ "assets": [
"CHANGELOG.md" "CHANGELOG.md"
] ],
"message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
} }
] ]
] ]
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
"""Configure and start the WSGI DAV Server.""" """Configure and start the WSGI DAV Server."""
import logging import logging
import os
import sentry_sdk import sentry_sdk
from cheroot import wsgi from cheroot import wsgi
from wsgidav.wsgidav_app import WsgiDAVApp from wsgidav.wsgidav_app import WsgiDAVApp
...@@ -14,13 +12,11 @@ from repdav.config import AppConfig ...@@ -14,13 +12,11 @@ from repdav.config import AppConfig
app_config = AppConfig() app_config = AppConfig()
if app_config.dsn: if app_config.dsn:
sentry_sdk.init( sentry_sdk.init(app_config.dsn, traces_sample_rate=1.0)
app_config.dsn,
traces_sample_rate=1.0
)
logging.basicConfig(level=logging.DEBUG, logging.basicConfig(
format='%(name)s %(levelname)s %(asctime)s %(message)s') level=logging.DEBUG, format="%(name)s %(levelname)s %(asctime)s %(message)s"
)
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
_logger.propagate = True _logger.propagate = True
...@@ -31,12 +27,13 @@ tmp_logger.setLevel(logging.DEBUG) ...@@ -31,12 +27,13 @@ tmp_logger.setLevel(logging.DEBUG)
# Configuration of the WsgiDAVApp. # Configuration of the WsgiDAVApp.
# https://wsgidav.readthedocs.io/en/latest/user_guide_configure.html # https://wsgidav.readthedocs.io/en/latest/user_guide_configure.html
# TODO: move to config.py
config = { config = {
"host": os.getenv("host") or "localhost", "host": app_config.host,
"port": int(os.getenv("port") or "8080"), "port": app_config.port,
"provider_mapping": { "provider_mapping": {
"/": {"class": "repdav.textgrid_named_dav_provider.TextgridNamedResourceProvider"}, "/": {
"class": "repdav.textgrid_named_dav_provider.TextgridNamedResourceProvider"
},
}, },
"verbose": 4, "verbose": 4,
"http_authenticator": { "http_authenticator": {
...@@ -47,7 +44,8 @@ config = { ...@@ -47,7 +44,8 @@ config = {
"default_to_digest": False, "default_to_digest": False,
# Name of a header field that will be accepted as authorized user # Name of a header field that will be accepted as authorized user
"trusted_auth_header": None, "trusted_auth_header": None,
} },
"tg_host": app_config.tg_host,
} }
app = WsgiDAVApp(config) app = WsgiDAVApp(config)
......
...@@ -3,63 +3,51 @@ ...@@ -3,63 +3,51 @@
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
import os import os
from typing import Optional
from urllib.parse import urlparse
from .errors import EnvNotSetError
# TODO: remove "tg_auth_wsdl", "tg_auth_address", "tg_nav_address" def check_url(url):
"""Check if `url` can be parsed."""
if url:
result = urlparse(url)
if result.scheme and result.netloc:
return url
raise ValueError(f"{url} is not a valid URL.")
def lookup_env_name(internal_name: str) -> str: def check_port(port):
mapping = { """Check if port is set correctly to a non-privileged value."""
"_auth_wsdl": "tg_auth_wsdl", if 1000 <= port <= 65535:
"_auth_address": "tg_auth_address", return port
"_dsn": "sentry_dsn", raise ValueError(f"{port} is not a valid Port.")
"_host": "tg_host",
"_nav_address": "tg_nav_address",
}
return mapping[internal_name]
# TODO check for trailing "/", add if missing!
# TODO check URLs for validity
class AppConfig: class AppConfig:
# TODO: configure the app according to the set environment (i.e. prod or dev) """Settings that can be be configured from the environment."""
def __init__(self) -> None:
self._dsn = os.getenv(lookup_env_name("_dsn"))
@property
def dsn(self) -> str:
return self._dsn
class TextgridConfig:
def __init__(self) -> None: def __init__(self) -> None:
self._auth_wsdl = os.getenv(lookup_env_name("_auth_wsdl")) self._dsn = check_url(os.getenv("SENTRY_DSN"))
self._auth_address = os.getenv(lookup_env_name("_auth_address")) self._host = os.getenv("REPDAV_HOST") or "localhost"
self._nav_address = os.getenv(lookup_env_name("_nav_address")) self._port = check_port(int(os.getenv("REPDAV_PORT") or 8080))
self._host = os.getenv(lookup_env_name("_host")) self._tg_host = check_url(os.getenv("TEXTGRID_HOST"))
@property @property
def auth_wsdl(self) -> str: def dsn(self) -> Optional[str]:
if self._auth_wsdl: """Sentry DSN."""
return self._auth_wsdl return self._dsn
raise EnvNotSetError(lookup_env_name("_auth_wsdl"))
@property @property
def auth_address(self) -> str: def host(self) -> str:
if self._auth_address: """Service hostname."""
return self._auth_address return self._host
raise EnvNotSetError(lookup_env_name("_auth_address"))
@property @property
def nav_address(self) -> str: def port(self) -> int:
if self._nav_address: """Service port."""
return self._nav_address return self._port
raise EnvNotSetError(lookup_env_name("_nav_address"))
@property @property
def host(self) -> str: def tg_host(self) -> Optional[str]:
if self._host: """Textgrid host URL."""
return self._host return self._tg_host
raise EnvNotSetError(lookup_env_name("_host"))
...@@ -21,6 +21,16 @@ from repdav.stream_tools import FileLikeQueue ...@@ -21,6 +21,16 @@ from repdav.stream_tools import FileLikeQueue
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
def tg_config(environ):
"""Initialize Textgrid configuration either with or without host setting. This
works around an [issue with tgclients](https://gitlab.gwdg.de/dariah-de/textgridrep/textgrid-python-clients/-/issues/59).
"""
tg_host = environ["wsgidav.config"]["tg_host"]
if tg_host:
return TextgridConfig(tg_host)
return TextgridConfig()
class TextgridRoot(DAVCollection): class TextgridRoot(DAVCollection):
"""Top level collection that incorporates Textgrid projects. """Top level collection that incorporates Textgrid projects.
...@@ -30,8 +40,9 @@ class TextgridRoot(DAVCollection): ...@@ -30,8 +40,9 @@ class TextgridRoot(DAVCollection):
def __init__(self, path, environ): def __init__(self, path, environ):
DAVCollection.__init__(self, path, environ) DAVCollection.__init__(self, path, environ)
self._sid = environ["wsgidav.auth.user_name"] self._sid = environ["wsgidav.auth.user_name"]
config = TextgridConfig() config = tg_config(environ)
self._auth = TextgridAuth(config) self._auth = TextgridAuth(config)
self.projects = ()
def get_display_info(self): def get_display_info(self):
return {"type": "Textgrid root collection"} return {"type": "Textgrid root collection"}
...@@ -83,7 +94,7 @@ class TextgridProject(DAVCollection): ...@@ -83,7 +94,7 @@ class TextgridProject(DAVCollection):
_logger.debug("Called TextgridProject.__init__(self, %s, environ).", path) _logger.debug("Called TextgridProject.__init__(self, %s, environ).", path)
DAVCollection.__init__(self, path, environ) DAVCollection.__init__(self, path, environ)
self._sid = environ["wsgidav.auth.user_name"] self._sid = environ["wsgidav.auth.user_name"]
config = TextgridConfig() config = tg_config(environ)
self._tgsearch = TextgridSearch(config.search) self._tgsearch = TextgridSearch(config.search)
self._project_id = self.path.split("/")[-1] self._project_id = self.path.split("/")[-1]
...@@ -175,7 +186,7 @@ class TextgridAggregation(DAVCollection): ...@@ -175,7 +186,7 @@ class TextgridAggregation(DAVCollection):
DAVCollection.__init__(self, path, environ) DAVCollection.__init__(self, path, environ)
self._sid = environ["wsgidav.auth.user_name"] self._sid = environ["wsgidav.auth.user_name"]
self._info = info self._info = info
config = TextgridConfig() config = tg_config(environ)
self._tgsearch = TextgridSearch(config.search) self._tgsearch = TextgridSearch(config.search)
self._tguri = self.path.split("/")[-1] self._tguri = self.path.split("/")[-1]
...@@ -261,7 +272,7 @@ class TextgridResource(DAVNonCollection): ...@@ -261,7 +272,7 @@ class TextgridResource(DAVNonCollection):
self._tguri = self.path.split("/")[-1] self._tguri = self.path.split("/")[-1]
self._info = info self._info = info
self.upload_thread = None self.upload_thread = None
config = TextgridConfig() config = tg_config(environ)
self._crud = TextgridCRUD(config.crud) self._crud = TextgridCRUD(config.crud)
def get_content_length(self): def get_content_length(self):
...@@ -273,7 +284,9 @@ class TextgridResource(DAVNonCollection): ...@@ -273,7 +284,9 @@ class TextgridResource(DAVNonCollection):
return self._info[self.name]["format"] return self._info[self.name]["format"]
def get_content(self): def get_content(self):
_logger.debug("Called TextgridResource.get_content(self) with path: %s", self.path) _logger.debug(
"Called TextgridResource.get_content(self) with path: %s", self.path
)
return io.BytesIO(self._crud.read_data(self._tguri, self._sid).content) return io.BytesIO(self._crud.read_data(self._tguri, self._sid).content)
def get_content_title(self): def get_content_title(self):
......