From 05eda8d33465732ffd9286fcb2a6d4c27c4be7fc Mon Sep 17 00:00:00 2001 From: Christoph Reiter <reiter.christoph@gmail.com> Date: Wed, 3 Feb 2021 11:38:48 +0100 Subject: [PATCH] showcase: port to app config --- toolkit-showcase/app.config.js | 22 +++ toolkit-showcase/assets/.htaccess.ejs | 6 +- toolkit-showcase/deploy.php | 18 +- toolkit-showcase/package.json | 13 +- toolkit-showcase/rollup.config.js | 227 +++++++++----------------- 5 files changed, 113 insertions(+), 173 deletions(-) create mode 100644 toolkit-showcase/app.config.js diff --git a/toolkit-showcase/app.config.js b/toolkit-showcase/app.config.js new file mode 100644 index 00000000..f9dfa2a8 --- /dev/null +++ b/toolkit-showcase/app.config.js @@ -0,0 +1,22 @@ +export default { + local: { + basePath: '/dist/', + entryPointURL: 'http://127.0.0.1:8000', + keyCloakBaseURL: 'https://auth-dev.tugraz.at/auth', + keyCloakClientId: 'auth-dev-mw-frontend-local', + matomoUrl: 'https://analytics.tugraz.at/', + matomoSiteId: 131, + nextcloudBaseURL: 'http://localhost:8081', + nextcloudName: 'TU Graz cloud', + }, + development: { + basePath: '/apps/checkin/', + entryPointURL: 'https://mw-dev.tugraz.at', + keyCloakBaseURL: 'https://auth-dev.tugraz.at/auth', + keyCloakClientId: 'demo-dev_tugraz_at-DEMO', + matomoUrl: 'https://analytics.tugraz.at/', + matomoSiteId: 131, + nextcloudBaseURL: 'https://nc-dev.tugraz.at/pers', + nextcloudName: 'TU Graz cloud', + }, +}; \ No newline at end of file diff --git a/toolkit-showcase/assets/.htaccess.ejs b/toolkit-showcase/assets/.htaccess.ejs index f2512eea..968bcc63 100644 --- a/toolkit-showcase/assets/.htaccess.ejs +++ b/toolkit-showcase/assets/.htaccess.ejs @@ -1,10 +1,10 @@ -DirectoryIndex <%= getUrl(name + '.html') %> +DirectoryIndex <%- getUrl(name + '.html') %> <FilesMatch "^(de|en|)$"> - FallbackResource <%= getUrl(name + '.html') %> + FallbackResource <%- getUrl(name + '.html') %> </FilesMatch> Header set Cache-Control "must-revalidate, max-age=60" -Header set Content-Security-Policy "default-src 'self' 'unsafe-eval' 'unsafe-inline' analytics.tugraz.at <%= keyCloakServer %> <%= entryPointURL %> httpbin.org <%= nextcloudBaseURL %> www.handy-signatur.at <%= pdfAsQualifiedlySigningServer %>; img-src * blob: data:" +Header set Content-Security-Policy "<%- CSP %>" # Apache adds a "-gzip" suffix to the etag when it uses gzip but doesn't # take that into account when receiving requests. diff --git a/toolkit-showcase/deploy.php b/toolkit-showcase/deploy.php index ab2a3619..e5d2e8d3 100644 --- a/toolkit-showcase/deploy.php +++ b/toolkit-showcase/deploy.php @@ -37,24 +37,16 @@ host('development') ->hostname('mw@mw01-dev.tugraz.at') ->set('deploy_path', '/home/mw/dev/deploy/apps/demo'); -// Demo build task -task('build-demo', function () { +task('build', function () { + $stage = get('stage'); runLocally("yarn install"); - runLocally("yarn run build-demo"); -})->onStage('demo'); - -// Demo dev task -task('build-development', function () { - runLocally("yarn install"); - runLocally("yarn run build-dev"); -})->onStage('development'); - + runLocally("APP_ENV=$stage yarn run build"); +}); // Deploy task task('deploy', [ 'deploy:info', - 'build-demo', - 'build-development', + 'build', 'deploy:prepare', 'deploy:lock', 'deploy:release', diff --git a/toolkit-showcase/package.json b/toolkit-showcase/package.json index 30bbfeeb..73e58e57 100644 --- a/toolkit-showcase/package.json +++ b/toolkit-showcase/package.json @@ -5,7 +5,8 @@ "license": "LGPL-2.1-or-later", "private": true, "workspaces": [ - "../packages/*" + "../packages/*", + "." ], "devDependencies": { "@babel/core": "^7.10.3", @@ -18,7 +19,6 @@ "@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^11.0.0", - "@rollup/plugin-replace": "^2.3.3", "@rollup/plugin-url": "^6.0.0", "babel-eslint": "^10.0.3", "chai": "^4.2.0", @@ -67,15 +67,14 @@ "webdav": "^3.3.0" }, "scripts": { - "build-dev": "rollup -c --environment BUILD:development", - "build-prod": "rollup -c --environment BUILD:production", - "build-demo": "rollup -c --environment BUILD:demo", + "build": "rollup -c", "i18next": "i18next-scanner", "watch": "rollup -c --watch", "watch-local": "yarn run watch", "watch-full": "rollup -c --watch --environment FORCE_FULL", - "test": "rollup -c --environment BUILD:test && karma start --singleRun", - "test-full": "rollup -c --environment FORCE_FULL,BUILD:test && karma start --singleRun", + "watch-bs": "rollup -c --watch --environment APP_ENV:bs", + "test": "rollup -c --environment APP_ENV:test && karma start --singleRun", + "test-full": "rollup -c --environment FORCE_FULL,APP_ENV:test && karma start --singleRun", "lint": "eslint ." } } diff --git a/toolkit-showcase/rollup.config.js b/toolkit-showcase/rollup.config.js index 5004c26f..a232dcd3 100644 --- a/toolkit-showcase/rollup.config.js +++ b/toolkit-showcase/rollup.config.js @@ -6,7 +6,6 @@ import commonjs from '@rollup/plugin-commonjs'; import copy from 'rollup-plugin-copy'; import {terser} from "rollup-plugin-terser"; import json from '@rollup/plugin-json'; -import replace from "@rollup/plugin-replace"; import serve from 'rollup-plugin-serve'; import urlPlugin from "@rollup/plugin-url"; import license from 'rollup-plugin-license'; @@ -14,126 +13,65 @@ import del from 'rollup-plugin-delete'; import md from 'rollup-plugin-md'; import emitEJS from 'rollup-plugin-emit-ejs' import babel from '@rollup/plugin-babel' -import {generateTLSConfig} from '../rollup.utils.js'; - -// ------------------------------- - -// Some new web APIs are only available when HTTPS is active. -// Note that this only works with a Non-HTTPS API endpoint with Chrome, -// Firefox will emit CORS errors, see https://bugzilla.mozilla.org/show_bug.cgi?id=1488740 -const USE_HTTPS = true; - -// ------------------------------- +import appConfig from './app.config.js'; +import {generateTLSConfig, getBuildInfo, getPackagePath, getDistPath} from '../rollup.utils.js'; const pkg = require('./package.json'); -const build = (typeof process.env.BUILD !== 'undefined') ? process.env.BUILD : 'local'; +const appEnv = (typeof process.env.APP_ENV !== 'undefined') ? process.env.APP_ENV : 'local'; const watch = process.env.ROLLUP_WATCH === 'true'; -const buildFull = (!watch && build !== 'test') || (process.env.FORCE_FULL !== undefined); - -console.log("build: " + build); -let basePath = ''; -let entryPointURL = ''; -let nextcloudBaseURL = 'https://cloud.tugraz.at'; -let nextcloudWebAppPasswordURL = nextcloudBaseURL + '/apps/webapppassword'; -let nextcloudWebDavURL = nextcloudBaseURL + '/remote.php/dav/files'; -let nextcloudName = 'TU Graz cloud'; -let keyCloakServer = ''; -let keyCloakBaseURL = ''; -let keyCloakClientId = ''; -let pdfAsQualifiedlySigningServer = ''; -const matomoUrl = "https://analytics.tugraz.at/"; -const matomoSiteId = 131; +const buildFull = (!watch && appEnv !== 'test') || (process.env.FORCE_FULL !== undefined); let useTerser = buildFull; let useBabel = buildFull; let checkLicenses = buildFull; +let useHTTPS = true; -switch (build) { - case 'local': - basePath = '/dist/'; - entryPointURL = 'http://127.0.0.1:8000'; - nextcloudBaseURL = 'http://localhost:8081'; - nextcloudWebAppPasswordURL = nextcloudBaseURL + '/index.php/apps/webapppassword'; - nextcloudWebDavURL = nextcloudBaseURL + '/remote.php/dav/files'; - keyCloakServer = 'auth-dev.tugraz.at'; - keyCloakBaseURL = 'https://' + keyCloakServer + '/auth'; - keyCloakClientId = 'auth-dev-mw-frontend-local'; - pdfAsQualifiedlySigningServer = 'sig-dev.tugraz.at'; - break; - case 'development': - basePath = '/apps/demo/'; - entryPointURL = 'https://mw-dev.tugraz.at'; - // "/pers" can't go here because it's not allowed in the "Content-Security-Policy" - nextcloudBaseURL = 'https://nc-dev.tugraz.at'; - // "/index.php" is needed to don't get a "This origin is not allowed!" because the "target-origin" get parameter can't be read - nextcloudWebAppPasswordURL = nextcloudBaseURL + '/pers/index.php/apps/webapppassword'; - nextcloudWebDavURL = nextcloudBaseURL + '/pers/remote.php/dav/files'; - keyCloakServer = 'auth-dev.tugraz.at'; - keyCloakBaseURL = 'https://' + keyCloakServer + '/auth'; - keyCloakClientId = 'demo-dev_tugraz_at-DEMO'; - pdfAsQualifiedlySigningServer = 'sig-dev.tugraz.at'; - break; - case 'demo': - basePath = '/apps/demo/'; - entryPointURL = 'https://api-demo.tugraz.at'; - // "/pers" can't go here because it's not allowed in the "Content-Security-Policy" - nextcloudBaseURL = 'https://nc-dev.tugraz.at'; - // "/index.php" is needed to don't get a "This origin is not allowed!" because the "target-origin" get parameter can't be read - nextcloudWebAppPasswordURL = nextcloudBaseURL + '/pers/index.php/apps/webapppassword'; - nextcloudWebDavURL = nextcloudBaseURL + '/pers/remote.php/dav/files'; - keyCloakServer = 'auth-test.tugraz.at'; - keyCloakBaseURL = 'https://' + keyCloakServer + '/auth'; - keyCloakClientId = 'auth-dev-mw-frontend'; - pdfAsQualifiedlySigningServer = 'sig-dev.tugraz.at'; - break; +console.log("APP_ENV: " + appEnv); - default: - console.error('Unknown build environment: ' + build); +let config; +if (appEnv in appConfig) { + config = appConfig[appEnv]; +} else if (appEnv === 'test') { + config = { + basePath: '/', + entryPointURL: 'https://test', + keyCloakBaseURL: 'https://test', + keyCloakClientId: '', + matomoUrl: '', + matomoSiteId: -1, + nextcloudBaseURL: 'https://test', + nextcloudName: '', + }; +} else { + console.error(`Unknown build environment: '${appEnv}', use one of '${Object.keys(appConfig)}'`); process.exit(1); } -let nextcloudFileURL = nextcloudBaseURL + '/apps/files/?dir='; +if (config.nextcloudBaseURL) { + config.nextcloudFileURL = config.nextcloudBaseURL + '/index.php/apps/files/?dir='; + config.nextcloudWebAppPasswordURL = config.nextcloudBaseURL + '/index.php/apps/webapppassword'; + config.nextcloudWebDavURL = config.nextcloudBaseURL + '/remote.php/dav/files'; +} else { + config.nextcloudFileURL = ''; + config.nextcloudWebAppPasswordURL = ''; + config.nextcloudWebDavURL = ''; +} -function getBuildInfo() { - const child_process = require('child_process'); - const url = require('url'); +function getOrigin(url) { + if (url) + return new URL(url).origin; + return ''; +} - let remote = child_process.execSync('git config --get remote.origin.url').toString().trim(); - let commit = child_process.execSync('git rev-parse --short HEAD').toString().trim(); +config.CSP = `default-src 'self' 'unsafe-eval' 'unsafe-inline' \ +${getOrigin(config.matomoUrl)} ${getOrigin(config.keyCloakBaseURL)} ${getOrigin(config.entryPointURL)} \ +httpbin.org ${getOrigin(config.nextcloudBaseURL)}; \ +img-src * blob: data:`; - let parsed = url.parse(remote); - // convert git urls - if (parsed.protocol === null) { - parsed = url.parse('git://' + remote.replace(":", "/")); - parsed.protocol = 'https:'; - } - let newPath = parsed.path.slice(0, parsed.path.lastIndexOf('.')); - let newUrl = parsed.protocol + '//' + parsed.host + newPath + '/commit/' + commit; +export default (async () => { + let privatePath = await getDistPath(pkg.name) return { - info: commit, - url: newUrl, - time: new Date().toISOString(), - env: build - } -} - -export async function getPackagePath(packageName, assetPath) { - const r = resolve(); - const resolved = await r.resolveId(packageName); - let packageRoot; - if (resolved !== null) { - const id = (await r.resolveId(packageName)).id; - const packageInfo = r.getPackageInfoForId(id); - packageRoot = packageInfo.root; - } else { - // Non JS packages - packageRoot = path.dirname(require.resolve(packageName + '/package.json')); - } - return path.relative(process.cwd(), path.join(packageRoot, assetPath)); -} - -export default (async () => {return { - input: (build != 'test') ? glob.sync('src/*.js') : glob.sync('test/**/*.js'), + input: (appEnv != 'test') ? glob.sync('src/dbp-*.js') : glob.sync('test/**/*.js'), output: { dir: 'dist', entryFileNames: '[name].js', @@ -154,11 +92,6 @@ export default (async () => {return { } warn(warning); }, - watch: { - chokidar: { - usePolling: true - } - }, plugins: [ del({ targets: 'dist/*' @@ -168,26 +101,24 @@ export default (async () => {return { include: ['**/*.ejs', '**/.*.ejs'], data: { getUrl: (p) => { - return url.resolve(basePath, p); + return url.resolve(config.basePath, p); }, getPrivateUrl: (p) => { - return url.resolve(`${basePath}local/${pkg.name}/`, p); + return url.resolve(`${config.basePath}${privatePath}/`, p); }, name: pkg.name, - entryPointURL: entryPointURL, - nextcloudBaseURL: nextcloudBaseURL, - nextcloudWebAppPasswordURL: nextcloudWebAppPasswordURL, - nextcloudWebDavURL: nextcloudWebDavURL, - nextcloudFileURL: nextcloudFileURL, - nextcloudName: nextcloudName, - keyCloakServer: keyCloakServer, - keyCloakBaseURL: keyCloakBaseURL, - keyCloakClientId: keyCloakClientId, - pdfAsQualifiedlySigningServer: pdfAsQualifiedlySigningServer, - environment: build, - matomoUrl: matomoUrl, - matomoSiteId: matomoSiteId, - buildInfo: getBuildInfo() + entryPointURL: config.entryPointURL, + nextcloudBaseURL: config.nextcloudBaseURL, + nextcloudWebAppPasswordURL: config.nextcloudWebAppPasswordURL, + nextcloudWebDavURL: config.nextcloudWebDavURL, + nextcloudFileURL: config.nextcloudFileURL, + nextcloudName: config.nextcloudName, + keyCloakBaseURL: config.keyCloakBaseURL, + keyCloakClientId: config.keyCloakClientId, + CSP: config.CSP, + matomoUrl: config.matomoUrl, + matomoSiteId: config.matomoSiteId, + buildInfo: getBuildInfo(appEnv) } }), resolve({ @@ -234,34 +165,30 @@ Dependencies: emitFiles: true, fileName: 'shared/[name].[hash][extname]' }), - replace({ - "process.env.BUILD": '"' + build + '"', - }), useTerser ? terser() : false, copy({ targets: [ - {src: 'assets/silent-check-sso.html', dest:'dist'}, + {src: 'assets/*.css', dest: 'dist/' + await getDistPath(pkg.name)}, + {src: 'assets/*.ico', dest: 'dist/' + await getDistPath(pkg.name)}, + {src: 'assets/*.metadata.json', dest: 'dist'}, + {src: 'assets/*.svg', dest: 'dist/' + await getDistPath(pkg.name)}, {src: 'assets/htaccess-shared', dest: 'dist/shared/', rename: '.htaccess'}, - {src: 'assets/*.css', dest: 'dist/local/' + pkg.name}, - {src: 'assets/*.ico', dest: 'dist/local/' + pkg.name}, - {src: 'assets/*.svg', dest: 'dist/local/' + pkg.name}, + {src: 'assets/icon-*.png', dest: 'dist/' + await getDistPath(pkg.name)}, + {src: 'assets/manifest.json', dest: 'dist', rename: pkg.name + '.manifest.json'}, + {src: 'assets/silent-check-sso.html', dest:'dist'}, { - src: 'node_modules/pdfjs-dist/build/pdf.worker.min.js', - dest: 'dist/local/' + pkg.name + '/pdfjs', + src: await getPackagePath('pdfjs-dist', 'es5/build/pdf.worker.js'), + dest: 'dist/' + await getDistPath(pkg.name, 'pdfjs'), // enable signatures in pdf preview - transform: (contents) => contents.toString().replace('if("Sig"===a.fieldType){a.fieldValue=null;this.setFlags(r.AnnotationFlag.HIDDEN)}', '') + transform: (contents) => contents.toString().replace('"Sig"', '"Sig-patched-show-anyway"') }, - {src: 'node_modules/pdfjs-dist/cmaps/*', dest: 'dist/local/' + pkg.name + '/pdfjs'}, // do we want all map files? - {src: await getPackagePath('@dbp-toolkit/font-source-sans-pro', 'files/*'), dest: 'dist/local/' + pkg.name + '/fonts/source-sans-pro'}, - {src: 'node_modules/@dbp-toolkit/common/src/spinner.js', dest: 'dist/local/' + pkg.name, rename: 'spinner.js'}, - {src: 'node_modules/@dbp-toolkit/common/misc/browser-check.js', dest: 'dist/local/' + pkg.name, rename: 'browser-check.js'}, - {src: 'assets/icon-*.png', dest: 'dist/local/' + pkg.name}, - {src: 'assets/*-placeholder.png', dest: 'dist/local/' + pkg.name}, - {src: 'assets/manifest.json', dest: 'dist', rename: pkg.name + '.manifest.json'}, - {src: 'assets/*.metadata.json', dest: 'dist'}, - {src: 'node_modules/@dbp-toolkit/common/assets/icons/*.svg', dest: 'dist/local/@dbp-toolkit/common/icons'}, - {src: 'node_modules/tabulator-tables/dist/css', dest: 'dist/local/@dbp-toolkit/file-handling/tabulator-tables'}, - {src: 'node_modules/qr-scanner/qr-scanner-worker.*', dest: 'dist/local/qr-code-scanner'}, + {src: await getPackagePath('pdfjs-dist', 'cmaps/*'), dest: 'dist/' + await getDistPath(pkg.name, 'pdfjs')}, // do we want all map files? + {src: await getPackagePath('@dbp-toolkit/font-source-sans-pro', 'files/*'), dest: 'dist/' + await getDistPath(pkg.name, 'fonts/source-sans-pro')}, + {src: await getPackagePath('@dbp-toolkit/common', 'src/spinner.js'), dest: 'dist/' + await getDistPath(pkg.name)}, + {src: await getPackagePath('@dbp-toolkit/common', 'misc/browser-check.js'), dest: 'dist/' + await getDistPath(pkg.name)}, + {src: await getPackagePath('@dbp-toolkit/common', 'assets/icons/*.svg'), dest: 'dist/' + await getDistPath('@dbp-toolkit/common', 'icons')}, + {src: await getPackagePath('tabulator-tables', 'dist/css'), dest: 'dist/' + await getDistPath('@dbp-toolkit/file-handling', 'tabulator-tables')}, + {src: await getPackagePath('qr-scanner', 'qr-scanner-worker.*'), dest: 'dist/' + await getDistPath('@dbp-toolkit/qr-code-scanner')}, ], }), useBabel && babel({ @@ -293,10 +220,10 @@ Dependencies: contentBase: '.', host: '127.0.0.1', port: 8001, - historyApiFallback: basePath + pkg.name + '.html', - https: USE_HTTPS ? await generateTLSConfig() : false, + historyApiFallback: config.basePath + pkg.name + '.html', + https: useHTTPS ? await generateTLSConfig() : false, headers: { - 'Content-Security-Policy': `default-src 'self' 'unsafe-eval' 'unsafe-inline' analytics.tugraz.at ${keyCloakServer} ${entryPointURL} httpbin.org ${nextcloudBaseURL} www.handy-signatur.at ${pdfAsQualifiedlySigningServer} ; img-src * blob: data:` + 'Content-Security-Policy': config.CSP }, }) : false ] -- GitLab