Merge branch 'main' into feat/new_wifi_tables
This commit is contained in:
		| @ -14,6 +14,12 @@ TODO | ||||
| - Create new user for database: `GRANT ALL PRIVILEGES ON dev_locationhub.* TO 'dbuser'@'localhost' IDENTIFIED BY '1234';` | ||||
| - Import tables: `/usr/bin/mariadb -u dbuser -p1234 dev_locationhub < server/sql/tables.sql` | ||||
|  | ||||
| ### TTN Integration | ||||
| Create new Webhook for application. Set base url and enable "Uplink message" to api `/api/ttn/webhook`. | ||||
| Add a addidtional header:  | ||||
| - Type: `authorization`  | ||||
| - Value: `Bearer your-very-secure-token` | ||||
|  | ||||
| ### Testing Webhook | ||||
| - To test the webhook use the python script `ttn-webhook-dummy.py` to send prerecorded TTN Uplinks. | ||||
| - To test the script you can use `while true; do echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nSuccess"; nc -l -p 8080 -q 1; done` | ||||
| @ -4,6 +4,7 @@ DB_PASSWORD="" | ||||
| DB_HOST="" | ||||
| DB_DIALECT="" | ||||
| DB_PORT="" | ||||
| WEBHOOK_TOKEN="" #Token that is placed a the TTN Webhook auth | ||||
| WIGLE_TOKEN="" # Go to account and generate token "Encoded for use" | ||||
| WIGLE_BASE_URL="https://api.wigle.net" | ||||
| WIGLE_NETWORK_SEARCH="/api/v2/network/search" | ||||
|  | ||||
| @ -9,11 +9,16 @@ import json | ||||
| import argparse | ||||
| import random | ||||
|  | ||||
| def send_post_request(uri, data): | ||||
| def send_post_request(uri, data, token): | ||||
|     headers = { | ||||
|         "Authorization": f"Bearer {token}", | ||||
|         "Content-Type": "application/json", | ||||
|     } | ||||
|     try: | ||||
|         requests.post(uri, json=data, timeout=1) | ||||
|         response = requests.post(uri, json=data, timeout=1, headers=headers) | ||||
|         print("Return code: " + str(response.status_code)) | ||||
|     except requests.exceptions.RequestException as e: | ||||
|         pass | ||||
|         print(e) | ||||
|  | ||||
| def main(): | ||||
|     parser = argparse.ArgumentParser( | ||||
| @ -24,6 +29,11 @@ def main(): | ||||
|         type=str, | ||||
|         help="The URI to send POST requests to (e.g., http://127.0.0.1:8080/api)", | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         "token", | ||||
|         type=str, | ||||
|         help="Bearer authorization token)", | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         "directory", | ||||
|         type=str, | ||||
| @ -46,7 +56,7 @@ def main(): | ||||
|                 try: | ||||
|                     data = json.load(file) | ||||
|                     print(f"Sending {args.directory} to {args.uri}") | ||||
|                     send_post_request(args.uri, data) | ||||
|                     send_post_request(args.uri, data, args.token) | ||||
|                 except json.JSONDecodeError as e: | ||||
|                     print(f"Error reading {args.directory}: {e}") | ||||
|             return | ||||
| @ -67,7 +77,7 @@ def main(): | ||||
|                 try: | ||||
|                     data = json.load(file) | ||||
|                     print(f"Sending {filename} to {args.uri}") | ||||
|                     send_post_request(args.uri, data) | ||||
|                     send_post_request(args.uri, data, args.token) | ||||
|                 except json.JSONDecodeError as e: | ||||
|                     print(f"Error reading {filename}: {e}") | ||||
|  | ||||
| @ -78,7 +88,7 @@ def main(): | ||||
|                 try: | ||||
|                     data = json.load(file) | ||||
|                     print(f"Sending {filename} to {args.uri}") | ||||
|                     send_post_request(args.uri, data) | ||||
|                     send_post_request(args.uri, data, args.token) | ||||
|                     input("Press Enter to send the next file...") | ||||
|                 except json.JSONDecodeError as e: | ||||
|                     print(f"Error reading {filename}: {e}") | ||||
| @ -91,11 +101,10 @@ def main(): | ||||
|                 try: | ||||
|                     data = json.load(file) | ||||
|                     print(f"Sending {filename} to {args.uri}") | ||||
|                     send_post_request(args.uri, data) | ||||
|                     send_post_request(args.uri, data, args.token) | ||||
|                     input("Press Enter to send another random file...") | ||||
|                 except json.JSONDecodeError as e: | ||||
|                     print(f"Error reading {filename}: {e}") | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
|  | ||||
| @ -7,6 +7,8 @@ import { LpTtnEndDeviceUplinksService } from "../services/lpTtnEndDeviceUplinksS | ||||
| import { TtnGatewayReceptionService } from "../services/ttnGatewayReceptionService"; | ||||
| import { WifiScanService } from "../services/wifiScanService"; | ||||
| import { ttnMessageValidator } from "../validation/ttn/ttnMessageValidation"; | ||||
| import { authenticateHeader } from "../middleware/authentificationMiddleware"; | ||||
| import { StatusCodes } from "http-status-codes"; | ||||
|  | ||||
| const lpTtnEndDeviceUplinksService = container.resolve( | ||||
|   LpTtnEndDeviceUplinksService | ||||
| @ -21,7 +23,7 @@ const router = express.Router(); | ||||
|  | ||||
| router.post( | ||||
|   "/webhook", | ||||
|   validateData(ttnMessageValidator), | ||||
|   [authenticateHeader, validateData(ttnMessageValidator)], | ||||
|   async (req: Request, res: Response) => { | ||||
|     try { | ||||
|       const message = req.body as TtnMessage; | ||||
| @ -92,17 +94,17 @@ router.post( | ||||
|           gnss: | ||||
|             gnnsLocation.latitude && gnnsLocation.longitude | ||||
|               ? { | ||||
|                   latitude: gnnsLocation.latitude, | ||||
|                   longitude: gnnsLocation.longitude, | ||||
|                 } | ||||
|                 latitude: gnnsLocation.latitude, | ||||
|                 longitude: gnnsLocation.longitude, | ||||
|               } | ||||
|               : undefined, | ||||
|         }); | ||||
|       }; | ||||
|       createDatabaseEntries().then(); | ||||
|       res.status(200); | ||||
|       res.status(StatusCodes.OK).send(); | ||||
|     } catch (error) { | ||||
|       console.log(error); | ||||
|       res.status(500).json({ error: "Error creating uplink" }); | ||||
|       res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: "Error creating uplink" }); | ||||
|     } | ||||
|   } | ||||
| ); | ||||
|  | ||||
							
								
								
									
										42
									
								
								server/src/middleware/authentificationMiddleware.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								server/src/middleware/authentificationMiddleware.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| import { NextFunction, Request, Response } from "express"; | ||||
| import { StatusCodes } from "http-status-codes"; | ||||
|  | ||||
| const validateBearerToken = (authorizationHeader: string | undefined): boolean => { | ||||
|     if (!authorizationHeader) { | ||||
|         console.log("Authorization header is missing!"); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     const token = authorizationHeader.split(' ')[1]; // Extract token after 'Bearer' | ||||
|     if (!token) { | ||||
|         console.log("Bearer token is missing!"); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (token !== process.env.WEBHOOK_TOKEN) { | ||||
|         console.log("Bearer token is incorrect!"); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| }; | ||||
|  | ||||
| export function authenticateHeader(req: Request, res: Response, next: NextFunction) { | ||||
|     try { | ||||
|         const authorizationHeader = req.headers['authorization']; | ||||
|  | ||||
|         if (!validateBearerToken(authorizationHeader as string)) { | ||||
|             res.status(StatusCodes.UNAUTHORIZED).json({ error: "Authentication failed" }); | ||||
|             return; | ||||
|         } | ||||
|         console.log("Bearer token is correct!"); | ||||
|  | ||||
|         next(); | ||||
|     } catch (error) { | ||||
|         res.status(StatusCodes.INTERNAL_SERVER_ERROR) | ||||
|             .json({ error: "Internal Server Error" }); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -22,4 +22,4 @@ export function validateData(schema: z.ZodObject<any, any>) { | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user