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
Select Git revision
  • 18-implement-textgridlockmanager
  • 5-initial-setup-integration-junit-tests-for-tgapi
  • main
  • 1.0.0
  • 1.0.1
  • 1.0.2
  • 1.1.0
  • 1.1.1
  • 1.1.2
  • 1.1.3
  • 1.2.0
  • 1.2.1
  • 1.2.2
  • 1.2.3
  • 1.2.4
  • 1.2.5
  • 1.3.0
  • 1.3.1
  • 1.4.0
  • 1.4.1
  • 1.4.2
21 results

Target

Select target project
No results found
Select Git revision
  • 18-implement-textgridlockmanager
  • 5-initial-setup-integration-junit-tests-for-tgapi
  • main
  • 1.0.0
  • 1.0.1
  • 1.0.2
  • 1.1.0
  • 1.1.1
  • 1.1.2
  • 1.1.3
  • 1.2.0
  • 1.2.1
  • 1.2.2
  • 1.2.3
  • 1.2.4
  • 1.2.5
  • 1.3.0
  • 1.3.1
  • 1.4.0
  • 1.4.1
  • 1.4.2
21 results
Show changes

Commits on Source 9

8 files
+ 3188
1510
Compare changes
  • Side-by-side
  • Inline

Files

+47 −4
Original line number Diff line number Diff line
@@ -7,16 +7,18 @@ workflow:
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_TAG

stages:
  - test
  - release
  - build
  - deploy

variables:
  harbor_registry: "harbor.gwdg.de"
  harbor_repo: "sub-fe"

  project_name: "repdav"

lint dockerfile:
  stage: test
@@ -40,7 +42,7 @@ lint dockerfile:

release:
  stage: release
  image: docker.io/node:16.14
  image: docker.io/node:18.12
  before_script:
    - npm ci --unsafe-perm
  script:
@@ -66,8 +68,49 @@ build container image:
      --build-arg build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
      --build-arg vcs_ref=${CI_COMMIT_SHORT_SHA}
      --build-arg version=${version}
      --destination $CI_REGISTRY_IMAGE/repdav:$version
      --destination $harbor_registry/$harbor_repo/repdav:$version
      --destination $CI_REGISTRY_IMAGE/$project_name:$version
      --destination $harbor_registry/$harbor_repo/$project_name:$version
  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_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
+7 −0
Original line number Diff line number Diff line
# [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)


Original line number Diff line number Diff line
@@ -11,14 +11,11 @@ services:
    build:
      context: .
    ports:
      - ${port:-8080}:${port:-8080}
      - ${REPDAV_PORT:-8080}:${REPDAV_PORT:-8080}
    environment:
      host: ${host:-0.0.0.0}
      port: ${port:-8080}
      sentry_dsn: ${sentry_dsn}
      tg_auth_wsdl: "https://textgridlab.org/1.0/tgauth/wsdl/tgextra.wsdl"
      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/"
      REPDAV_HOST: ${REPDAV_HOST:-0.0.0.0}
      REPDAV_PORT: ${REPDAV_PORT:-8080}
      SENTRY_DSN: ${SENTRY_DSN}
      TEXTGRID_HOST: ${TEXTGRID_HOST}
    volumes:
      - $PWD/src:/app
+3063 −1433

File changed.

Preview size limit exceeded, changes collapsed.

+6 −4
Original line number Diff line number Diff line
@@ -2,10 +2,11 @@
  "name": "repdav",
  "private": true,
  "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/gitlab": "^7.0.4",
    "semantic-release": "^19.0.2"
    "@semantic-release/gitlab": "^9.5.1",
    "semantic-release": "^19.0.5"
  },
  "release": {
    "branches": [
@@ -38,7 +39,8 @@
        {
          "assets": [
            "CHANGELOG.md"
          ]
          ],
          "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
        }
      ]
    ]
+11 −13
Original line number Diff line number Diff line
@@ -4,8 +4,6 @@

"""Configure and start the WSGI DAV Server."""
import logging
import os

import sentry_sdk
from cheroot import wsgi
from wsgidav.wsgidav_app import WsgiDAVApp
@@ -14,13 +12,11 @@ from repdav.config import AppConfig
app_config = AppConfig()

if app_config.dsn:
    sentry_sdk.init(
        app_config.dsn,
        traces_sample_rate=1.0
    )
    sentry_sdk.init(app_config.dsn, traces_sample_rate=1.0)

logging.basicConfig(level=logging.DEBUG,
                    format='%(name)s %(levelname)s %(asctime)s %(message)s')
logging.basicConfig(
    level=logging.DEBUG, format="%(name)s %(levelname)s %(asctime)s %(message)s"
)
_logger = logging.getLogger(__name__)
_logger.propagate = True

@@ -31,12 +27,13 @@ tmp_logger.setLevel(logging.DEBUG)

# Configuration of the WsgiDAVApp.
# https://wsgidav.readthedocs.io/en/latest/user_guide_configure.html
# TODO: move to config.py
config = {
    "host": os.getenv("host") or "localhost",
    "port": int(os.getenv("port") or "8080"),
    "host": app_config.host,
    "port": app_config.port,
    "provider_mapping": {
        "/": {"class": "repdav.textgrid_named_dav_provider.TextgridNamedResourceProvider"},
        "/": {
            "class": "repdav.textgrid_named_dav_provider.TextgridNamedResourceProvider"
        },
    },
    "verbose": 4,
    "http_authenticator": {
@@ -47,7 +44,8 @@ config = {
        "default_to_digest": False,
        # Name of a header field that will be accepted as authorized user
        "trusted_auth_header": None,
    }
    },
    "tg_host": app_config.tg_host,
}

app = WsgiDAVApp(config)
Original line number Diff line number Diff line
@@ -3,63 +3,51 @@
# SPDX-License-Identifier: CC0-1.0

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:
    mapping = {
        "_auth_wsdl": "tg_auth_wsdl",
        "_auth_address": "tg_auth_address",
        "_dsn": "sentry_dsn",
        "_host": "tg_host",
        "_nav_address": "tg_nav_address",
    }
    return mapping[internal_name]
def check_port(port):
    """Check if port is set correctly to a non-privileged value."""
    if 1000 <= port <= 65535:
        return port
    raise ValueError(f"{port} is not a valid Port.")


# TODO check for trailing "/", add if missing!
# TODO check URLs for validity

class AppConfig:
    # TODO: configure the app according to the set environment (i.e. prod or dev)
    def __init__(self) -> None:
        self._dsn = os.getenv(lookup_env_name("_dsn"))

    @property
    def dsn(self) -> str:
        return self._dsn

    """Settings that can be be configured from the environment."""

class TextgridConfig:
    def __init__(self) -> None:
        self._auth_wsdl = os.getenv(lookup_env_name("_auth_wsdl"))
        self._auth_address = os.getenv(lookup_env_name("_auth_address"))
        self._nav_address = os.getenv(lookup_env_name("_nav_address"))
        self._host = os.getenv(lookup_env_name("_host"))
        self._dsn = check_url(os.getenv("SENTRY_DSN"))
        self._host = os.getenv("REPDAV_HOST") or "localhost"
        self._port = check_port(int(os.getenv("REPDAV_PORT") or 8080))
        self._tg_host = check_url(os.getenv("TEXTGRID_HOST"))

    @property
    def auth_wsdl(self) -> str:
        if self._auth_wsdl:
            return self._auth_wsdl
        raise EnvNotSetError(lookup_env_name("_auth_wsdl"))
    def dsn(self) -> Optional[str]:
        """Sentry DSN."""
        return self._dsn

    @property
    def auth_address(self) -> str:
        if self._auth_address:
            return self._auth_address
        raise EnvNotSetError(lookup_env_name("_auth_address"))
    def host(self) -> str:
        """Service hostname."""
        return self._host

    @property
    def nav_address(self) -> str:
        if self._nav_address:
            return self._nav_address
        raise EnvNotSetError(lookup_env_name("_nav_address"))
    def port(self) -> int:
        """Service port."""
        return self._port

    @property
    def host(self) -> str:
        if self._host:
            return self._host
        raise EnvNotSetError(lookup_env_name("_host"))
    def tg_host(self) -> Optional[str]:
        """Textgrid host URL."""
        return self._tg_host
Original line number Diff line number Diff line
@@ -21,6 +21,16 @@ from repdav.stream_tools import FileLikeQueue
_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):
    """Top level collection that incorporates Textgrid projects.

@@ -30,8 +40,9 @@ class TextgridRoot(DAVCollection):
    def __init__(self, path, environ):
        DAVCollection.__init__(self, path, environ)
        self._sid = environ["wsgidav.auth.user_name"]
        config = TextgridConfig()
        config = tg_config(environ)
        self._auth = TextgridAuth(config)
        self.projects = ()

    def get_display_info(self):
        return {"type": "Textgrid root collection"}
@@ -83,7 +94,7 @@ class TextgridProject(DAVCollection):
        _logger.debug("Called TextgridProject.__init__(self, %s, environ).", path)
        DAVCollection.__init__(self, path, environ)
        self._sid = environ["wsgidav.auth.user_name"]
        config = TextgridConfig()
        config = tg_config(environ)
        self._tgsearch = TextgridSearch(config.search)
        self._project_id = self.path.split("/")[-1]

@@ -175,7 +186,7 @@ class TextgridAggregation(DAVCollection):
        DAVCollection.__init__(self, path, environ)
        self._sid = environ["wsgidav.auth.user_name"]
        self._info = info
        config = TextgridConfig()
        config = tg_config(environ)
        self._tgsearch = TextgridSearch(config.search)
        self._tguri = self.path.split("/")[-1]

@@ -261,7 +272,7 @@ class TextgridResource(DAVNonCollection):
        self._tguri = self.path.split("/")[-1]
        self._info = info
        self.upload_thread = None
        config = TextgridConfig()
        config = tg_config(environ)
        self._crud = TextgridCRUD(config.crud)

    def get_content_length(self):
@@ -273,7 +284,9 @@ class TextgridResource(DAVNonCollection):
        return self._info[self.name]["format"]

    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)

    def get_content_title(self):