From 23dd7953970cc911932820a242b4b4ba6c4b7947 Mon Sep 17 00:00:00 2001 From: TimmensOne Date: Sat, 1 Apr 2023 20:34:39 +0200 Subject: [PATCH 1/4] simple api export --- ChatGPT/JSON Response with Device IDs | 55 +++++++++++++++++++++++++++ device-app/routes/api.php | 34 ++++++++++++----- 2 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 ChatGPT/JSON Response with Device IDs diff --git a/ChatGPT/JSON Response with Device IDs b/ChatGPT/JSON Response with Device IDs new file mode 100644 index 0000000..c3a11b4 --- /dev/null +++ b/ChatGPT/JSON Response with Device IDs @@ -0,0 +1,55 @@ +I have this methode: +Route::get('/export', function () { + return response()->json([ + 'Devices' => Device::all(), + 'purchasingInformations' => PurchasingInformation::all(), + 'OwnerTransactions' => OwnerTransaction::all(), + 'LocationTransactions' => LocationTransaction::all() + ]); +}); + +but i want to use the id of for example the devices as key for my json + +To use the id of the Device model as a key in your JSON response, you can modify your code to map each device to an array with the device id as the key. Here's an example: + +php + +Route::get('/export', function () { + $devices = Device::all()->mapWithKeys(function ($device) { + return [$device->id => $device]; + }); + + return response()->json([ + 'Devices' => $devices, + 'purchasingInformations' => PurchasingInformation::all(), + 'OwnerTransactions' => OwnerTransaction::all(), + 'LocationTransactions' => LocationTransaction::all() + ]); +}); + +In this modified code, we first retrieve all Device models using the all() method. We then call the mapWithKeys method on the resulting collection to transform it into an associative array where the device id is the key and the device model is the value. + +We then pass this modified $devices variable to the JSON response, so that the devices will be outputted with their ids as keys. The other collections are passed as is without modification. + +Note that if you have multiple models with the same id, the later models will overwrite the earlier ones in the JSON response. + +------------- + +can i also do it without an key, just the objects? + +Yes, you can also return an array of objects without using keys. Here's an example: + +scss + +Route::get('/export', function () { + return response()->json([ + 'Devices' => Device::all()->toArray(), + 'purchasingInformations' => PurchasingInformation::all()->toArray(), + 'OwnerTransactions' => OwnerTransaction::all()->toArray(), + 'LocationTransactions' => LocationTransaction::all()->toArray() + ]); +}); + +In this code, we're using the toArray() method to convert each collection of models to an array of objects. These arrays are then included in the JSON response with their corresponding names as keys. + +This will return an array of objects without keys. However, keep in mind that if you have multiple models with the same primary key value, their data will be merged into a single object in the JSON response, which may not be what you intended. diff --git a/device-app/routes/api.php b/device-app/routes/api.php index fa1c366..c6f4572 100644 --- a/device-app/routes/api.php +++ b/device-app/routes/api.php @@ -1,5 +1,9 @@ json([ - 'devices' => [ - [ - 'title' => 'Device One' - ], - [ - 'title' => 'Device Two' - ] - ] - ]); + 'Devices' => Device::all(), + 'PurchasingInformations' => PurchasingInformation::all(), + 'OwnerTransactions' => OwnerTransaction::all(), + 'LocationTransactions' => LocationTransaction::all() + ]); +}); + +Route::post('/import', function (Request $request) { + $data = $request->json()->all(); + $devices = $data['Devices']; + foreach ($devices as $device) { + Device::create([ + 'device_id' => $device->device_id, + ]); + } + $purchasingInformations = $data['PurchasingInformations']; + $ownerTransactions = $data['OwnerTransactions']; + $locationTransactions = $data['LocationTransactions']; }); Route::middleware('auth:sanctum')->get('/user', function (Request $request) { From ffd98d046e6513c766e742d5fb98322c8b30a7aa Mon Sep 17 00:00:00 2001 From: TimmensOne Date: Mon, 3 Apr 2023 11:54:41 +0200 Subject: [PATCH 2/4] add basic import api --- ChatGPT/Default value for 'description' | 42 ++++++++++++ README.md | 3 +- .../database/factories/DeviceFactory.php | 3 +- device-app/routes/api.php | 68 +++++++++++++++++-- 4 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 ChatGPT/Default value for 'description' diff --git a/ChatGPT/Default value for 'description' b/ChatGPT/Default value for 'description' new file mode 100644 index 0000000..7293e0a --- /dev/null +++ b/ChatGPT/Default value for 'description' @@ -0,0 +1,42 @@ +Route::post('/import', function (Request $request) { + $data = $request->json()->all(); + $devices = $data['devices']; + foreach ($devices as $device) { + Device::create([ + 'device_id' => $device['device_id'], + 'title' => $device['title'], + 'device_type' => $device['device_type'], + 'description' => $device['description'], + 'accessories' => $device['accessories'], + 'rz_username_buyer' => $device['rz_username_buyer'], + 'serial_number' => $device['serial_number'], + 'image_url' => $device['image_url'], + ]); + } + +but 'description' is not always given. How do i solv it in php? + +You can use the null coalescing operator (??) in PHP to provide a default value when the 'description' field is not present in the input data. + +Here's an example of how you can modify the code to use the null coalescing operator: + +php + +Route::post('/import', function (Request $request) { + $data = $request->json()->all(); + $devices = $data['devices']; + foreach ($devices as $device) { + Device::create([ + 'device_id' => $device['device_id'], + 'title' => $device['title'], + 'device_type' => $device['device_type'], + 'description' => $device['description'] ?? '', // provide an empty string as the default value + 'accessories' => $device['accessories'], + 'rz_username_buyer' => $device['rz_username_buyer'], + 'serial_number' => $device['serial_number'], + 'image_url' => $device['image_url'], + ]); + } +}); + +In the example above, the null coalescing operator is used to check whether the 'description' field exists in the input data. If it does not exist, an empty string is provided as the default value. This way, even if the 'description' field is not present in the input data, the code will still run without errors. diff --git a/README.md b/README.md index 741bb04..acf89c6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,8 @@ latest: 15.04.2023 Laravel is a full feature framework ### security -coss-side-scripting disabled +- coss-side-scripting disabled +- SQL injection attacks ## Database setup diff --git a/device-app/database/factories/DeviceFactory.php b/device-app/database/factories/DeviceFactory.php index 1b44aad..7d0ed7f 100644 --- a/device-app/database/factories/DeviceFactory.php +++ b/device-app/database/factories/DeviceFactory.php @@ -16,10 +16,11 @@ class DeviceFactory extends Factory */ public function definition(): array { + $device_type = $this->faker->randomElement(['projektor','computer','laptop','mikrofon','whiteboard','unbekannt']); return [ 'device_id' => $this->faker->uuid(), 'title' => $this->faker->word(), - 'device_type' => $this->faker->domainWord(), + 'device_type' => $device_type, 'description' => $this->faker->sentence(), 'accessories' => $this->faker->word(), 'rz_username_buyer' => $this->faker->name(), diff --git a/device-app/routes/api.php b/device-app/routes/api.php index c6f4572..5d7419b 100644 --- a/device-app/routes/api.php +++ b/device-app/routes/api.php @@ -5,6 +5,7 @@ use App\Models\OwnerTransaction; use App\Models\PurchasingInformation; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Route; /* @@ -29,16 +30,69 @@ }); Route::post('/import', function (Request $request) { - $data = $request->json()->all(); - $devices = $data['Devices']; + $data = $request->json()->all(); + $devices = $data['devices']; + $purchasingInformations = $data['purchasing_information']; + $ownerTransactions = $data['owner_transactions']; + $locationTransactions = $data['location_transactions']; + //$response = {}; foreach ($devices as $device) { - Device::create([ - 'device_id' => $device->device_id, + $deviceInsert = DB::table('devices')->insertOrIgnore([ + 'device_id' => $device['device_id'], + 'title' => $device['title'], + 'device_type' => $device['device_type'], + 'description' => $device['description'] ?? '', + 'accessories' => $device['accessories'] ?? '', + 'rz_username_buyer' => $device['rz_username_buyer'], + 'serial_number' => $device['serial_number'], + 'image_url' => $device['image_url'] ]); + // insertOrIgnore returns 0 if statement was ignored + if ($deviceInsert != 0) { + // save insert for later + } } - $purchasingInformations = $data['PurchasingInformations']; - $ownerTransactions = $data['OwnerTransactions']; - $locationTransactions = $data['LocationTransactions']; + foreach ($purchasingInformations as $purchasing) { + $purchasingInsert = DB::table('purchasing_information')->insertOrIgnore([ + 'purchasing_information_id' => $purchasing['purchasing_information_id'], + 'price' => $purchasing['price'], + 'timestamp_warranty_end' => $purchasing['timestamp_warranty_end'], + 'timestamp_purchase' => $purchasing['timestamp_purchase'], + 'cost_centre' => $purchasing['cost_centre'], + 'seller' => $purchasing['seller'] ?? '', + 'device_id' => $purchasing['device_id'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($purchasingInsert != 0) { + // save insert for later + } + } + foreach ($ownerTransactions as $owner) { + $ownerInsert = DB::table('owner_transactions')->insertOrIgnore([ + 'owner_transaction_id' => $owner['owner_transaction_id'], + 'rz_username' => $owner['rz_username'], + 'timestamp_owner_since' => $owner['timestamp_owner_since'], + 'device_id' => $owner['device_id'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($ownerInsert != 0) { + // save insert for later + } + } + foreach ($locationTransactions as $location) { + $locationInsert = DB::table('location_transactions')->insertOrIgnore([ + 'location_transaction_id' => $location['location_transaction_id'], + 'room_code' => $location['room_code'], + 'timestamp_located_since' => $location['timestamp_located_since'], + 'device_id' => $location['device_id'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($locationInsert != 0) { + // save insert for later + } + } + // ToDo: return only inserted + return $request->json()->all(); }); Route::middleware('auth:sanctum')->get('/user', function (Request $request) { From ca9762df9a7bb934bea7d6d57e6bb44ee42781ae Mon Sep 17 00:00:00 2001 From: TimmensOne Date: Mon, 3 Apr 2023 14:44:33 +0200 Subject: [PATCH 3/4] add token based api auth --- ...01_create_personal_access_tokens_table.php | 4 ++- device-app/routes/api.php | 25 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/device-app/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/device-app/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php index e828ad8..92d4b1b 100644 --- a/device-app/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php +++ b/device-app/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -13,7 +13,9 @@ public function up(): void { Schema::create('personal_access_tokens', function (Blueprint $table) { $table->id(); - $table->morphs('tokenable'); + $table->string('tokenable_type'); + $table->string('tokenable_id'); + $table->index(["tokenable_type", "tokenable_id"]); $table->string('name'); $table->string('token', 64)->unique(); $table->text('abilities')->nullable(); diff --git a/device-app/routes/api.php b/device-app/routes/api.php index 5d7419b..88414be 100644 --- a/device-app/routes/api.php +++ b/device-app/routes/api.php @@ -4,8 +4,11 @@ use App\Models\LocationTransaction; use App\Models\OwnerTransaction; use App\Models\PurchasingInformation; +use App\Models\User; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Route; /* @@ -19,7 +22,25 @@ | */ -Route::get('/export', function () { +Route::post('/login', function (Request $request) { + $fields = $request->validate( + [ + 'user' => 'required', + 'password' => 'required' + ] + + ); + $user = User::where('rz_username', $fields['user'])->first(); + if (!$user || !Hash::check($fields['password'], $user->hashed_password)) { + return response([ + 'message' => 'Bad login' + ], 401); + } + $token = $user->createToken('token'); + return ['token' => $token->plainTextToken]; +}); + +Route::middleware('auth:sanctum')->get('/export', function () { return response()->json([ 'Devices' => Device::all(), @@ -29,7 +50,7 @@ ]); }); -Route::post('/import', function (Request $request) { +Route::middleware('auth:sanctum')->post('/import', function (Request $request) { $data = $request->json()->all(); $devices = $data['devices']; $purchasingInformations = $data['purchasing_information']; From 4c4d806e8a41486594291b486ad7293e7ab7a4a1 Mon Sep 17 00:00:00 2001 From: TimmensOne Date: Mon, 3 Apr 2023 15:07:12 +0200 Subject: [PATCH 4/4] add auto generated swagger documentation --- ChatGPT/API Swagger document generated.txt | 263 +++++++++++++++++++++ device-app/swagger.yml | 199 ++++++++++++++++ 2 files changed, 462 insertions(+) create mode 100644 ChatGPT/API Swagger document generated.txt create mode 100644 device-app/swagger.yml diff --git a/ChatGPT/API Swagger document generated.txt b/ChatGPT/API Swagger document generated.txt new file mode 100644 index 0000000..6ca6548 --- /dev/null +++ b/ChatGPT/API Swagger document generated.txt @@ -0,0 +1,263 @@ +Can you generate me a swagger document for the following api? + +Route::post('/login', function (Request $request) { + $fields = $request->validate( + [ + 'user' => 'required', + 'password' => 'required' + ] + + ); + $user = User::where('rz_username', $fields['user'])->first(); + if (!$user || !Hash::check($fields['password'], $user->hashed_password)) { + return response([ + 'message' => 'Bad login' + ], 401); + } + $token = $user->createToken('token'); + return ['token' => $token->plainTextToken]; +}); + +Route::middleware('auth:sanctum')->get('/export', function () { + + return response()->json([ + 'Devices' => Device::all(), + 'PurchasingInformations' => PurchasingInformation::all(), + 'OwnerTransactions' => OwnerTransaction::all(), + 'LocationTransactions' => LocationTransaction::all() + ]); +}); + +Route::middleware('auth:sanctum')->post('/import', function (Request $request) { + $data = $request->json()->all(); + $devices = $data['devices']; + $purchasingInformations = $data['purchasing_information']; + $ownerTransactions = $data['owner_transactions']; + $locationTransactions = $data['location_transactions']; + //$response = {}; + foreach ($devices as $device) { + $deviceInsert = DB::table('devices')->insertOrIgnore([ + 'device_id' => $device['device_id'], + 'title' => $device['title'], + 'device_type' => $device['device_type'], + 'description' => $device['description'] ?? '', + 'accessories' => $device['accessories'] ?? '', + 'rz_username_buyer' => $device['rz_username_buyer'], + 'serial_number' => $device['serial_number'], + 'image_url' => $device['image_url'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($deviceInsert != 0) { + // save insert for later + } + } + foreach ($purchasingInformations as $purchasing) { + $purchasingInsert = DB::table('purchasing_information')->insertOrIgnore([ + 'purchasing_information_id' => $purchasing['purchasing_information_id'], + 'price' => $purchasing['price'], + 'timestamp_warranty_end' => $purchasing['timestamp_warranty_end'], + 'timestamp_purchase' => $purchasing['timestamp_purchase'], + 'cost_centre' => $purchasing['cost_centre'], + 'seller' => $purchasing['seller'] ?? '', + 'device_id' => $purchasing['device_id'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($purchasingInsert != 0) { + // save insert for later + } + } + foreach ($ownerTransactions as $owner) { + $ownerInsert = DB::table('owner_transactions')->insertOrIgnore([ + 'owner_transaction_id' => $owner['owner_transaction_id'], + 'rz_username' => $owner['rz_username'], + 'timestamp_owner_since' => $owner['timestamp_owner_since'], + 'device_id' => $owner['device_id'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($ownerInsert != 0) { + // save insert for later + } + } + foreach ($locationTransactions as $location) { + $locationInsert = DB::table('location_transactions')->insertOrIgnore([ + 'location_transaction_id' => $location['location_transaction_id'], + 'room_code' => $location['room_code'], + 'timestamp_located_since' => $location['timestamp_located_since'], + 'device_id' => $location['device_id'] + ]); + // insertOrIgnore returns 0 if statement was ignored + if ($locationInsert != 0) { + // save insert for later + } + } + return $request->json()->all(); +}); + +Sure! Here's a Swagger document for the provided API: + +yaml + +swagger: '2.0' +info: + title: My API + version: '1.0' +basePath: / +schemes: + - http +consumes: + - application/json +produces: + - application/json + +paths: + /login: + post: + summary: Authenticate user + description: Authenticate user with username and password + parameters: + - in: body + name: body + description: User credentials + required: true + schema: + type: object + properties: + user: + type: string + password: + type: string + responses: + '200': + description: Authentication successful + schema: + type: object + properties: + token: + type: string + '401': + description: Authentication failed + schema: + type: object + properties: + message: + type: string + + /export: + get: + summary: Export data + description: Get all devices, purchasing information, owner transactions, and location transactions + responses: + '200': + description: Data retrieved successfully + schema: + type: object + properties: + Devices: + type: array + items: + $ref: '#/definitions/Device' + PurchasingInformations: + type: array + items: + $ref: '#/definitions/PurchasingInformation' + OwnerTransactions: + type: array + items: + $ref: '#/definitions/OwnerTransaction' + LocationTransactions: + type: array + items: + $ref: '#/definitions/LocationTransaction' + '401': + description: Authentication failed + schema: + type: object + properties: + message: + type: string + + /import: + post: + summary: Import data + description: Import device, purchasing information, owner transaction, and location transaction data + parameters: + - in: body + name: body + description: Data to import + required: true + schema: + type: object + properties: + devices: + type: array + items: + $ref: '#/definitions/Device' + purchasing_information: + type: array + items: + $ref: '#/definitions/PurchasingInformation' + owner_transactions: + type: array + items: + $ref: '#/definitions/OwnerTransaction' + location_transactions: + type: array + items: + $ref: '#/definitions/LocationTransaction' + responses: + '200': + description: Data imported successfully + schema: + type: object + properties: + devices: + type: array + items: + type: string + purchasing_information: + type: array + items: + type: string + owner_transactions: + type: array + items: + type: string + location_transactions: + type: array + items: + type: string + '401': + description: Authentication failed + schema: + type: object + properties: + message: + type: string + +definitions: + Device: + type: object + properties: + device_id: + type: integer + title: + type: string + device_type: + type: string + description: + type: string + accessories: + type: string + rz_username_buyer: + type: string + serial_number: + type: string + image_url: + type: string + + PurchasingInformation: + type: object + properties: + purchasing_information_id: + type: integer + price diff --git a/device-app/swagger.yml b/device-app/swagger.yml new file mode 100644 index 0000000..662822c --- /dev/null +++ b/device-app/swagger.yml @@ -0,0 +1,199 @@ +swagger: '2.0' +info: + title: Device Manager API + version: '1.0' +basePath: /api +schemes: + - http +consumes: + - application/json +produces: + - application/json + +paths: + /login: + post: + summary: Authenticate user + description: Authenticate user with username and password + parameters: + - in: body + name: body + description: User credentials + required: true + schema: + type: object + properties: + user: + type: string + password: + type: string + responses: + '200': + description: Authentication successful + schema: + type: object + properties: + token: + type: string + '401': + description: Authentication failed + schema: + type: object + properties: + message: + type: string + + /export: + get: + summary: Export data + description: Get all devices, purchasing information, owner transactions, and location transactions + responses: + '200': + description: Data retrieved successfully + schema: + type: object + properties: + Devices: + type: array + items: + $ref: '#/definitions/Device' + PurchasingInformations: + type: array + items: + $ref: '#/definitions/PurchasingInformation' + OwnerTransactions: + type: array + items: + $ref: '#/definitions/OwnerTransactions' + LocationTransactions: + type: array + items: + $ref: '#/definitions/LocationTransactions' + '401': + description: Authentication failed + schema: + type: object + properties: + message: + type: string + + /import: + post: + summary: Import data + description: Import device, purchasing information, owner transaction, and location transaction data + parameters: + - in: body + name: body + description: Data to import + required: true + schema: + type: object + properties: + devices: + type: array + items: + $ref: '#/definitions/Device' + purchasing_information: + type: array + items: + $ref: '#/definitions/PurchasingInformation' + owner_transactions: + type: array + items: + $ref: '#/definitions/OwnerTransactions' + location_transactions: + type: array + items: + $ref: '#/definitions/LocationTransactions' + responses: + '200': + description: Data imported successfully + schema: + type: object + properties: + devices: + type: array + items: + type: string + purchasing_information: + type: array + items: + type: string + owner_transactions: + type: array + items: + type: string + location_transactions: + type: array + items: + type: string + '401': + description: Authentication failed + schema: + type: object + properties: + message: + type: string + +definitions: + Device: + type: object + properties: + device_id: + type: string + title: + type: string + device_type: + type: string + description: + type: string + accessories: + type: string + rz_username_buyer: + type: string + serial_number: + type: string + image_url: + type: string + + PurchasingInformation: + type: object + properties: + purchasing_information_id: + type: string + price: + type: string + timestamp_warranty_end: + type: string + timestamp_purchase: + type: string + cost_centre: + type: integer + seller: + type: string + device_id: + type: string + + OwnerTransactions: + type: object + properties: + owner_transaction_id: + type: string + rz_username: + type: string + timestamp_owner_since: + type: string + device_id: + type: string + + LocationTransactions: + type: object + properties: + location_transaction_id: + type: string + room_code: + type: string + timestamp_located_since: + type: string + device_id: + type: string