Skip to content
This repository has been archived by the owner on Sep 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #9 from Dwigoric/Sprint-3
Browse files Browse the repository at this point in the history
Sprint 3
  • Loading branch information
riki-11 authored Nov 16, 2023
2 parents 434056d + 9c98706 commit 319f95c
Show file tree
Hide file tree
Showing 42 changed files with 2,749 additions and 980 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/deployment_azure-app-service.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Deploy Node.js express app to Azure Web App - compact-donuts

on:
push:
branches:
- main
- 'Sprint-[0-9]'
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

steps:
- uses: actions/checkout@v4

- name: Setup Node.js version
uses: actions/setup-node@v1
with:
node-version: '18.x'

- name: Install dependencies with yarn
run: |
echo 'Get latest yarn'
yarn set version stable
echo 'Install dependencies'
yarn install --immutable
- name: 'Deploy to Azure Web App'
uses: azure/webapps-deploy@v2
id: deploy-to-webapp
with:
app-name: 'unboundmnl-area-2-backend'
slot-name: 'Production'
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: .
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
"esbenp.prettier-vscode",
"arcanis.vscode-zipfs"
]
}
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
},
"eslint.nodePath": ".yarn/sdks",
"prettier.prettierPath": ".yarn/sdks/prettier/index.cjs",
"editor.formatOnSave": true
}
646 changes: 323 additions & 323 deletions .yarn/releases/yarn-4.0.0.cjs → .yarn/releases/yarn-4.0.1.cjs

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions .yarn/sdks/eslint/bin/eslint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint/bin/eslint.js
require(absPnpApiPath).setup();
}
}

// Defer to the real eslint/bin/eslint.js your application uses
module.exports = absRequire(`eslint/bin/eslint.js`);
20 changes: 20 additions & 0 deletions .yarn/sdks/eslint/lib/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint
require(absPnpApiPath).setup();
}
}

// Defer to the real eslint your application uses
module.exports = absRequire(`eslint`);
20 changes: 20 additions & 0 deletions .yarn/sdks/eslint/lib/unsupported-api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint/use-at-your-own-risk
require(absPnpApiPath).setup();
}
}

// Defer to the real eslint/use-at-your-own-risk your application uses
module.exports = absRequire(`eslint/use-at-your-own-risk`);
14 changes: 14 additions & 0 deletions .yarn/sdks/eslint/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "eslint",
"version": "8.53.0-sdk",
"main": "./lib/api.js",
"type": "commonjs",
"bin": {
"eslint": "./bin/eslint.js"
},
"exports": {
"./package.json": "./package.json",
".": "./lib/api.js",
"./use-at-your-own-risk": "./lib/unsupported-api.js"
}
}
5 changes: 5 additions & 0 deletions .yarn/sdks/integrations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# This file is automatically generated by @yarnpkg/sdks.
# Manual changes might be lost!

integrations:
- vscode
20 changes: 20 additions & 0 deletions .yarn/sdks/prettier/bin/prettier.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require prettier/bin/prettier.cjs
require(absPnpApiPath).setup();
}
}

// Defer to the real prettier/bin/prettier.cjs your application uses
module.exports = absRequire(`prettier/bin/prettier.cjs`);
20 changes: 20 additions & 0 deletions .yarn/sdks/prettier/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require prettier
require(absPnpApiPath).setup();
}
}

// Defer to the real prettier your application uses
module.exports = absRequire(`prettier`);
7 changes: 7 additions & 0 deletions .yarn/sdks/prettier/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "prettier",
"version": "3.0.3-sdk",
"main": "./index.cjs",
"type": "commonjs",
"bin": "./bin/prettier.cjs"
}
2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ enableGlobalCache: false

nodeLinker: pnp

yarnPath: .yarn/releases/yarn-4.0.0.cjs
yarnPath: .yarn/releases/yarn-4.0.1.cjs
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ The MongoDB URI to use for the application, defaults to `mongodb://localhost:270
### `JWT_SECRET`
The secret to use for JWT. This is required for the application to run.
If not set, the application will throw an error.
### `FRONTEND_URL`
The URL of the frontend application, defaults to `http://localhost:5173`.
### `FRONTEND_URLS`
The comma-separated list of URLs of the frontend application.
This is used for CORS.
If no value is set, the application will allow all origins.

## Private Files
Put any private files in the `private` directory.
Expand All @@ -47,3 +48,8 @@ yarn
```sh
yarn start
```

### Automatically Restart the Server on Changes
```sh
yarn watch
```
2 changes: 1 addition & 1 deletion example.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
MONGODB_URI=
JWT_SECRET=
FRONTEND_URL=
FRONTEND_URLS=
PORT=
22 changes: 12 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,31 @@
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node index.js"
"start": "node index.js",
"watch": "nodemon --watch src index.js"
},
"dependencies": {
"argon2": "0.30.3",
"cookie-parser": "~1.4.4",
"cookie-parser": "~1.4.6",
"cors": "^2.8.5",
"debug": "~2.6.9",
"debug": "~4.3.4",
"dotenv": "^16.3.1",
"express": "~4.16.1",
"express": "~4.18.2",
"http-errors": "^2.0.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^7.5.3",
"morgan": "~1.9.1",
"mongoose": "^8.0.0",
"morgan": "~1.10.0",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.5.1",
"eslint": "^8.50.0",
"eslint-plugin-import": "^2.28.1",
"prettier": "^3.0.3"
"eslint": "^8.53.0",
"eslint-plugin-import": "^2.29.0",
"nodemon": "^3.0.1",
"prettier": "^3.1.0"
},
"packageManager": "[email protected].0"
"packageManager": "[email protected].1"
}
26 changes: 13 additions & 13 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Default FRONTEND_URL

const DEFAULT_FRONTEND_URL = 'http://localhost:5173'

// Packages
import createError from 'http-errors'
import express from 'express'
Expand All @@ -22,18 +18,20 @@ await database.init().catch((err) => {
import indexRouter from './routes/index.js'
import usersRouter from './routes/users.js'
import authRouter from './routes/auth.js'
import officerRoute from './routes/officers.js'
import loanApplications from './routes/loan-applications.js'
import officerRouter from './routes/officers.js'
import loansRouter from './routes/loans.js'
import depositsRouter from './routes/deposits.js'
import settingsRouter from './routes/settings.js'

const app = express()

// Configure CORS
if (!process.env.FRONTEND_URL)
console.warn(`FRONTEND_URL not set, using default: ${DEFAULT_FRONTEND_URL}`)

const whitelist = []
if (!process.env.FRONTEND_URLS) console.warn('FRONTEND_URLS not set, allowing all origins')
else whitelist.push(...process.env.FRONTEND_URLS.split(','))
app.use(
cors({
origin: process.env.FRONTEND_URL || DEFAULT_FRONTEND_URL,
origin: whitelist.length === 0 ? true : whitelist,
optionsSuccessStatus: 200
})
)
Expand All @@ -47,7 +45,7 @@ if (!process.env.JWT_SECRET) {
process.exit(1)
}

logger.token('url', (req) => req.path)
logger.token('url', (req) => (req.baseUrl || '') + req.path)
app.use(logger('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
Expand All @@ -69,8 +67,10 @@ app.use('/private', express.static('private'))
app.use('/', indexRouter)
app.use('/users', usersRouter)
app.use('/auth', authRouter)
app.use('/officers', officerRoute)
app.use('/loan-applications', loanApplications)
app.use('/officers', officerRouter)
app.use('/loans', loansRouter)
app.use('/deposits', depositsRouter)
app.use('/settings', settingsRouter)

// Catch 404 and forward to error handler
app.use(function (req, res, next) {
Expand Down
6 changes: 3 additions & 3 deletions src/auth/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ passport.use(
* to use this strategy.
*/
passport.use(
'register-officer',
'admin',
new JwtStrategy(
{
jwtFromRequest: ExtractJwt.fromExtractors([
Expand All @@ -96,7 +96,7 @@ passport.use(
},
async function verify(payload, done) {
// Retrieve admin from request body's UUID
const admin = await Admin.findOne({ uuid: payload.uuid }).lean()
const admin = await Admin.findOne({ id: payload.uuid }).lean()

// Check if admin exists
if (!admin) {
Expand Down Expand Up @@ -129,7 +129,7 @@ passport.use(
async function verify(payload, done) {
try {
const manager = await (payload.type === 'admin' ? Admin : LoanOfficer)
.findOne({ uuid: payload.uuid })
.findOne({ id: payload.uuid })
.lean()

if (!manager) {
Expand Down
12 changes: 6 additions & 6 deletions src/models/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const Admin = model(
username: {
type: String,
unique: true,
required: [true, 'Username is required'],
immutable: true,
default: 'admin',
validate: {
validator: (username) => {
return username === 'admin'
Expand All @@ -21,10 +22,11 @@ const Admin = model(
type: String,
required: [true, 'Password is required']
},
uuid: {
id: {
type: String,
unique: true,
required: [true, 'UUID is required'],
immutable: true,
default: () => uuidV5('admin', uuidV5.URL),
validate: {
validator: (uuid) => uuidValidate(uuid) && uuidVersion(uuid) === 5,
message: 'UUID must be a valid UUID'
Expand All @@ -39,12 +41,10 @@ Admin.findOne({ username: 'admin' }, 'username')
.then(async (existing) => {
if (!existing) {
const password_hash = await argon2.hash('admin')
const uuid = uuidV5('admin', uuidV5.URL)

const admin = new Admin({
username: 'admin',
password_hash,
uuid
password_hash
})

admin.save()
Expand Down
Loading

0 comments on commit 319f95c

Please sign in to comment.