Skip to content

Commit

Permalink
Merge branch 'release/1.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
dotFionn committed May 22, 2023
2 parents 60417b8 + e2a520a commit 77c35a0
Show file tree
Hide file tree
Showing 21 changed files with 248 additions and 80 deletions.
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vacdm-backend",
"version": "1.0.3",
"version": "1.1.0",
"description": "",
"main": "app.js",
"scripts": {
Expand Down
14 changes: 12 additions & 2 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import ecfmpService from './services/ecfmp.service';
logger.info('starting worker...');

setInterval(async () => {
logger.debug('running cleanup');
logger.debug('running pilot cleanup');
try {
await cdmService.cleanupPilots();
} catch (error) {
Expand All @@ -44,7 +44,17 @@ import ecfmpService from './services/ecfmp.service';
} catch (error) {
logger.error('error occurred getting ecfmp details');
}
}, 10000);
}, 60000);

setInterval(async () => {
logger.debug('running user cleanup');
try {
await cdmService.cleanupUsers();
} catch (error) {
logger.error('error occurred when cleaning up users', error);
}
}, 6 * 60 * 60 * 1000); /* 6h */
console.log(6 * 60 * 60 * 1000);

while (true) {
await (() => new Promise((res, rej) => setTimeout(res, 10000)))();
Expand Down
19 changes: 14 additions & 5 deletions backend/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
FrontendSettings,
PluginSettings,
} from '@shared/interfaces/config.interface';
import { FrontendSettings, PluginSettings } from '@shared/interfaces/config.interface';

interface vacdmConfig {
mongoUri: string;
Expand All @@ -14,6 +11,7 @@ interface vacdmConfig {
timeframes: {
timeSinceLastSeen: number;
timeSinceInactive: number;
timeSinceLastLogin: number;
};

eventUrl: string;
Expand All @@ -22,6 +20,9 @@ interface vacdmConfig {

clientId: string;
clientSecret: string;
vaccAuthType: string;
vaccAuthUrl: string;
vaccAuthToken: string;
publicUrl: string;
vatsimAuthUrl: string;
jwtSecret: string;
Expand All @@ -32,6 +33,8 @@ export default function config(): vacdmConfig {
serverName: process.env.SERVER_NAME ?? 'vACDM Server',
vatsimAuthUrl: process.env.VATSIM_AUTH_URL ?? 'https://auth.vatsim.net',
vatsimAuthClientId: process.env.CLIENT_ID ?? '',
vaccLogoUrl: process.env.VACC_LOGO_URL ?? '',
vaccImprintUrl: process.env.VACC_IMPRINT_URL ?? '',
};

return {
Expand All @@ -49,11 +52,14 @@ export default function config(): vacdmConfig {
serverName: options.serverName,
vatsimAuthUrl: options.vatsimAuthUrl,
vatsimAuthClientId: options.vatsimAuthClientId,
vaccLogoUrl: options.vaccLogoUrl,
vaccImprintUrl: options.vaccImprintUrl,
},

timeframes: {
timeSinceLastSeen: Number(process.env.TIME_LAST_SEEN || 5) * 60 * 1000,
timeSinceInactive: Number(process.env.TIME_INACTIVE || 5) * 60 * 1000
timeSinceInactive: Number(process.env.TIME_INACTIVE || 5) * 60 * 1000,
timeSinceLastLogin: Number(process.env.TIME_LAST_LOGIN || 48) * 60 * 60 * 1000,
},

eventUrl: process.env.EVENT_URL || 'https://slots.vatsim-germany.org/api/events/',
Expand All @@ -63,6 +69,9 @@ export default function config(): vacdmConfig {
vatsimAuthUrl: options.vatsimAuthUrl,
clientId: options.vatsimAuthClientId,
clientSecret: process.env.CLIENT_SECRET ?? '',
vaccAuthType: process.env.VACC_AUTH_TYPE ?? '',
vaccAuthUrl: process.env.VACC_AUTH_URL ?? '',
vaccAuthToken: process.env.VACC_AUTH_TOKEN ?? '',

publicUrl: process.env.PUBLIC_URL ?? '',
jwtSecret: process.env.JWT_SECRET ?? 'super-secret-secret!',
Expand Down
13 changes: 12 additions & 1 deletion backend/src/controllers/flow.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,18 @@ export async function getLegacyMeasures(
}
}

export async function editMeasure(req: Request, res: Response, next: NextFunction) {
try {
const measure = await ecfmpService.editMeasure(req.body);

res.json(measure);
} catch (error) {
next(error);
}
}

export default {
getAllMeasures,
getLegacyMeasures
getLegacyMeasures,
editMeasure,
};
12 changes: 7 additions & 5 deletions backend/src/models/measure.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import mongoose, { HydratedDocument, Schema } from 'mongoose';
import {EcfmpMeasure} from '@shared/interfaces/ecfmp.interface';
import { EcfmpMeasure } from '@shared/interfaces/ecfmp.interface';
import timeUtils from '../utils/time.utils';

export type EcfmpMeasureDocument = HydratedDocument<EcfmpMeasure>;
Expand All @@ -8,21 +8,23 @@ export const ecfmpMeasureSchema = new mongoose.Schema(
{
id: { type: Number, default: null },
ident: { type: String, required: true },
event_id: {type: Number, default: null},
event_id: { type: Number, default: null },
enabled: { type: Boolean, default: true },
reason: { type: String, default: '' },
starttime: { type: Date, default: timeUtils.emptyDate },
endtime: { type: Date, default: timeUtils.emptyDate },
withdrawn_at: { type: Date, default: timeUtils.emptyDate },
notified_flight_information_regions: [Number],
measure: {
type: { type: String, default: '' },
value: {type: Number, default: null},
value: { type: Number, default: null },
},
filters: [
{
type: { type: String, default: '' },
value: Schema.Types.Mixed
}]
value: Schema.Types.Mixed,
},
],
},
{ timestamps: true }
);
Expand Down
1 change: 1 addition & 0 deletions backend/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ router.patch('/pilots/:callsign', pilotController.updatePilot);
router.patch('/vdgs/:callsign', authMiddleware, pilotController.updatePilot);

router.get('/measures', flowController.getAllMeasures);
router.patch('/measures/:id', flowController.editMeasure);
router.get('/legacy-measures', flowController.getLegacyMeasures);

router.get('/airports', airportController.getAllAirports);
Expand Down
12 changes: 8 additions & 4 deletions backend/src/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import userModel, { UserDocument } from '../models/user.model';
import jwt from 'jsonwebtoken';
import nestedobjectsUtils from '../utils/nestedobjects.utils';
import config from '../config';
import { vaccAuth } from './vacc.service';

export async function authUser(code: string): Promise<string> {
let body = {
Expand All @@ -14,10 +15,7 @@ export async function authUser(code: string): Promise<string> {
};

try {
const tokenResponse = await axios.post(
config().vatsimAuthUrl + '/oauth/token',
body
);
const tokenResponse = await axios.post(config().vatsimAuthUrl + '/oauth/token', body);

const userResponse = await axios.get(config().vatsimAuthUrl + '/api/user', {
headers: {
Expand All @@ -36,8 +34,14 @@ export async function authUser(code: string): Promise<string> {
apidata: userFromApi,
access_token: tokenResponse.data.access_token,
refresh_token: tokenResponse?.data?.refresh_token ?? null,
vacdm: {},
};

// Auth user from VACC Auth URL
if (config().vaccAuthType !== undefined) {
updateOps.vacdm.atc = await vaccAuth({cid: userFromApi.cid});
}

if (userFromApi.oauth.token_valid != 'true') {
// do not save tokens if :wow: they aren't valid
updateOps.access_token = '';
Expand Down
19 changes: 19 additions & 0 deletions backend/src/services/cdm.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import pilotService from './pilot.service';
import bookingsService from './bookings.service';
import datafeedService from './datafeed.service';
import dayjs from 'dayjs';
import userModel from '../models/user.model';
const logger = new Logger('vACDM:services:cdm');

export function determineInitialBlock(pilot: PilotDocument): {
Expand Down Expand Up @@ -336,9 +337,27 @@ export async function optimizeBlockAssignments() {
}
}

export async function cleanupUsers() {
const usersToBeDeleted = await userModel
.find({
vacdm: {
admin: false,
atc: false,
banned: false,
},
updatedAt: {
$lte: new Date(Date.now() - config().timeframes.timeSinceLastLogin).getTime(),
},
})
.exec();

await Promise.allSettled(usersToBeDeleted.map(user => user.delete()));
}

export default {
determineInitialBlock,
putPilotIntoBlock,
cleanupPilots,
optimizeBlockAssignments,
cleanupUsers,
};
14 changes: 12 additions & 2 deletions backend/src/services/ecfmp.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ export async function allocateMeasuresToPilots() {
if (
dayjs(measure.starttime).isBefore(new Date(pilot.vacdm.ttot)) &&
dayjs(measure.endtime).isAfter(new Date(pilot.vacdm.ttot)) &&
(await isMeasureValidForPilot(pilot, measure))
(await isMeasureValidForPilot(pilot, measure)) &&
measure.enabled
) {
if (!pilot.measures.find((e) => e.ident === measure.ident)) {
pilot.measures.push({
Expand Down Expand Up @@ -210,4 +211,13 @@ export async function doesMeasureExist(ident: string): Promise<boolean> {
}
}

export default { getAllMeasures, getEcfmpDetails, allocateMeasuresToPilots };
export async function editMeasure(measureId: number, measure: EcfmpMeasureDocument) {
try {
const updatedMeasure = await ecfmpModel.findOneAndUpdate({ id: measureId }, { enabled: measure.enabled }, {new: true}).exec();
return updatedMeasure;
} catch (e) {
throw e;
}
}

export default { getAllMeasures, getEcfmpDetails, allocateMeasuresToPilots, editMeasure };
31 changes: 31 additions & 0 deletions backend/src/services/vacc.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import axios from 'axios';
import config from '../config';

type VaccAuthData = {
cid: string;
}

export async function vaccAuth(authData: VaccAuthData): Promise<boolean> {
switch (config().vaccAuthType) {
case 'URL':
return await vaccAuth_URL(authData.cid);
default:
return false;
}
}

export async function vaccAuth_URL(cid: string): Promise<boolean> {
try {
const vaccAuthResponse = await axios.get(config().vaccAuthUrl, {
headers: {
Authorization: 'Bearer ' + config().vaccAuthToken,
},
params: {
vatsimid: cid,
},
});
return vaccAuthResponse.status == 200;
} catch (err) {
return false;
}
}
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ services:
- CLIENT_SECRET
- PUBLIC_URL
- VATSIM_AUTH_URL
- VACC_AUTH_URL
- VACC_AUTH_TOKEN
- VACC_LOGO_URL
- VACC_IMPRINT_URL
- JWT_SECRET
- ALLOW_SIM=true
- ALLOW_OBS_MASTER=true
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cdm-frontend-react",
"version": "0.1.0",
"version": "1.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
Expand Down
24 changes: 24 additions & 0 deletions frontend/src/components/FlowManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EcfmpMeasure } from "@shared/interfaces/ecfmp.interface";
import { Card } from "primereact/card";
import { Column } from "primereact/column";
import { Checkbox } from "primereact/checkbox";
import { DataTable } from "primereact/datatable";
import { useEffect, useState } from "react";
import FlowService from "services/FlowService";
Expand Down Expand Up @@ -45,6 +46,24 @@ const FlowManagement = () => {
);
};

const enabledColumnTemplate = (rowData: EcfmpMeasure) => {
let checked = rowData.enabled;
return (
<Checkbox
checked={checked}
onChange={(e) => {
setMeasureEnabled(rowData, e.checked);
checked = e.checked;
}}
/>
);
};

const setMeasureEnabled = async (measure: EcfmpMeasure, checked: boolean) => {
const updatedMeasure = await FlowService.setMeasureEnable(measure.id, checked);
setMeasures((measures) => [...measures.filter((_measure) => _measure.id !== measure.id), updatedMeasure]);
};

return (
<Card>
<DataTable
Expand All @@ -54,6 +73,11 @@ const FlowManagement = () => {
loading={loading}
dataKey="id"
>
<Column
field="enabled"
header="Enabled"
body={enabledColumnTemplate}
/>
<Column field="ident" header="Measure ID" />
<Column
field="starttime"
Expand Down
21 changes: 11 additions & 10 deletions frontend/src/components/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,25 @@ const Login = () => {

const atcFooter = (
<span>
<Button
label='Login with VATSIM SSO'
className='p-button p-button-success'
onClick={redirectToVatsimAuth}
/>
<Button label="Login with VATSIM SSO" className="p-button p-button-success" onClick={redirectToVatsimAuth} />
</span>
);

return (
<>
<div className='flex justify-content-evenly flex-wrap'>
<div className='flex align-items-center justify-content-center'>
<div className="flex justify-content-evenly flex-wrap">
<div className="flex flex-column gap-3 align-items-center justify-content-center">
<Card
title='vACDM'
className='login-card text-center surface-200'
title="vACDM"
className="login-card text-center surface-200"
style={{ width: '25rem' }}
footer={atcFooter}
></Card>
/>
{config?.vaccImprintUrl && (
<a className="text-gray-500" href={config?.vaccImprintUrl}>
Imprint
</a>
)}
</div>
</div>
</>
Expand Down
Loading

0 comments on commit 77c35a0

Please sign in to comment.