Skip to content

Commit

Permalink
implemented query filtering for pilots
Browse files Browse the repository at this point in the history
  • Loading branch information
dotFionn committed Mar 23, 2024
1 parent 701ad17 commit 38d2176
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 3 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ RUN apk update && \
# apk add --no-cache git && \

COPY --chown=node:node package*.json ./
COPY --chown=node:node assets ./assets

USER node

Expand Down
38 changes: 38 additions & 0 deletions assets/filter.peggy
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Filter
= ComparingFilter / CombiningFilter

Filters
= f:Filter _ fs:Filters {return [f, ...fs]}
/ f:Filter {return [f]}


CombiningFilter
= "(" comb:Combinator _ filters:Filters ")" {return {[comb]: filters}}

ComparingFilter
= "(" _ field:Field _ comp:Comparator _ value:String _ ")" {return {[field]: {[comp]: value}}}

Field =
s:String {
switch(s) {
default: return s; // PLACEHOLDER_REPLACE_THIS_LINE
}
}

String "string"
= s:[a-zA-Z0-9]+ {return s.join('')}

Comparator "comparator"
= "<=" {return "$lte"}
/ ">=" {return "$gte"}
/ "!=" {return "$neq"}
/ "=" {return "$eq"}
/ ">" {return "$gt"}
/ "<" {return "$lt"}

Combinator "combinator"
= "|" {return "$or"}
/ "&" {return "$and"}

_ "whitespace"
= [ \t\n\r]*
74 changes: 74 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"ms": "2.1.3",
"nest-winston": "1.9.4",
"nestjs-joi": "1.10.0",
"peggy": "4.0.2",
"point-in-polygon": "^1.1.0",
"winston": "3.11.0"
},
Expand Down
19 changes: 16 additions & 3 deletions src/backend/pilot/pilot.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';
import { BadRequestException, Body, Controller, Delete, Get, Param, Patch, Post, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { JoiPipe } from 'nestjs-joi';

import logger from '../logger';

import { PilotDto, PilotCallsignValidator } from './pilot.dto';
import { PilotService } from './pilot.service';

Expand All @@ -15,8 +17,19 @@ export class PilotController {
) {}

@Get('/')
async getAllPilots() {
const pilots = await this.pilotService.getAllPilots();
async getAllPilots(@Query('filter') filter = '') {
let parsedFilter = {};

if (filter) {
try {
parsedFilter = this.pilotService.processFilter(filter);
} catch (error) {
throw new BadRequestException(error.message);
}
logger.debug('filter: %s - parsedFilter: %o', filter, parsedFilter);
}

const pilots = await this.pilotService.getPilots(parsedFilter);

return {
count: pilots.length,
Expand Down
12 changes: 12 additions & 0 deletions src/backend/pilot/pilot.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ConflictException, Inject, Injectable, NotFoundException, forwardRef } from '@nestjs/common';
import Agenda from 'agenda';
import { FilterQuery } from 'mongoose';
import { Parser } from 'peggy';

import { AirportService } from '../airport/airport.service';
import { CdmService } from '../cdm/cdm.service';
Expand All @@ -25,6 +26,17 @@ export class PilotService {
) {
this.agenda.define('PILOT_cleanupPilots', this.cleanupPilots.bind(this));
this.agenda.every('10 minutes', 'PILOT_cleanupPilots');

this.parser = this.utilsService.generateFilter({
adep: 'flightplan.adep',
ades: 'flightplan.ades',
}, true);
}

private parser: Parser;

processFilter(filter: string): FilterQuery<Pilot> {
return this.parser.parse(filter);
}

getPilots(filter: FilterQuery<Pilot>): Promise<PilotDocument[]> {
Expand Down
48 changes: 48 additions & 0 deletions src/backend/utils/utils.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import crypto from 'node:crypto';
import fs from 'node:fs';

import { Injectable } from '@nestjs/common';
import peggy, { Parser } from 'peggy';

import logger from '../logger';

Expand Down Expand Up @@ -113,4 +115,50 @@ export class UtilsService {
generateRandomBytes(length = 32, encoding: BufferEncoding = 'base64') {
return crypto.randomBytes(length).toString(encoding);
}

generateFilter(fieldMapping = {}, disallowUndefinedFieldNames = false): Parser {
const baseFilter = fs.readFileSync('assets/filter.peggy', { encoding: 'utf8' });

if (Object.values(fieldMapping).length == 0 && disallowUndefinedFieldNames) {
return peggy.generate(baseFilter);
}

const lines = baseFilter.replace(/\r\n/gm, '\n').split('\n');
let line = -1;
let prefix = '';

// find line to replace
for (let i = 0; i < lines.length; i++) {
const lstring = lines[i];
if (lstring.includes('PLACEHOLDER_REPLACE_THIS_LINE')) {
line = i;
const match = lstring.match(/([ \t]+)[\w\W\d ]*/i);

if (match) {
prefix = match[1];
}

break;
}
}

if (line == -1) {
return peggy.generate(baseFilter);
}

const fieldsLines = Object.entries(fieldMapping)
.map(([k, v]) => `${prefix}case '${k}': return '${v}'`);

if (disallowUndefinedFieldNames) {
fieldsLines.push(`${prefix}default: throw new Error('"' + s + '" is not an accepted field name');`);
} else {
fieldsLines.push(`${prefix}default: return s;`);
}

lines.splice(line, 1, ...fieldsLines);

const newFilter = lines.join('\n');

return peggy.generate(newFilter);
}
}

0 comments on commit 38d2176

Please sign in to comment.