Skip to content
Snippets Groups Projects
Commit d7222cf5 authored by Bernard Roland (Student Com20)'s avatar Bernard Roland (Student Com20)
Browse files

Merge branch 'devel' into frontend-devel

parents 74e6a1d2 0ac73f13
No related branches found
No related tags found
No related merge requests found
......@@ -17,6 +17,31 @@ facilitates effective collaboration.
## Getting Started
You can test out our web application at https://ryoko-planning.herokuapp.com/.
### Simple deployment
If you have [yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/) installed it is possible
to build and start the complete project the same way it is deployed on our server.
For this simply enter the root directory of the repository and execute the following three command in order:
1. `yarn install` (or `npm install`) This will install all the dependencies for both the frontend and backend
2. `yarn build` (or `npm run build`) This will bundle the source for the frontend and transpile backend
3. `yarn start` (or `npm run start`) This will start the web server and host the webserver at `localhost:8000`
Note:
* The server can use a public and private key pair to sign the authentication web token. They can
either be placed into the directory `server/keys/` with the name `cert.pem` (public key) and
`cert.key` (private key), or they can be given using the `JWT_PUBLIC_KEY` and `JWT_PRIVATE_KEY`
envirenvironment variables. In any case the keys must be suitable for ES384 signatures. If these
keys are not given it will use a simple password to sign the tokens.
* If your `PORT` environment variable is set that will be used as the port to host the webserver in stead of port 8000.
* If your `NODE_ENV` environment variable is set to `production` (with SSL) or `staging` (without SSL) the server will try
to connect to a postgres database using the connection url inside `DATABASE_URL` or
`postgresql://postgres@localhost/ryoko` if no such variable is present in the environment.
### Details
The source code for the repository is split into two parts. The backend code can be found inside the
`server` directory while the frontend code can be found inside the `client` directory. Both parts
are managed using the `yarn` package manager, but can also be used with `npm` if necessary. The
......@@ -24,19 +49,19 @@ server and client parts also use the same commands for running building and test
Before building or running you will have to make sure that you have installed all dependencies. This
can be done by executing `yarn install` (or `npm install --legacy-peer-deps`).
### How to Run
#### How to Run
To start a development server you can execute `yarn start` (or `npm run start`) inside the `server`
and the `client` directories. Most parts of the client will also require the server to be running
simultaneously.
### How to Build
#### How to Build
To build a production build enter the respective directory (either `server` or `client`) and execute
`yarn build` (or `npm run build`). The build output will be created inside a directory named `build`
and can then be executed using node for the server, or served staticaly for the client.
### How to Use
#### How to Use
After starting the development server inside `client`, the website is accessible at
`http://localhost:3000`. Depending on your configuration the site will probably be opened
......
......@@ -37,7 +37,7 @@ async function extendAccessToken() {
if (response.ok) {
const json = await response.json();
setToken(json.token);
} else if (response.status === 403) {
} else {
clearToken();
}
} catch(e) {
......
export const apiRoot = `${window.location.origin}/v1`;
export let apiRoot: string;
if (process.env.NODE_ENV === 'production') {
apiRoot = `${window.location.origin}/v1`;
} else {
apiRoot = `http://localhost:8000/v1`;
}
......@@ -8,12 +8,14 @@
"private": true,
"main": "server/build.js",
"scripts": {
"install": "cd server && yarn install --production=false && cd ../client && yarn install --production=false",
"install": "cd server && yarn install --production=false && cd ../client && yarn install --production=false",
"build": "cd server && yarn build && cd ../client && yarn build",
"start": "cd server && node build/index.js"
},
"keywords": [ ],
"dependencies": { },
"keywords": [],
"dependencies": {
"yarn": "^1.22.10"
},
"engines": {
"node": "16.x"
}
......
......@@ -6,6 +6,7 @@ export const port = env.PORT ?? 8000;
export const keys = {
private: './keys/cert.key',
public: './keys/cert.pem',
secret: 'SECRET',
};
export const allowedOrigins = [ "*" ];
......
......@@ -3,6 +3,25 @@ import { readFileBuffer } from './util';
import { env } from 'process';
import { keys } from './config';
let hasKeys: boolean | null = null;
export async function usePublicAndPrivate(): Promise<boolean> {
if (hasKeys === null) {
try {
await getPrivateKey();
await getPublicKey();
hasKeys = true;
} catch(e) {
hasKeys = false;
}
}
return hasKeys;
}
export function getSecret(): string {
return keys.secret;
}
let privateKey: string;
export async function getPrivateKey(): Promise<string> {
......
......@@ -3,7 +3,7 @@ import { env } from 'process';
import { join } from 'path';
import { parse } from 'pg-connection-string';
const pgconfig: any = parse(env.DATABASE_URL ?? '');
const pgconfig: any = parse(env.DATABASE_URL ?? 'postgresql://postgres@localhost/ryoko');
export default {
development: {
......
......@@ -6,7 +6,7 @@ import { sign, verify } from 'jsonwebtoken';
import database from '../database';
import { isOfType, asyncify } from '../util';
import { getPublicKey, getPrivateKey } from '../keys';
import { getPublicKey, getPrivateKey, getSecret, usePublicAndPrivate } from '../keys';
const auth = express();
......@@ -31,9 +31,21 @@ export async function tokenVerification(req: Request, _res: Response, next: Next
if (token) {
delete req.body.token;
try {
const decoded = await asyncify(verify, token, await getPublicKey(), { algorithms: ["ES384"] });
let decoded;
if (await usePublicAndPrivate()) {
decoded = await asyncify(verify, token, await getPublicKey(), { algorithms: ["ES384"] });
} else {
decoded = await asyncify(verify, token, getSecret(), { algorithms: ["HS384"] });
}
if (isOfType<Token>(decoded, [['id', 'string'], ['type', 'string']]) && decoded.type === authTokenType) {
req.body.token = decoded;
const user = await database('users')
.select({ id: 'users.id' })
.where({
'users.id': decoded.id,
});
if (user.length >= 1) {
req.body.token = decoded;
}
}
} catch (err) { /* Token has already been deleted */ }
next();
......@@ -58,7 +70,11 @@ async function generateAuthToken(id: string) {
id: id,
type: authTokenType,
};
return asyncify(sign, token, await getPrivateKey(), { algorithm: "ES384", expiresIn: 60 * 60 });
if (await usePublicAndPrivate()) {
return asyncify(sign, token, await getPrivateKey(), { algorithm: "ES384", expiresIn: 60 * 60 });
} else {
return asyncify(sign, token, getSecret(), { algorithm: "HS384", expiresIn: 60 * 60 });
}
}
interface RegisterBody {
......
......@@ -2,3 +2,7 @@
# yarn lockfile v1
yarn@^1.22.10:
version "1.22.10"
resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c"
integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA==
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment