Unverified Commit 5f2a443a authored by Philipp Berger's avatar Philipp Berger
Browse files

chore: release v1.9.0

parent c090fca3
......@@ -13,3 +13,4 @@
*.woff2 filter=lfs diff=lfs merge=lfs -text
## documents
*.pdf filter=lfs diff=lfs merge=lfs -text
*.luca filter=lfs diff=lfs merge=lfs -text
# Changelog
### 1.9.0 (2021-08-18)
* **backend:** fix: openAPI JSON
* **backend:** feat: send email to operator after approved location transfer
* **backend:** feat: add note to tracing proccess
* **backend:** feat: add rate limit for change operator email
* **backend:** feat: hash IP addresses in rate-limit redis
* **locations:** fix: area list not scrollable
* **locations:** fix: native tooltips for icons
* **locations:** fix: popconfirm texts for checkout guests
* **locations:** feat: notify that luca does not support IE
* **locations:** feat: add timestamp of answered data request to data requests view
* **locations:** feat: add tooltip for support code in help center
* **health-department:** fix: button alignment in track infection modal
* **health-department:** fix: native tooltips for icons
* **health-department:** feat: notify that luca does not support IE
* **health-department:** feat: improved wording in process details table
* **health-department:** feat: add help center
* **health-department:** feat: update design of private key modal
* **contact-form:** fix: possibility to enter a streetname with only numbers
* **contact-form:** fix: native tooltips for icons
* **scanner:** fix: native tooltips for icons
* **scanner:** fix: use correct camera depending on the used device
* **webapp:** fix: possibility to enter a streetname with only numbers
* **webapp:** fix: native tooltips for icons
* **webapp:** feat: extend check-in history to 28 days
* **webapp:** feat: remove Checkbox for privacy policy
### 1.8.1 (2021-08-13)
* **health-department:** fix: dependency resolution jszip
......
......@@ -128,6 +128,8 @@ Closure buildAndPushContainer(String service, String tag) {
usernameVariable: 'DOCKER_USERNAME',
passwordVariable: 'DOCKER_PASSWORD'),
string(credentialsId: 'luca-docker-registry', variable: 'DOCKER_REGISTRY'),
string(credentialsId: 'luca-hd-support-mail', variable: 'REACT_APP_SUPPORT_EMAIL'),
string(credentialsId: 'luca-hd-support-phone', variable: 'REACT_APP_SUPPORT_PHONE_NUMBER'),
usernamePassword( credentialsId: 'jenkins-docker-public-registry',
usernameVariable:'DOCKER_PUBLIC_USERNAME',
passwordVariable:'DOCKER_PUBLIC_PASSWORD'),
......
......@@ -4,6 +4,9 @@ services:
database:
volumes:
- ./local-data/postgres:/data/postgres
redis:
ports:
- "6379:6379"
elb:
volumes:
- ./services/elb/nginx.conf:/etc/nginx/nginx.conf
......
......@@ -33,9 +33,11 @@ services:
build:
context: "services/health-department"
args:
- NPM_CONFIG__AUTH
- GIT_VERSION
- GIT_COMMIT
- GIT_VERSION
- NPM_CONFIG__AUTH
- REACT_APP_SUPPORT_EMAIL
- REACT_APP_SUPPORT_PHONE_NUMBER
contact-form:
image: lucaapp/contact-form:${IMAGE_TAG}
build:
......@@ -79,7 +81,5 @@ services:
redis:
image: redis:6.0.9-alpine3.12
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
ports:
- "6379:6379"
volumes:
- ./services/redis/redis.conf:/usr/local/etc/redis/redis.conf
File added
{
"name": "e2e",
"version": "1.8.1",
"version": "1.9.0",
"main": "index.js",
"private": true,
"engines": {
......
import {
E2E_HEALTH_DEPARTMENT_USERNAME,
E2E_HEALTH_DEPARTMENT_PASSWORD,
} from '../../helper/user';
import { logout } from '../../helper/api/auth.helper';
import {
loginToHD,
openHDLoginPage,
uploadWrongHealthDepartmentPrivateKeyFileType,
uploadWrongHealthDepartmentPrivateKeyFile,
uploadWrongHealthDepartmentPrivateKeyFileTypeReUploadCorrectFile,
uploadHealthDepartmentPrivateKeyFileLargeSize,
} from '../../helper/ui/login.helper';
const appTracking = '/app/tracking';
const testSetup = () => {
openHDLoginPage();
loginToHD(E2E_HEALTH_DEPARTMENT_USERNAME, E2E_HEALTH_DEPARTMENT_PASSWORD);
cy.url().should('include', appTracking);
};
describe('Authentication', () => {
describe('Health Department / Authentication / Login / Private key upload', () => {
describe('When uploading a wrong key', () => {
describe('When Uploading private key file that is too large', () => {
it('A notification occours stating that the key is too large', () => {
testSetup();
uploadHealthDepartmentPrivateKeyFileLargeSize();
cy.get('.ant-notification-notice', { timeout: 10000 }).should(
'be.visible'
);
cy.get('.ant-modal').should('exist');
logout();
});
});
describe('When uploading a Private key that has the wrong key format', () => {
it('A notification occours stating that a wrong key file has been uploaded', () => {
testSetup();
uploadWrongHealthDepartmentPrivateKeyFileType();
cy.get('.ant-notification-notice', { timeout: 10000 }).should(
'be.visible'
);
cy.get('.ant-modal').should('exist');
logout();
});
});
describe('When uploading a wrong Private key', () => {
it('it will reject the private key file and a notification should occur stating that a wrong key has been uploaded', () => {
testSetup();
uploadWrongHealthDepartmentPrivateKeyFile();
cy.get('.ant-notification-notice', { timeout: 10000 }).should(
'be.visible'
);
cy.get('.ant-modal').should('exist');
logout();
});
});
});
describe('Try again key Re-upload', () => {
describe('When uploading a Wrong private key and afterwards re-upload a correct private key', () => {
it('it should reject the key upload and a notification should show stating that a wrong key has been uploaded, after that the correct private key is being uploaded and a notification occurs stating the the private key has been successfully uploaded as well the modal should close', () => {
testSetup();
uploadWrongHealthDepartmentPrivateKeyFileTypeReUploadCorrectFile();
cy.getByCy('header').within($header => {
cy.contains('Health-Department')
.should('exist')
.should('be.visible');
cy.get('.ant-dropdown-trigger')
.should('exist')
.should('be.enabled');
cy.get('button').contains('LOG OUT').should('exist');
});
cy.get('.ant-menu-horizontal').should('exist').should('be.visible');
cy.getByCy('navigation').should('exist').should('be.visible');
logout();
});
});
});
});
});
import { HEALTH_DEPARTMENT_PRIVATE_KEY_PATH } from '../user';
import {
HEALTH_DEPARTMENT_PRIVATE_KEY_PATH,
HEALTH_DEPARTMENT_WRONG_PRIVATE_KEY_PATH,
HEALTH_DEPARTMENT_WRONG_FILE_PRIVATE_KEY_PATH,
HEALTH_DEPARTMENT_LARGE_SIZE_FILE_PRIVATE_KEY_PATH,
} from '../user';
import { HEALTH_DEPARTMENT_BASE_ROUTE } from '../../helper/routes';
export const openHDLoginPage = () => {
......@@ -41,10 +46,70 @@ export const uploadHealthDepartmentPrivateKeyFile = () => {
});
};
export const uploadHealthDepartmentPrivateKeyFileLargeSize = () => {
cy.get('.ant-modal').should('exist');
cy.readFile(HEALTH_DEPARTMENT_LARGE_SIZE_FILE_PRIVATE_KEY_PATH).then(
fileContent => {
cy.get('input[type="file"]').attachFile({
fileContent,
fileName: 'HealthDepartmentLargeFile.luca',
mimeType: 'text/plain',
});
}
);
};
export const uploadWrongHealthDepartmentPrivateKeyFile = () => {
cy.get('.ant-modal').should('exist');
cy.readFile(HEALTH_DEPARTMENT_WRONG_PRIVATE_KEY_PATH).then(fileContent => {
cy.get('input[type="file"]').attachFile({
fileContent,
fileName: 'HealthDepartmentWrongKeyFile.luca',
mimeType: 'text/plain',
});
});
};
export const removeHealthDepartmentPrivateKeyFile = () => {
cy.task('deleteFileIfExists', HEALTH_DEPARTMENT_PRIVATE_KEY_PATH);
};
export const uploadWrongHealthDepartmentPrivateKeyFileType = () => {
cy.get('.ant-modal').should('exist');
cy.readFile(HEALTH_DEPARTMENT_WRONG_FILE_PRIVATE_KEY_PATH).then(
fileContent => {
cy.get('input[type="file"]').attachFile({
fileContent,
fileName: 'dummy.pdf',
mimeType: 'application/pdf',
});
}
);
};
export const uploadWrongHealthDepartmentPrivateKeyFileTypeReUploadCorrectFile = () => {
cy.get('.ant-modal').should('exist');
cy.readFile(HEALTH_DEPARTMENT_WRONG_PRIVATE_KEY_PATH).then(fileContent => {
cy.get('input[type="file"]').attachFile({
fileContent,
fileName: 'HealthDepartmentWrongKeyFile.luca',
mimeType: 'text/plain',
});
});
cy.get('.ant-notification-notice', { timeout: 10000 }).should('be.visible');
cy.get('.ant-modal').should('exist');
cy.getByCy('tryAgain', { timeout: 1000 }).should('exist');
cy.getByCy('tryAgain').click();
cy.readFile(HEALTH_DEPARTMENT_PRIVATE_KEY_PATH).then(fileContent => {
cy.get('input[type="file"]').attachFile({
fileContent,
fileName: 'HealthDepartmentKeyFile.luca',
mimeType: 'text/plain',
});
});
cy.get('.ant-modal', { timeout: 1000 }).should('not.exist');
};
export const addHealthDepartmentPrivateKeyFile = () => {
cy.task('fileExists', HEALTH_DEPARTMENT_PRIVATE_KEY_PATH).then(exists => {
if (!exists) {
......
export const E2E_HEALTH_DEPARTMENT_PASSWORD = 'testing';
export const E2E_HEALTH_DEPARTMENT_USERNAME = 'luca@nexenio.com';
export const HEALTH_DEPARTMENT_PRIVATE_KEY_PATH = './downloads/HealthDepartmentKeyFile.luca';
export const HEALTH_DEPARTMENT_PRIVATE_KEY_PATH =
'./downloads/HealthDepartmentKeyFile.luca';
export const HEALTH_DEPARTMENT_WRONG_PRIVATE_KEY_PATH =
'./assets/HealthDepartmentWrongKeyFile.luca';
export const HEALTH_DEPARTMENT_WRONG_FILE_PRIVATE_KEY_PATH =
'./assets/dummy.pdf';
export const HEALTH_DEPARTMENT_LARGE_SIZE_FILE_PRIVATE_KEY_PATH =
'./assets/HealthDepartmentLargeFile.luca';
......@@ -23,7 +23,6 @@ describe('WebApp / Register', () => {
cy.getByCy('ignoreWarning').click();
cy.getByCy('welcomeStep').should('exist');
cy.getByCy('termsConsCheckbox').click();
cy.getByCy('privacyCheckbox').click();
cy.getByCy('welcomeSubmit').click();
// Privacy step
cy.getByCy('dataContent').should('exist');
......
{
"name": "@lucaapp/web",
"version": "1.8.1",
"version": "1.9.0",
"private": true,
"license": "Apache-2.0",
"author": "Culture4Life <hello@luca-app.de> (https://www.luca-app.de/)",
......
......@@ -7,29 +7,28 @@ PFX_PASS="testing"
if [ -f "$CERTS_DIR/ca_root.pem" ]; then
echo "Root CA already exists."
exit
fi
mkdir -p $CERTS_DIR
else
mkdir -p $CERTS_DIR
# generate self-signed root ca
cfssl genkey -initca $CA_DIR/ca_root.json | cfssljson -bare $CERTS_DIR/ca_root
# generate self-signed root ca
cfssl genkey -initca $CA_DIR/ca_root.json | cfssljson -bare $CERTS_DIR/ca_root
# generate intermediate ca
cfssl genkey $CA_DIR/ca_basic.json | cfssljson -bare $CERTS_DIR/ca_basic
cfssl sign -config $CA_DIR/config.json -profile ca -ca $CERTS_DIR/ca_root.pem -ca-key $CERTS_DIR/ca_root-key.pem $CERTS_DIR/ca_basic.csr | cfssljson -bare $CERTS_DIR/ca_basic
# generate intermediate ca
cfssl genkey $CA_DIR/ca_basic.json | cfssljson -bare $CERTS_DIR/ca_basic
cfssl sign -config $CA_DIR/config.json -profile ca -ca $CERTS_DIR/ca_root.pem -ca-key $CERTS_DIR/ca_root-key.pem $CERTS_DIR/ca_basic.csr | cfssljson -bare $CERTS_DIR/ca_basic
# generate Health Department Certificate
cfssl genkey $CA_DIR/health.json | cfssljson -bare $CERTS_DIR/health
cfssl sign -config $CA_DIR/config.json -profile client -ca $CERTS_DIR/ca_basic.pem -ca-key $CERTS_DIR/ca_basic-key.pem $CERTS_DIR/health.csr | cfssljson -bare $CERTS_DIR/health
# generate Health Department Certificate
cfssl genkey $CA_DIR/health.json | cfssljson -bare $CERTS_DIR/health
cfssl sign -config $CA_DIR/config.json -profile client -ca $CERTS_DIR/ca_basic.pem -ca-key $CERTS_DIR/ca_basic-key.pem $CERTS_DIR/health.csr | cfssljson -bare $CERTS_DIR/health
# generate SSL Certificate
cfssl genkey $CA_DIR/ssl.json | cfssljson -bare $CERTS_DIR/ssl
cfssl sign -config $CA_DIR/config.json -profile server -ca $CERTS_DIR/ca_basic.pem -ca-key $CERTS_DIR/ca_basic-key.pem $CERTS_DIR/ssl.csr | cfssljson -bare $CERTS_DIR/ssl
# generate client certificates
openssl pkcs12 -export -inkey $CERTS_DIR/health-key.pem -in $CERTS_DIR/health.pem -name health -passout pass:$PFX_PASS -out $CERTS_DIR/health.pfx
# generate SSL Certificate
cfssl genkey $CA_DIR/ssl.json | cfssljson -bare $CERTS_DIR/ssl
cfssl sign -config $CA_DIR/config.json -profile server -ca $CERTS_DIR/ca_basic.pem -ca-key $CERTS_DIR/ca_basic-key.pem $CERTS_DIR/ssl.csr | cfssljson -bare $CERTS_DIR/ssl
# generate client certificates
openssl pkcs12 -export -inkey $CERTS_DIR/health-key.pem -in $CERTS_DIR/health.pem -name health -passout pass:$PFX_PASS -out $CERTS_DIR/health.pfx
fi
echo "Copying certs..."
# copy certificates to services
# nginx
cp $CERTS_DIR/ssl.pem services/elb/ssl/ssl.crt.pem
......
node_modules
.nyc_output
coverage
build
\ No newline at end of file
......@@ -22,6 +22,7 @@ node_modules/
# license and version information
licenses-full.txt
licenses.txt
version.json
# certificates
......
FROM node:14.17.3-alpine3.14
FROM node:14.17.3-alpine3.14 as builder
# set timezone
ENV TZ=Europe/Berlin
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /app
ENV NODE_ENV=production
# install dependencies
ARG NPM_CONFIG__AUTH
COPY package.json yarn.lock .npmrc .yarnrc ./
RUN yarn install --production --check-files && yarn cache clean
RUN mkdir -p ./build
RUN yarn licenses generate-disclaimer > ./licenses-full.txt
# copy source files
COPY tsconfig.json ./
COPY src/ ./src/
# build
ARG GIT_COMMIT
ARG GIT_VERSION
ENV NODE_ENV=production
RUN echo "{\"commit\":\"$GIT_COMMIT\", \"version\":\"$GIT_VERSION\"}" >> ./build/version.json
RUN yarn --silent licenses generate-disclaimer > licenses.txt
RUN yarn build
# install security patches
RUN apk --no-cache add musl=1.2.2-r3
FROM node:14.17.3-alpine3.14
WORKDIR /app
ENV NODE_ENV=production
# copy build
COPY --from=builder /app/node_modules /app/node_modules
COPY --from=builder /app/src /app/src
COPY --from=builder /app/build /app/build
COPY --from=builder /app/licenses.txt /app/licenses.txt
COPY --from=builder /app/version.json /app/version.json
# copy aux files
COPY .sequelizerc package.json ./
COPY config/ ./config/
COPY certs/ ./certs/
COPY tsconfig.json .sequelizerc ./
COPY config/ ./config/
COPY src/ ./src/
RUN yarn build
RUN yarn tsconfig-replace-paths --project tsconfig.json
# change user
RUN adduser -D worker
USER worker
# expose ports
EXPOSE 8080
CMD ["node", "build/src/index.js"]
FROM node:14.17.3-alpine3.14
WORKDIR /app
ARG GIT_COMMIT
ARG GIT_VERSION
ARG NPM_CONFIG__AUTH
# set timezone
ENV TZ=Europe/Berlin
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /app
ENV NODE_ENV=development
# install dependencies
ARG NPM_CONFIG__AUTH
COPY package.json tsconfig.json yarn.lock .npmrc .yarnrc ./
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
# copy source files
COPY .sequelizerc ./
COPY certs/ ./certs/
COPY config/ ./config/
COPY src/ ./src/
# change user
RUN adduser -D worker
USER worker
# expose ports
EXPOSE 8080
EXPOSE 9229
CMD ["yarn", "migrate-dev"]
Supports Markdown
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