Skip to content
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

Payload validation and parsing with zod #125

Merged
merged 24 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d857122
#65 install zod
JulianGrabitzky Sep 5, 2023
45ffd7c
#65 Create and test UpdateTrack schema
JulianGrabitzky Sep 5, 2023
fb62d9d
#65 add zod schemas
JulianGrabitzky Sep 12, 2023
6de62e7
Merge branch 'development' into 65-payload-validation
JulianGrabitzky Sep 12, 2023
f04a435
Merge branch 'development' into 65-payload-validation
JulianGrabitzky Sep 12, 2023
9b5c4fd
#65 Add validation to track route
JulianGrabitzky Sep 12, 2023
4103690
#65 remove schema validation from index route
JulianGrabitzky Sep 12, 2023
eb27c04
#65 add zod to init route
JulianGrabitzky Sep 12, 2023
397b83b
Change first letter to uppercase
JulianGrabitzky Sep 12, 2023
f46305f
#65 zod, login route
JulianGrabitzky Sep 12, 2023
529d2e1
#65 zod, poi route
JulianGrabitzky Sep 12, 2023
53183d1
#65 zod, poitype route
JulianGrabitzky Sep 12, 2023
3471879
Convert api/tracker schema names to uppercase
JulianGrabitzky Sep 12, 2023
5ded28a
#65 zod, tracker route
JulianGrabitzky Sep 12, 2023
d4687c5
#65 zod, user route
JulianGrabitzky Sep 12, 2023
d07830e
#65 zod, vehicle route
JulianGrabitzky Sep 12, 2023
28144e3
#65 zod, vehicletype route
JulianGrabitzky Sep 12, 2023
ae5ff4b
#65 remove jsonschmea
JulianGrabitzky Sep 12, 2023
798637b
#65 adjust types in non-route files
JulianGrabitzky Sep 12, 2023
c324a9e
#65 adjust validation error severity in logging
JulianGrabitzky Sep 12, 2023
5ae62fb
#65 remove finished todo's
JulianGrabitzky Sep 12, 2023
665549d
#65
JulianGrabitzky Sep 12, 2023
fc67a41
Merge branch 'development' into 65-payload-validation
JulianGrabitzky Sep 13, 2023
1924b9d
#65 add payload validation for lte payload
JulianGrabitzky Sep 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Server/package-lock.json

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

5 changes: 3 additions & 2 deletions Server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"jsonschema": "^1.4.1",
"jsonwebtoken": "^9.0.0",
"morgan": "^1.10.0",
"winston": "^3.8.2"
"winston": "^3.8.2",
"zod": "^3.22.2"
},
"devDependencies": {
"@types/dotenv": "^8.2.0",
Expand All @@ -55,4 +56,4 @@
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
}
}
}
102 changes: 44 additions & 58 deletions Server/src/models/api.app.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,32 @@
import { PointOfInterest, Position, Vehicle } from "./api"
import { GeoJSON } from "geojson"
import { z } from "zod"

// TODO: seperate the types
/** @see {isInitResponseApp} ts-auto-guard:type-guard */
export type InitResponseApp = {
trackId: number
trackName: string
trackPath: GeoJSON.FeatureCollection
trackLength: number
pointsOfInterest: PointOfInterest[]
} // FullTrack & {pointsOfInterest: PointOfInterest[];};
export const InitResponseApp = z.object({
trackId: z.number(),
trackName: z.string(),
trackPath: z.any(), //TODO: What kind of FeatureCollection? old ->GeoJSON.FeatureCollection
trackLength: z.number(),
pointsOfInterest: PointOfInterest.array()
}) // FullTrack & {pointsOfInterest: PointOfInterest[];};

// TODO: change to just BareTrack.
/** @see {isTrackListEntryApp} ts-auto-guard:type-guard */
export type TrackListEntryApp = {
id: number // Positive integer to uniquely identify track
name: string // E.g. "Malente-Lütjenburg"
}
export const TrackListEntryApp = z.object({
id: z.number(), // Positive integer to uniquely identify track
name: z.string() // E.g. "Malente-Lütjenburg"
})

// TODO: simplify to just Position, without wrapping.
/** @see {isInitRequestApp} ts-auto-guard:type-guard */
export type InitRequestApp = {
export const InitRequestApp = z.object({
pos: Position
}
})

// export enum POIType {
// None = 0,
// LevelCrossing = 1,
// LesserLevelCrossing = 2,
// Picnic = 3,
// TrackEnd = 4,
// }

/** @see {isUpdateRequestApp} ts-auto-guard:type-guard */
export interface UpdateRequestApp {
vehicleId: number // vehicle id of user
pos?: Position // the current position of user
speed?: number // Speed in km/h
heading?: number // Heading of the vehicle between 0 and 359
}

/** @see {isUpdateResponseApp} ts-auto-guard:type-guard */
export interface UpdateResponseApp {
pos: Position // The current position as measured by vehicle
heading: number // Heading of the vehicle between 0 and 359
vehiclesNearUser: VehicleApp[] // Vehicles that should be marked on the map
percentagePositionOnTrack: number // Percentage (0-100) e.g. 0% Malente; 100% Lütjenburg
speed: number // Speed in km/h
passingPosition?: Position // Only set if needed
}

/** @see {isGetUidApp} ts-auto-guard:type-guard */
export interface GetUidApp {
vehicleName: string
trackId: number
}

/** @see {isReturnUidApp} ts-auto-guard:type-guard */
export interface ReturnUidApp {
vehicleId: number
}
export const UpdateRequestApp = z.object({
vehicleId: z.number(), // vehicle id of user
pos: Position.optional(), // the current position of user
speed: z.number().optional(), // Speed in km/h
heading: z.number().optional() // Heading of the vehicle between 0 and 359
})

//================ new

Expand All @@ -68,8 +35,27 @@ export interface ReturnUidApp {
* if it is heading towards a user.
* TODO: replace with a specific API
*/
/** @see {isVehicleApp} ts-auto-guard:type-guard */
export interface VehicleApp extends Vehicle {
id: number
headingTowardsUser?: boolean // Is the other vehicle heading towards the user?
}
export const VehicleApp = Vehicle.extend({
id: z.number(),
headingTowardsUser: z.boolean().optional() // Is the other vehicle heading towards the user?
})

//================ new

export const UpdateResponseApp = z.object({
pos: Position, // The current position as measured by vehicle
heading: z.number(), // Heading of the vehicle between 0 and 359
vehiclesNearUser: VehicleApp.array(), // Vehicles that should be marked on the map
percentagePositionOnTrack: z.number(), // Percentage (0-100) e.g. 0% Malente; 100% Lütjenburg
speed: z.number(), // Speed in km/h
passingPosition: Position.optional() // Only set if needed
})

export const GetUidApp = z.object({
vehicleName: z.string(),
trackId: z.number()
})

export const ReturnUidApp = z.object({
vehicleId: z.number()
})
110 changes: 54 additions & 56 deletions Server/src/models/api.tracker.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,62 @@
/** @see {isUplinkTracker} ts-auto-guard:type-guard */
export type UplinkTracker = {
end_device_ids: EndDeviceIdsTracker
received_at: string
uplink_message: UplinkMessageTracker
}
import { z } from "zod"

export const EndDeviceIdsTracker = z.object({
device_id: z.string()
})

/** @see {isEndDevoceIdsTracker} ts-auto-guard:type-guard */
export type EndDeviceIdsTracker = {
device_id: string
}
export const DecodedPayloadTracker = z.object({
batV: z.number(),
fixFailed: z.boolean(),
headingDeg: z.number(),
inTrip: z.boolean(),
latitudeDeg: z.number(),
longitudeDeg: z.number(),
speedKmph: z.number(),
type: z.string()
})

/** @see {isUplinkMessageTracker} ts-auto-guard:type-guard */
export type UplinkMessageTracker = {
f_port: number
export const UplinkMessageTracker = z.object({
f_port: z.number(),
decoded_payload: DecodedPayloadTracker
}
})

/** @see {isDecodedPayloadTracker} ts-auto-guard:type-guard */
export type DecodedPayloadTracker = {
batV: number
fixFailed: boolean
headingDeg: number
inTrip: boolean
latitudeDeg: number
longitudeDeg: number
speedKmph: number
type: string
}
export const UplinkTracker = z.object({
end_device_ids: EndDeviceIdsTracker,
received_at: z.string(),
uplink_message: UplinkMessageTracker
})

export type UplinkLteTracker = {
SerNo: number
IMEI: string
ICCID: string
ProdId: number
FW: string
Records: LteRecord[]
}
export const LteRecord = z.object({
SeqNo: z.number(),
Reason: z.number(),
DateUTC: z.string(),
Fields: z.any() // list of heterogenous objects depending on FType
})

export type LteRecord = {
SeqNo: number
Reason: number
DateUTC: string
Fields: any // list of heterogenous objects depending on FType
}
export const LteRecordField0 = z.object({
GpsUTC: z.string(),
Lat: z.number(),
Long: z.number(),
Alt: z.number(),
Spd: z.number(),
SpdAcc: z.number(),
Head: z.number(),
PDOP: z.number(),
PosAcc: z.number(),
GpsStat: z.number(),
FType: z.literal(0)
})

export type LteRecordField0 = {
GpsUTC: string
Lat: number
Long: number
Alt: number
Spd: number
SpdAcc: number
Head: number
PDOP: number
PosAcc: number
GpsStat: number
FType: 0
}
export const LteRecordField6 = z.object({
AnalogueData: z.any(), // object with numbers as keys ("1": probably battery voltage (x100), "3": probably temperature (x100), "4": probably GSM signal)
FType: z.literal(6)
})

export type LteRecordField6 = {
AnalogueData: any // object with numbers as keys ("1": probably battery voltage (x100), "3": probably temperature (x100), "4": probably GSM signal)
FType: 6
}
export const UplinkLteTracker = z.object({
SerNo: z.number(),
IMEI: z.string(),
ICCID: z.string(),
ProdId: z.number(),
FW: z.string(),
Records: z.array(LteRecord)
})
Loading
Loading