-
-
Notifications
You must be signed in to change notification settings - Fork 1
Division Airport Request Deletion #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,10 @@ interface AirportData { | |
| name?: string; | ||
| continent?: string; | ||
| elevation_ft?: string; | ||
| country?: { | ||
| code: string; | ||
| name: string; | ||
| }; | ||
|
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The This creates a type mismatch between the interface definition and the actual runtime data structure. Consider either:
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/services/airport.ts
Line: 12:15
Comment:
The `AirportData` interface defines `country` as a nested object with `code` and `name` properties, but the database stores these as separate `country_code` and `country_name` columns. When airports are returned from the database (lines 286, 419, 430), they contain the flat structure (`country_code`, `country_name`) rather than the nested structure defined in this interface.
This creates a type mismatch between the interface definition and the actual runtime data structure. Consider either:
1. Transforming the database result to match the interface (add a `country` object when `country_code` exists)
2. Or updating the interface to reflect the actual flat structure returned by `getAirport()`
How can I resolve this? If you propose a fix, please make it concise. |
||
| runways?: Array<{ | ||
| length_ft: string; | ||
| width_ft: string; | ||
|
|
@@ -194,6 +198,8 @@ export class AirportService { | |
| bbox_min_lon: number | null; | ||
| bbox_max_lat: number | null; | ||
| bbox_max_lon: number | null; | ||
| country_code: string | null; | ||
| country_name: string | null; | ||
| }>('SELECT * FROM airports WHERE icao = ?', [uppercaseIcao]); | ||
| const airportFromDb = airportResult.results[0]; | ||
|
|
||
|
|
@@ -250,6 +256,8 @@ export class AirportService { | |
| bbox_min_lon: number | null; | ||
| bbox_max_lat: number | null; | ||
| bbox_max_lon: number | null; | ||
| country_code: string | null; | ||
| country_name: string | null; | ||
| }>('SELECT * FROM airports WHERE icao = ?', [uppercaseIcao]); | ||
| if (reread.results[0]) Object.assign(airportFromDb, reread.results[0]); | ||
| } | ||
|
|
@@ -297,11 +305,13 @@ export class AirportService { | |
| continent: airportData.continent || 'UNKNOWN', | ||
| elevation_ft: !Number.isNaN(elevation_ft) ? elevation_ft : null, | ||
| elevation_m, | ||
| country_code: airportData.country?.code || null, | ||
| country_name: airportData.country?.name || null, | ||
| }; | ||
|
|
||
| // Save airport to database using write-optimized operation | ||
| await this.dbSession.executeWrite( | ||
| 'INSERT INTO airports (icao, latitude, longitude, name, continent, elevation_ft, elevation_m) VALUES (?, ?, ?, ?, ?, ?, ?)', | ||
| 'INSERT INTO airports (icao, latitude, longitude, name, continent, elevation_ft, elevation_m, country_code, country_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', | ||
| [ | ||
| airport.icao, | ||
| airport.latitude ?? null, | ||
|
|
@@ -310,6 +320,8 @@ export class AirportService { | |
| airport.continent, | ||
| airport.elevation_ft, | ||
| airport.elevation_m, | ||
| airport.country_code, | ||
| airport.country_name, | ||
| ], | ||
| ); | ||
|
|
||
|
|
@@ -341,6 +353,8 @@ export class AirportService { | |
| bbox_min_lon: number | null; | ||
| bbox_max_lat: number | null; | ||
| bbox_max_lon: number | null; | ||
| country_code: string | null; | ||
| country_name: string | null; | ||
| }>('SELECT * FROM airports WHERE icao = ?', [uppercaseIcao]); | ||
| const mergedAirport = { ...airport, ...reread.results[0] }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -232,6 +232,33 @@ export class DivisionService { | |||||||||
| })); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| async deleteAirportRequest(divisionId: number, icao: string, vatsimId: string): Promise<boolean> { | ||||||||||
| // Verify user is a member of this division | ||||||||||
| const role = await this.getMemberRole(divisionId, vatsimId); | ||||||||||
| if (!role) throw new HttpError(403, 'Forbidden: User is not a member of this division'); | ||||||||||
|
|
||||||||||
| // Delete only if the division has requested this ICAO and status is pending or rejected | ||||||||||
| const result = await this.dbSession.executeWrite( | ||||||||||
| `DELETE FROM division_airports | ||||||||||
| WHERE division_id = ? AND icao = ? AND status IN ('pending', 'rejected') | ||||||||||
| RETURNING id`, | ||||||||||
| [divisionId, icao.toUpperCase()], | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code will crash with a runtime error if Add validation before using the parameter:
Suggested change
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/services/divisions.ts
Line: 245:245
Comment:
The code will crash with a runtime error if `icao` is `undefined` or `null` when calling `toUpperCase()`. This can happen if the API endpoint receives a JSON body without the `icao` field or with `icao: null`.
Add validation before using the parameter:
```suggestion
if (!icao) throw new HttpError(400, 'ICAO code is required');
// Delete only if the division has requested this ICAO and status is pending or rejected
```
How can I resolve this? If you propose a fix, please make it concise. |
||||||||||
| ); | ||||||||||
|
|
||||||||||
| const rows = result.results as unknown as Array<{ id: number }> | null; | ||||||||||
| const deleted = !!(rows && rows[0]); | ||||||||||
|
|
||||||||||
| if (deleted) { | ||||||||||
| try { | ||||||||||
| this.posthog?.track('Division Airport Request Deleted', { divisionId, icao, deletedBy: vatsimId }); | ||||||||||
| } catch (e) { | ||||||||||
| console.warn('Posthog track failed (Division Airport Request Deleted)', e); | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return deleted; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| async getDivisionMembers(divisionId: number): Promise<(DivisionMember & { display_name: string })[] | null> { | ||||||||||
| type DivisionMemberRow = { | ||||||||||
| division_exists: number | null; | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing input validation for the
icaofield. If the request body doesn't includeicaoor if it'snull/undefined, the code will crash whendeleteAirportRequesttries to callicao.toUpperCase()on line 245 of divisions.ts.Add validation after parsing the JSON:
Prompt To Fix With AI