Unverified Commit 78f28b96 authored by Philipp Berger's avatar Philipp Berger
Browse files

chore: release v1.5.0

parent eec87764
_
\ No newline at end of file
_
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged
# Changelog
### 1.5.0 (2021-07-06)
* **backend:** feat: replace node-mailjet with axios
* **backend:** feat: move some error handling to cryto package
* **backend:** feat: add GTX SMS provider
* **backend** feat: add route to provide download url for signing tool
* **backend:** feat: return a different status code for expired SMS challenges
* **backend:** feat: moved traceId calculation to backend
* **backend:** feat: completely delete tracing processes after 28 days
* **backend:** ref: move json parse middleware into validateSchema middleware
* **backend:** chore: colorize and improve dev logging output
* **backend:** chore: publish traceIds for notifications when data was shared
* **health-department:** fix: add missing mac check
* **health-department** chore: add limit for private key file size
* **health-department:** feat: visualise signed public keys
* **health-department:** feat: set main font and remove duplicate definitions
* **locations:** fix: "forgot password" displaying incorrect error message for not activated users
* **locations:** fix: typos in registration email step
* **locations** fix: private key modal issue
* **locations** chore: add limit for private key file size
* **location** feat: redesign header
* **location** feat: checkin options for guests are directly accessible via location view
* **location** feat: provide link to checkin options via qr code
* **webapp:** chore: fix typos
* **webapp** feat: add gitlab link
* **webapp:** feat: validate that private meeting is not spoofing a location
* **webapp** feat: add a consent modal for data sharing with the health department
* security: update container base images and install security patches
* feat: add husky for git hooks
### 1.4.0 (2021-06-29)
* **backend:** feat: add test provider key route
* **backend:** feat: add isTrusted to Operators
......@@ -30,8 +60,11 @@
* **backend:** feat: add expireAt functionality to test redeems
* **contact-form:** fix: handle input starting with mutated vowels
* **contact-form:** feat: improved input validation
* **health-department:** fix: use secure-json-parse to prevent prototype pollution
* **health-department:** fix: replace react-csv with papaparse and improve csv output encoding
* **health-department:** fix: typo in error notification
* **health-department:** fix: status names in process table and filter were not identical
* **health-department:** feat: validate object schema directly after decryption and apply sanitization
* **health-department:** feat: new designs for process details
* **locations:** fix: input fields for manual input are disabled under certain conditions
* **locations:** fix: password not persisted after back action in registration
......
#!groovy
services = [
"backend",
"contact-form",
"health-department",
"locations",
"scanner",
"webapp",
'backend',
'contact-form',
'health-department',
'locations',
'scanner',
'webapp',
]
BRANCH_NAME = env.BRANCH_NAME
BUILD_NUMBER = env.BUILD_NUMBER
BRANCH_NAME_ESCAPED = BRANCH_NAME.replaceAll("/", "-")
BRANCH_NAME_ESCAPED = BRANCH_NAME.replaceAll('/', '-')
UNIQUE_TAG = "${BRANCH_NAME_ESCAPED}_build-${BUILD_NUMBER}"
node {
......@@ -32,19 +32,19 @@ node {
e2eTest()
}
if (env.BRANCH_NAME == "dev") {
if (env.BRANCH_NAME == 'dev') {
triggerDeploy('dev', GIT_VERSION)
}
if (env.BRANCH_NAME.startsWith("release/")) {
if (env.BRANCH_NAME.startsWith('release/')) {
triggerDeploy('release', GIT_VERSION)
}
if (env.BRANCH_NAME.startsWith("hotfix/")) {
if (env.BRANCH_NAME.startsWith('hotfix/')) {
triggerDeploy('hotfix', GIT_VERSION)
}
if (env.BRANCH_NAME == "master") {
if (env.BRANCH_NAME == 'master') {
triggerDeploy('preprod', GIT_VERSION)
}
......@@ -61,19 +61,19 @@ node {
}
void updateSourceCode() {
cleanWs()
checkout scm
// replace public registry references with private registries
withCredentials([
cleanWs()
checkout scm
// replace public registry references with private registries
withCredentials([
string(credentialsId: 'luca-docker-repository', variable: 'DOCKER_REPOSITORY'),
string(credentialsId: 'luca-npm-registry', variable: 'NPM_REGISTRY')
]) {
sh("./scripts/usePrivateRegistries.sh")
sh('./scripts/usePrivateRegistries.sh')
}
}
void abortPreviousRunningBuilds() {
echo "Aborting previous builds"
echo 'Aborting previous builds'
def jobname = env.JOB_NAME
def buildnum = env.BUILD_NUMBER.toInteger()
......@@ -86,7 +86,7 @@ void abortPreviousRunningBuilds() {
}
//check if the same number as currentBuild, if so skip
if (buildnum == build.getNumber().toInteger()) {
continue; println "equals"
continue; println 'equals'
}
echo "Aborting previous build = ${build}"
build.doStop()
......@@ -105,10 +105,10 @@ void triggerDeploy(String env, String image_tag) {
stage('Deploy') {
echo("deploying ${image_tag} to ${env}")
build(
job: "luca/luca-web-deploy",
job: 'luca/luca-web-deploy',
parameters: [
text(name: "ENV", value: env),
text(name: "IMAGE_TAG", value: image_tag)
text(name: 'ENV', value: env),
text(name: 'IMAGE_TAG', value: image_tag)
]
)
}
......@@ -116,21 +116,29 @@ void triggerDeploy(String env, String image_tag) {
Closure buildAndPushContainer(String service, String tag) {
return {
node("docker") {
node('docker') {
try {
updateSourceCode()
GIT_VERSION = sh(script: 'git describe --long --tags', returnStdout: true).trim()
GIT_COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
withCredentials([
usernamePassword(credentialsId: 'luca-docker-auth', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD'),
usernamePassword(credentialsId: 'luca-docker-auth',
usernameVariable: 'DOCKER_USERNAME',
passwordVariable: 'DOCKER_PASSWORD'),
string(credentialsId: 'luca-docker-registry', variable: 'DOCKER_REGISTRY'),
usernamePassword( credentialsId: 'jenkins-docker-public-registry',
usernameVariable:'DOCKER_PUBLIC_USERNAME',
passwordVariable:'DOCKER_PUBLIC_PASSWORD'),
string(credentialsId: 'luca-docker-public-registry', variable: 'DOCKER_PUBLIC_REGISTRY'),
string(credentialsId: 'luca-npm-auth', variable: 'NPM_CONFIG__AUTH'),
]) {
sh('docker login -u=$DOCKER_USERNAME -p=$DOCKER_PASSWORD $DOCKER_REGISTRY')
sh('docker login -u=$DOCKER_PUBLIC_USERNAME -p=$DOCKER_PUBLIC_PASSWORD $DOCKER_PUBLIC_REGISTRY')
sh("IMAGE_TAG=${tag} GIT_VERSION=${GIT_VERSION} GIT_COMMIT=${GIT_COMMIT} docker-compose -f docker-compose.yml build ${service}")
sh("IMAGE_TAG=${tag} docker-compose -f docker-compose.yml push ${service}")
sh("docker logout")
sh('docker logout')
}
} finally {
cleanWs()
......@@ -141,12 +149,17 @@ Closure buildAndPushContainer(String service, String tag) {
Closure executeTestScriptForService(String script, String service) {
return {
node("docker") {
node('docker') {
try {
updateSourceCode()
withCredentials([
usernamePassword( credentialsId: 'jenkins-docker-public-registry',
usernameVariable:'DOCKER_PUBLIC_USERNAME',
passwordVariable:'DOCKER_PUBLIC_PASSWORD'),
string(credentialsId: 'luca-docker-public-registry', variable: 'DOCKER_PUBLIC_REGISTRY'),
string(credentialsId: 'luca-npm-auth', variable: 'NPM_CONFIG__AUTH'),
]) {
sh('docker login -u=$DOCKER_PUBLIC_USERNAME -p=$DOCKER_PUBLIC_PASSWORD $DOCKER_PUBLIC_REGISTRY')
sh("IMAGE_TAG=test_${UNIQUE_TAG} docker-compose -f docker-compose.yml -f docker-compose.test.yml build ${service}")
sh("IMAGE_TAG=test_${UNIQUE_TAG} docker-compose -f docker-compose.yml -f docker-compose.test.yml run --rm ${service} ${script}")
}
......@@ -166,9 +179,14 @@ void e2eTest() {
withCredentials([
string(credentialsId: 'luca-npm-auth', variable: 'NPM_CONFIG__AUTH'),
string(credentialsId: 'luca-google-maps-api-key', variable: 'REACT_APP_GOOGLE_MAPS_API_KEY')
string(credentialsId: 'luca-google-maps-api-key', variable: 'REACT_APP_GOOGLE_MAPS_API_KEY'),
usernamePassword( credentialsId: 'jenkins-docker-public-registry',
usernameVariable:'DOCKER_PUBLIC_USERNAME',
passwordVariable:'DOCKER_PUBLIC_PASSWORD'),
string(credentialsId: 'luca-docker-public-registry', variable: 'DOCKER_PUBLIC_REGISTRY'),
]) {
sh("IMAGE_TAG=e2e docker-compose -f docker-compose.yml build --parallel")
sh('docker login -u=$DOCKER_PUBLIC_USERNAME -p=$DOCKER_PUBLIC_PASSWORD $DOCKER_PUBLIC_REGISTRY')
sh('IMAGE_TAG=e2e docker-compose -f docker-compose.yml build --parallel')
sh("IMAGE_TAG=e2e_${UNIQUE_TAG} docker-compose -f docker-compose.yml up -d database")
sh("IMAGE_TAG=e2e_${UNIQUE_TAG} docker-compose -f docker-compose.yml run backend yarn migrate")
sh("IMAGE_TAG=e2e_${UNIQUE_TAG} docker-compose -f docker-compose.yml run backend yarn seed")
......
......@@ -49,7 +49,7 @@ The services will be available on:
5.2 Cam - https://localhost/scanner/cam/`:locationScannerId`
6. luca Web App - https://localhost/webapp
We use https always. To not get annoyed by the browser warning of unsecure ssl certificate please trust the root.crt in the ca folder.
We always use https. Disable the browser's unsecure ssl certificate warning by trusting the root.crt in the ca folder.
Make sure to allocate enough Docker memory, the 2GB default might be insufficient to run all containers at once.
......
{
"name": "e2e",
"version": "1.4.0",
"version": "1.5.0",
"main": "index.js",
"private": true,
"engines": {
......
......@@ -11,6 +11,7 @@ const NONEXISTENT_EMAIL = 'non-existant-user@nexenio.com';
describe('Forgot password', () => {
beforeEach(() => cy.visit('/'));
afterEach(() => cy.wait(2000));
it('can send the reset password email and redirect the user back to the login page', () => {
enterEmail(E2E_EMAIL);
......
......@@ -13,7 +13,6 @@ describe('Start scanner', () => {
win.location.href = E2E_DEFAULT_CONTACT_FORM_LINK;
}).as('contactForm');
});
cy.getByCy('startScanner').click();
cy.getByCy('contactForm').click();
cy.get('@contactForm').should('be.called');
});
......@@ -23,7 +22,6 @@ describe('Start scanner', () => {
win.location.href = E2E_DEFAULT_SCANNER_LINK;
}).as('scanner');
});
cy.getByCy('startScanner').click();
cy.getByCy('scanner').click();
cy.get('@scanner').should('be.called');
});
......@@ -33,7 +31,6 @@ describe('Start scanner', () => {
win.location.href = E2E_DEFAULT_CAM_SCANNER_LINK;
}).as('camScanner');
});
cy.getByCy('startScanner').click();
cy.getByCy('camScanner').click();
cy.get('@camScanner').should('be.called');
});
......
......@@ -30,7 +30,10 @@ export const basicLocationLogin = (
origin: 'https://localhost',
},
});
cy.server();
cy.intercept({ method: 'GET', url: '**/me' }).as('me');
cy.visit(APP_ROUTE);
cy.wait('@me');
cy.window().then(window => {
window.sessionStorage.setItem('PRIVATE_KEY_MODAL_SEEN', 'true');
});
......
......@@ -85,7 +85,6 @@ describe('a deactivated account', () => {
cy.visit(APP_ROUTE);
cy.getByCy('locationDisplayName');
cy.getByCy('location-General');
cy.getByCy('startScanner');
});
});
});
......@@ -54,8 +54,6 @@ context('Workflow', () => {
// Checkin with contact form
cy.log('Checkin with in testing Location with Contact Form');
cy.getByCy('startScanner').click();
cy.get('.ant-modal').should('exist');
cy.window().then(win => {
cy.stub(win, 'open', link => {
win.location.href = link;
......
{
"name": "@lucaapp/web",
"version": "1.4.0",
"private": true,
"license": "Apache-2.0",
"author": "Culture4Life <hello@luca-app.de> (https://www.luca-app.de/)",
"scripts": {
"latest": ". ./scripts/getGITEnvironmentVariables.sh && docker-compose -f docker-compose.yml",
"prod": ". ./scripts/getGITEnvironmentVariables.sh && IMAGE_TAG=prod docker-compose -f docker-compose.yml",
"dev": ". ./scripts/getGITEnvironmentVariables.sh && IMAGE_TAG=dev docker-compose -f docker-compose.yml -f docker-compose.dev.yml",
"test": ". ./scripts/getGITEnvironmentVariables.sh && IMAGE_TAG=test docker-compose -f docker-compose.yml -f docker-compose.test.yml",
"all": ". ./scripts/yarnAll.sh"
}
"name": "@lucaapp/web",
"version": "1.5.0",
"private": true,
"license": "Apache-2.0",
"author": "Culture4Life <hello@luca-app.de> (https://www.luca-app.de/)",
"scripts": {
"latest": ". ./scripts/getGITEnvironmentVariables.sh && docker-compose -f docker-compose.yml",
"prod": ". ./scripts/getGITEnvironmentVariables.sh && IMAGE_TAG=prod docker-compose -f docker-compose.yml",
"dev": ". ./scripts/getGITEnvironmentVariables.sh && IMAGE_TAG=dev docker-compose -f docker-compose.yml -f docker-compose.dev.yml",
"test": ". ./scripts/getGITEnvironmentVariables.sh && IMAGE_TAG=test docker-compose -f docker-compose.yml -f docker-compose.test.yml",
"all": ". ./scripts/yarnAll.sh",
"prepare": "husky install",
"lint:backend": "npm run lint --prefix services/backend",
"lint:contact-form": "npm run lint --prefix services/contact-form",
"lint:health-department": "npm run lint --prefix services/health-department",
"lint:locations": "npm run lint --prefix services/locations",
"lint:scanner": "npm run lint --prefix services/scanner",
"lint:webapp": "npm run lint --prefix services/webapp"
},
"lint-staged": {
"services/backend/**/*.{js,jsx}": [
"npm run --silent lint:backend"
],
"services/contact-form/**/*.{js,jsx}": [
"npm run --silent lint:contact-form"
],
"services/health-department/**/*.{js,jsx}": [
"npm run --silent lint:health-department"
],
"services/locations/**/*.{js,jsx}": [
"npm run --silent lint:locations"
],
"services/scanner/**/*.{js,jsx}": [
"npm run --silent lint:scanner"
],
"services/webapp/**/*.{js,jsx}": [
"npm run --silent lint:webapp"
]
},
"devDependencies": {
"husky": "6.0.0",
"lint-staged": "11.0.0"
}
}
......@@ -51,6 +51,7 @@ overrides:
import/no-extraneous-dependencies: 0
unicorn/no-useless-undefined: 0
sonarjs/no-duplicate-string: 0
no-unused-expressions: 0
- files: ["*.test.js", "src/database/seeds/*.js"]
rules:
max-lines: 0
......
FROM node:14.17.0-alpine3.13
FROM node:14.17.1-alpine3.13
WORKDIR /app
ARG GIT_COMMIT
......@@ -11,6 +11,9 @@ RUN yarn install --production --check-files && yarn cache clean
RUN yarn licenses generate-disclaimer > ./licenses-full.txt
RUN echo "{\"commit\":\"$GIT_COMMIT\", \"version\":\"$GIT_VERSION\"}" >> version.json
# install security patches
RUN apk --no-cache add musl=1.2.2-r1
RUN adduser -D worker
USER worker
......
FROM node:14.17.0-alpine3.13
FROM node:14.17.1-alpine3.13
WORKDIR /app
ARG GIT_COMMIT
......
FROM node:14.17.0-alpine3.13
FROM node:14.17.1-alpine3.13
WORKDIR /app
ARG GIT_COMMIT
......
set -e
yarn lint
yarn test
yarn improved-yarn-audit --ignore-dev-deps
\ No newline at end of file
......@@ -21,10 +21,10 @@ module.exports = {
hostname: 'REDIS_HOSTNAME',
password: 'REDIS_PASSWORD',
},
mailjet: {
apiKey: 'MJ_APIKEY_PUBLIC',
secretKey: 'MJ_APIKEY_PRIVATE',
token: 'MJ_TOKEN',
mailer: {
apiUrl: 'MAILER_API_URL',
apiKey: 'MAILER_API_KEY',
apiSecret: 'MAILER_API_KEY_SECRET',
},
messagemobile: {
accessKey: 'MM_ACCESS_KEY',
......@@ -36,6 +36,10 @@ module.exports = {
gateway1: 'SINCH_GATEWAY1',
gateway2: 'SINCH_GATEWAY2',
},
gtx: {
authKey: 'GTX_AUTH_KEY',
gateway: 'GTX_GATEWAY',
},
keys: {
badge: {
targetKeyId: 'BADGE_TARGET_KEY_ID',
......
......@@ -27,10 +27,10 @@ module.exports = {
// DEV ONLY TOKEN
'ConqsCqWd]eaR82wv%C.iDdRybor8Ms2bM*h=m?V3@x2w^UxKA9pEjMjHn^y7?78',
},
mailjet: {
secretKey: '',
mailer: {
apiUrl: '',
apiKey: '',
token: '',
apiSecret: '',
},
messagemobile: {
accessKey: '',
......@@ -42,6 +42,10 @@ module.exports = {
gateway1: '',
gateway2: '',
},
gtx: {
authKey: '',
gateway: '',
},
luca: {
traces: {
maximumRequestablePeriod: moment.duration(24, 'hours').as('hours'),
......@@ -54,9 +58,6 @@ module.exports = {
userTransfers: {
maxAge: moment.duration(1, 'hours').as('hours'),
},
locationTransferTraces: {
maxAge: moment.duration(28, 'days').as('hours'),
},
locations: {
maxAge: moment.duration(28, 'days').as('hours'),
},
......@@ -68,6 +69,9 @@ module.exports = {
users: {
maxAge: moment.duration(28, 'days').as('hours'),
},
tracingProcess: {
maxAge: moment.duration(28, 'days').as('hours'),
},
testRedeems: {
defaultMaxAge: moment.duration(72, 'hours').as('hours'),
maxAge: moment.duration(1, 'years').as('hours'),
......@@ -76,6 +80,9 @@ module.exports = {
emails: {
expiry: moment.duration(24, 'hours').as('hours'),
},
sms: {
expiry: moment.duration(1, 'hours').as('hours'),
},
proxy: {
http: null,
https: null,
......
{
"name": "@lucaapp/backend",
"version": "1.4.0",
"version": "1.5.0",
"private": true,
"license": "Apache-2.0",
"author": "Culture4Life <hello@luca-app.de> (https://www.luca-app.de/)",
......@@ -22,8 +22,9 @@
"generate-version": "echo \"{\\\"commit\\\":\\\"$GIT_COMMIT\\\", \\\"version\\\":\\\"$GIT_VERSION\\\"}\" > version.json"
},
"dependencies": {
"@lucaapp/crypto": "2.0.1",
"@lucaapp/crypto": "2.0.3",
"axios": "0.21.1",
"colors": "1.4.0",
"config": "3.3.6",
"connect-session-sequelize": "7.1.1",
"cookie-parser": "1.4.5",
......@@ -47,7 +48,6 @@
"lodash": "4.17.21",
"moment": "2.29.1",
"node-forge": "0.10.0",
"node-mailjet": "3.3.1",
"nodemon": "2.0.7",
"passport": "0.4.1",
"passport-custom": "1.1.1",
......@@ -60,6 +60,7 @@
"sequelize-cli": "6.2.0",
"swagger-jsdoc": "6.1.0",
"swagger-ui-express": "4.1.6",
"triple-beam": "1.3.0",
"uuid": "8.3.2",
"winston": "3.3.3",
"xml2js": "0.4.23",
......@@ -82,7 +83,7 @@
"eslint-plugin-sonarjs": "0.6.0",
"eslint-plugin-unicorn": "28.0.2",
"improved-yarn-audit": "2.3.2",
"mocha": "8.3.2",
"mocha": "9.0.1",
"nyc": "15.1.0",
"prettier": "2.2.1",
"sinon": "9.2.4",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment