Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1e2010e
[Fix] Add .gitignore
ledsoft Oct 20, 2023
1b394d5
[Fix] Ignore prop-types eslint rule.
ledsoft Oct 20, 2023
778b612
[OIDC] Add basic OIDC infrastructure code.
ledsoft Oct 20, 2023
45e9c33
[Fix] Fix test setup.
ledsoft Oct 20, 2023
01dbd8c
[OIDC] Extend .env.example with authentication-related parameters.
ledsoft Oct 20, 2023
1cb2d94
[OIDC] Working on integration with OIDC authentication service.
ledsoft Oct 20, 2023
74876f3
[OIDC] Implement React-based OIDC redirect components.
ledsoft Oct 26, 2023
f89b2d3
[OIDC] Ensure path resolution works in OidcMainView.
ledsoft Oct 26, 2023
a88b5e4
[OIDC] Move user profile load into MainView to prevent reloads on OID…
ledsoft Oct 26, 2023
cfc8250
[Ref] Simplify MainView component authorization.
ledsoft Oct 26, 2023
b05f04e
[OIDC] Implement proper OIDC logout.
ledsoft Oct 26, 2023
a356103
[OIDC] Open Keycloak account management on user profile link click.
ledsoft Oct 26, 2023
901fbcc
[Fix] Fix UnhandledPromiseRejection error in tests.
ledsoft Oct 26, 2023
981b988
[Doc] Improve OIDC setup documentation.
ledsoft Oct 26, 2023
3313f22
Merge pull request #4 from akaene/main
blcham Nov 2, 2023
5fdcb3c
Add GH action to push docker image
blcham Nov 3, 2023
7237c82
Merge pull request #5 from kbss-cvut/publish-docker-image
blcham Nov 3, 2023
2b3f60a
[Fix] Provide reasonable defaults for non-required configuration vari…
ledsoft Nov 8, 2023
9553c60
[Fix] Add auth-related variables into Docker config.js.template
ledsoft Nov 9, 2023
af388ee
Merge branch 'kbss-cvut:main' into main
ledsoft Nov 9, 2023
94f64ab
[Fix] Publish docker image only on push to main.
ledsoft Nov 9, 2023
3dc3c62
Merge branch 'kbss-cvut:main' into main
ledsoft Nov 9, 2023
9696c48
Merge pull request #6 from akaene/main
blcham Nov 9, 2023
e4136ff
[Fix] Add auth-related variables into Docker environment substitution.
ledsoft Nov 9, 2023
78abf51
Merge branch 'kbss-cvut:main' into main
ledsoft Nov 9, 2023
edf3731
[OIDC] Allow listing users, but prevent editing them when using OIDC.
ledsoft Nov 9, 2023
2f3ece5
[OIDC] Prevent adding users when using OIDC.
ledsoft Nov 9, 2023
3a8a6f1
[OIDC] Use basename when resolving URL for OIDC signing redirect.
ledsoft Nov 13, 2023
7df0d22
[Fix] Fix history timestamp parsing.
ledsoft Nov 13, 2023
53fee97
[New] Add example docker-compose setup for internal authentication
blcham Nov 20, 2023
3bcc56d
[Fix] Fix css retrieval of graphdb
blcham Nov 20, 2023
6596d4a
[New] Deploy generic form generation script to clone form
blcham Nov 21, 2023
6668946
Merge pull request #9 from kbss-cvut/add-docker-compose-for-internal-…
blcham Nov 22, 2023
1a0d627
Merge pull request #7 from akaene/main
blcham Nov 22, 2023
48e1d0e
[New] Add docker-services for local development
blcham Nov 23, 2023
f088be2
Update development.md
blcham Nov 23, 2023
548e9de
[Fix] Add missing configuration file for development
blcham Nov 23, 2023
fcf6641
[Upd #3] Migrate to React 18
LaChope Nov 22, 2023
7d39e1a
[Upd #3] Importing utilities from s-forms
LaChope Nov 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 0 additions & 31 deletions .babelrc

This file was deleted.

7 changes: 5 additions & 2 deletions .docker/config.js.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ window.__config__ = {
LANGUAGE: '${LANGUAGE}',
NAVIGATOR_LANGUAGE: '${NAVIGATOR_LANGUAGE}',
BASENAME: '${BASENAME}',
EXTENSIONS: '${EXTENSIONS}'
}
EXTENSIONS: '${EXTENSIONS}',
AUTHENTICATION: '${AUTHENTICATION}',
AUTH_SERVER_URL: '${AUTH_SERVER_URL}',
AUTH_CLIENT_ID: '${AUTH_CLIENT_ID}'
}
2 changes: 1 addition & 1 deletion .docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
set -eu

envsubst '${API_URL} ${APP_TITLE} ${LANGUAGE} ${NAVIGATOR_LANGUAGE} ${BASENAME} ${EXTENSIONS}' < /etc/nginx/config.js.template > /var/www/config.js
envsubst '${API_URL} ${APP_TITLE} ${LANGUAGE} ${NAVIGATOR_LANGUAGE} ${BASENAME} ${EXTENSIONS} ${AUTHENTICATION} ${AUTH_SERVER_URL} ${AUTH_CLIENT_ID}' < /etc/nginx/config.js.template > /var/www/config.js

cp /etc/nginx/index.html.template /var/www/index.html
sed -i "s|%RECORD_MANAGER_BASENAME%|${BASENAME}|g" /var/www/index.html
Expand Down
14 changes: 11 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ RECORD_MANAGER_PROD_SERVER_PORT=8080
RECORD_MANAGER_LANGUAGE=cs
# Flag if language of the UI should be determined from browser settings. Possible values: true, false.
RECORD_MANAGER_NAVIGATOR_LANGUAGE=true
# Context path added to URL or "" in case application path should not be modified.
# Context path added to URL or "/" in case application path should not be modified.
RECORD_MANAGER_BASENAME=/record-manager
# List of extensions seperated by comma, currently supports only values: "kodi"
RECORD_MANAGER_EXTENSIONS=kodi
# List of extensions separated by comma, currently supports only values: "kodi"
RECORD_MANAGER_EXTENSIONS=kodi
# Authentication method - use "internal" for internal authentication or "oidc" for an external auth service compatible with OIDC
RECORD_MANAGER_AUTHENTICATION=internal
# Authentication server URL, applicable when AUTHENTICATION=oidc. In case of Keycloak, this would be the server URL including the
# realm used to authenticate users, e.g. http://localhost:8080/realms/record-manager
RECORD_MANAGER_AUTH_SERVER_URL=
# Client ID of this application in the OIDC authentication server. The client should have public access and valid redirect and origin URIs
# configured
RECORD_MANAGER_AUTH_CLIENT_ID=record-manager-ui
11 changes: 11 additions & 0 deletions .env.internal-auth
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RECORD_MANAGER_API_URL=http://localhost:1235/record-manager/record-manager-server
RECORD_MANAGER_APP_TITLE=Record Manager
RECORD_MANAGER_DEV_SERVER_PORT=3000
RECORD_MANAGER_PROD_SERVER_PORT=8080
RECORD_MANAGER_LANGUAGE=cs
RECORD_MANAGER_NAVIGATOR_LANGUAGE=true
RECORD_MANAGER_BASENAME=/
RECORD_MANAGER_EXTENSIONS=kodi
RECORD_MANAGER_AUTHENTICATION=internal
RECORD_MANAGER_AUTH_SERVER_URL=
RECORD_MANAGER_AUTH_CLIENT_ID=record-manager-ui
11 changes: 11 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RECORD_MANAGER_API_URL=http://localhost:8080/record-manager
RECORD_MANAGER_APP_TITLE=OFN Record Manager
RECORD_MANAGER_DEV_SERVER_PORT=3000
RECORD_MANAGER_PROD_SERVER_PORT=8080
RECORD_MANAGER_LANGUAGE=en
RECORD_MANAGER_NAVIGATOR_LANGUAGE=false
RECORD_MANAGER_BASENAME=/record-manager
RECORD_MANAGER_EXTENSIONS=
RECORD_MANAGER_AUTHENTICATION=internal
RECORD_MANAGER_AUTH_SERVER_URL=
RECORD_MANAGER_AUTH_CLIENT_ID=
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
"plugin:react/recommended"
],
"rules": {

"react/prop-types": "off"
}
}
37 changes: 37 additions & 0 deletions .github/workflows/merge-to-protected.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: "16.x"
- name: Install
run: npm install
- name: Build
run: npm run-script build
env:
CI: ""
- name: Test
env:
NODE_OPTIONS: "--max-old-space-size=4096"
run: npm run-script test
46 changes: 46 additions & 0 deletions .github/workflows/publish-docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Publish Docker Image

on:
push:
branches: [ main ]
workflow_dispatch:
env:
# Last fragment of identifier of the docker image
IMAGE_NAME: ${{ github.repository }}
# Group identifier of the docker image, typically ${{ github.repository_owner }} or ${{ github.repository }}
IMAGE_GROUP_NAME: ${{ github.repository_owner }}
MAIN_BRANCH_NAME: main

jobs:
build-and-publish:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Build docker image
run: docker build . --file Dockerfile --tag $IMAGE_NAME

- name: Log in to the Container registry
run: echo "${{ github.token }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin

- name: Push image
run: |
IMAGE_ID=docker.pkg.github.com/$IMAGE_GROUP_NAME/$IMAGE_NAME
# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
# Get branch name if merge to a branch
GIT_BRANCH_NAME=$(echo "${{ github.ref }}" | grep 'refs/heads/.*' | cut -d"/" -f 3)
# Get pull request id (e.g. "pr-123" from "/pulls/123")
PULL_REQUEST_ID=$(echo "${{ github.event.pull_request.number }}" | grep -v "^$" | sed 's/^/pr-/')
# Get tag id while strip "v" prefix (e.g. "1.2" from "v1.2")
TAG_ID=$(echo "${{ github.ref }}" | grep 'refs/tags/.*' | cut -d"/" -f 3 | sed -e 's/^v//')
# Version is either "git branch name"/"pull request id"/"tag id"
VERSION=${GIT_BRANCH_NAME:-${PULL_REQUEST_ID:-${TAG_ID}}}
# Use Docker `latest` tag convention
[ "$VERSION" == $MAIN_BRANCH_NAME ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.idea
*.iml
node_modules
build
coverage
junit.xml
.DS_store
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# BASE STAGE
# Prepare node, copy package.json
FROM node:14 AS base
FROM node:18 AS base
WORKDIR /usr/src/app
COPY package.json package-lock.json ./

Expand Down
13 changes: 0 additions & 13 deletions WEB-INF/web.xml

This file was deleted.

39 changes: 39 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module.exports = {
"plugins": [
"lodash",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-runtime"
],
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": 18,
"browsers": "last 2 versions, > 0.2%, ie 11, not dead"
},
"useBuiltIns": "usage",
"corejs": {
"version": 3,
"proposals": true
}
}
],
"@babel/preset-react"
],
"env": {
"test": {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"@babel/preset-react"
]
}
}
}
8 changes: 4 additions & 4 deletions config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const getEnv = (name, defaultValue) => {
};

export const API_URL = getEnv("API_URL");
export const APP_TITLE = getEnv("APP_TITLE");
export const LANGUAGE = getEnv("LANGUAGE");
export const NAVIGATOR_LANGUAGE = JSON.parse(getEnv("NAVIGATOR_LANGUAGE"));
export const BASENAME = getEnv("BASENAME");
export const APP_TITLE = getEnv("APP_TITLE", "Record Manager");
export const LANGUAGE = getEnv("LANGUAGE", "en");
export const NAVIGATOR_LANGUAGE = JSON.parse(getEnv("NAVIGATOR_LANGUAGE", "true"));
export const BASENAME = getEnv("BASENAME", "");
export const EXTENSIONS = getEnv("EXTENSIONS", "");
8 changes: 8 additions & 0 deletions deploy/internal-auth/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# In this setting it is assumed there is no apapche/nginx in front of the application
RECORD_SET_NAME=iauth-example
PORT=1235
RECORD_MANAGER_SERVER_URL=http://localhost:1235/record-manager/record-manager-server
FORMGEN_SERVICE_URL=http://s-pipes-engine:8080/s-pipes/service?_pId=clone-form
RECORD_MANAGER_APP_TITLE=Record manager
RECORD_MANAGER_BASENAME=/record-manager
LANGUAGE=en
22 changes: 22 additions & 0 deletions deploy/internal-auth/db-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM ontotext/graphdb:10.2.0

# Override parent entrypoint
ENTRYPOINT []

ENV GRAPHDB_HOME=/opt/graphdb/home
ENV GRAPHDB_INSTALL_DIR=/opt/graphdb/dist

WORKDIR ${GRAPHDB_HOME}

# Install libs related to RDF processing
RUN apk add py3-rdflib
RUN apk add perl-uri

# Copy initialization data and repository config
COPY init-data /root/graphdb-import
COPY init-config /repo-config
COPY bin/* ${GRAPHDB_INSTALL_DIR}/bin/

EXPOSE 7200

CMD ${GRAPHDB_INSTALL_DIR}/bin/repo-init.sh /repo-config ${GRAPHDB_HOME} & ${GRAPHDB_INSTALL_DIR}/bin/graphdb -Dgraphdb.home=${GRAPHDB_HOME} -Dgraphdb.logback=${GRAPHDB_INSTALL_DIR}/conf/logback.xml
75 changes: 75 additions & 0 deletions deploy/internal-auth/db-server/bin/get-rdf-subject-by-type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/python3

import sys
from rdflib import Graph, URIRef

def log(message):
print("ERROR: " + message, file=sys.stderr)

def check_params():
if len(sys.argv) != 3:
log(f"""Illegal number of parameters.

Script returns single subject of triple matching the pattern '?result a <type-uri>'
from the file specified by <rdf-file-path>.

Usage: {sys.argv[0]} <rdf-file-path> <type-uri>

Example: {sys.argv[0]} "./init-data/forms/example-1.ttl" "http://onto.fel.cvut.cz/ontologies/form/form-template"
""")
sys.exit(1)

def check_only_one_instance(results, rdf_type):
if len(results) == 0:
log(f"No instance found for the specified {rdf_type}.")
sys.exit(2)
elif len(results) > 1:
error_message = f"Multiple instances found for the type {rdf_type}. Triple that match pattern '?s a <{rdf_type}>' are:\n"
for row in results:
subject = row[0]
error_message += f" {subject.n3()} a <{rdf_type}> .\n"
log(error_message)
sys.exit(3)


def load_rdf_graph(file_path):
# Load RDF file into an RDFLib graph
g = Graph()

# Explicitly specify the format based on the file extension
if file_path.endswith(".ttl"):
g.parse(file_path, format="turtle")
elif file_path.endswith(".rdf"):
g.parse(file_path, format="xml")
else:
log(f"Unsupported RDF file format of {file_path}.")
sys.exit(1)

return g

def main():
check_params()

file_path = sys.argv[1]
rdf_type = URIRef(sys.argv[2])

g = load_rdf_graph(file_path)

# Query for subjects with the specified RDF type
query = f"""
SELECT ?subject
WHERE {{
?subject a <{rdf_type}>.
}}
"""

results = g.query(query)

check_only_one_instance(results, rdf_type)

for row in results:
subject = row[0]
print(subject.n3())

if __name__ == "__main__":
main()
Loading