From 70999994b8e9c4552be382ada0247abcc69b2e9d Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 14:55:10 +0100 Subject: [PATCH 01/13] Remove unused 'DetectedDevice' functionality --- app/Entities/DetectedDevice.php | 37 -------- app/Http/Controllers/ACSController.php | 1 - .../Controllers/DetectedDevicesController.php | 84 ------------------- ...4_06_09_135311_remove_detected_devices.php | 34 ++++++++ .../detected_devices/index-row.blade.php | 7 -- .../views/detected_devices/index.blade.php | 30 ------- routes/web.php | 4 - 7 files changed, 34 insertions(+), 163 deletions(-) delete mode 100644 app/Entities/DetectedDevice.php delete mode 100644 app/Http/Controllers/DetectedDevicesController.php create mode 100644 database/migrations/2024_06_09_135311_remove_detected_devices.php delete mode 100644 resources/views/detected_devices/index-row.blade.php delete mode 100644 resources/views/detected_devices/index.blade.php diff --git a/app/Entities/DetectedDevice.php b/app/Entities/DetectedDevice.php deleted file mode 100644 index a48c55ba..00000000 --- a/app/Entities/DetectedDevice.php +++ /dev/null @@ -1,37 +0,0 @@ -get(); - $uniqueDevices = $devices->unique('mac_address'); - - //Attach the count of the number of occurrences to each record - $uniqueDevices->each(function ($item, $key) use ($devices) { - - $item['occurrences'] = $devices->where('mac_address', $item['mac_address'])->count(); - - }); - - //Ensure the display name is always present and doesn't get overridden by a newer blank name - $uniqueDevices->each(function ($item, $key) use ($devices) { - - $item['display_name'] = $devices->where('mac_address', $item['mac_address'])->sortByDesc('display_name')->first()->display_name; - - }); - - return view('detected_devices.index', ['devices' => $uniqueDevices]); - } - - /** - * Display the specified resource. - * - * @param int $id - * @return Response - */ - public function show($id) - { - // - } - - /** - * Show the form for editing the specified resource. - * - * @param int $id - * @return Response - */ - public function edit($id) - { - // - } - - /** - * Update the specified resource in storage. - * - * @param int $id - * @return Response - */ - public function update($id) - { - // - } - - /** - * Remove the specified resource from storage. - * - * @param int $id - * @return Response - */ - public function destroy($id) - { - // - } -} diff --git a/database/migrations/2024_06_09_135311_remove_detected_devices.php b/database/migrations/2024_06_09_135311_remove_detected_devices.php new file mode 100644 index 00000000..40054e82 --- /dev/null +++ b/database/migrations/2024_06_09_135311_remove_detected_devices.php @@ -0,0 +1,34 @@ +increments('id'); + $table->string('type', 50); + $table->string('mac_address', 25); + $table->string('display_name', 100)->nullable(); + $table->timestamps(); + }); + } +} diff --git a/resources/views/detected_devices/index-row.blade.php b/resources/views/detected_devices/index-row.blade.php deleted file mode 100644 index ea764ffd..00000000 --- a/resources/views/detected_devices/index-row.blade.php +++ /dev/null @@ -1,7 +0,0 @@ - - {{ $device->created_at }} - {{ $device->type }} - {{ $device->mac_address }} - {{ $device->display_name }} - {{ $device->occurrences }} - \ No newline at end of file diff --git a/resources/views/detected_devices/index.blade.php b/resources/views/detected_devices/index.blade.php deleted file mode 100644 index df53018e..00000000 --- a/resources/views/detected_devices/index.blade.php +++ /dev/null @@ -1,30 +0,0 @@ -@extends('layouts.main') - -@section('meta-title') - Detected Devices -@stop - -@section('page-title') - Detected Devices -@stop - - -@section('content') - - - - - - - - - - - - - - @each('detected_devices.index-row', $devices, 'device') - -
DateTypeMac AddressDisplay NameOccurrences
- -@stop diff --git a/routes/web.php b/routes/web.php index c57f272e..6cb9ce47 100755 --- a/routes/web.php +++ b/routes/web.php @@ -188,10 +188,6 @@ //spark core - printer charges Route::post('acs/spark', ['uses' => 'ACSSparkController@handle']); -Route::group(array('middleware' => 'role:admin'), function () { - Route::resource('detected_devices', 'DetectedDevicesController'); -}); - Route::group(array('middleware' => 'role:acs'), function () { Route::resource('devices', 'DeviceController'); }); From e03199157f5f4855a8e13357662a9984729f79a7 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:00:25 +0100 Subject: [PATCH 02/13] Remove unused api-docs --- .../Controllers/ACS/ActivityController.php | 1 - app/Http/Requests/ACS/Activity.php | 1 - composer.json | 1 - composer.lock | 192 +--------------- config/swagger.php | 51 ----- resources/views/swagger/index.blade.php | 85 ------- routes/web.php | 75 ------- storage/docs/api-docs.json | 208 ------------------ 8 files changed, 1 insertion(+), 613 deletions(-) delete mode 100644 config/swagger.php delete mode 100644 resources/views/swagger/index.blade.php delete mode 100644 storage/docs/api-docs.json diff --git a/app/Http/Controllers/ACS/ActivityController.php b/app/Http/Controllers/ACS/ActivityController.php index 3bc1d694..b7b03bb9 100644 --- a/app/Http/Controllers/ACS/ActivityController.php +++ b/app/Http/Controllers/ACS/ActivityController.php @@ -10,7 +10,6 @@ use Illuminate\Http\Request; use BB\Http\Requests; use BB\Http\Controllers\Controller; -use Swagger\Annotations as SWG; class ActivityController extends Controller { diff --git a/app/Http/Requests/ACS/Activity.php b/app/Http/Requests/ACS/Activity.php index 07c6b0fc..95c04af1 100644 --- a/app/Http/Requests/ACS/Activity.php +++ b/app/Http/Requests/ACS/Activity.php @@ -1,7 +1,6 @@ =5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/master" - }, - "time": "2016-08-06T20:24:11+00:00" - }, { "name": "psr/container", "version": "1.1.1", @@ -6701,71 +6576,6 @@ }, "abandoned": "laminas/laminas-diactoros", "time": "2019-11-13T19:16:13+00:00" - }, - { - "name": "zircote/swagger-php", - "version": "2.1.13", - "source": { - "type": "git", - "url": "https://github.com/zircote/swagger-php.git", - "reference": "cc88b23d2dfb9fa38b989cd479477860235d0591" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/cc88b23d2dfb9fa38b989cd479477860235d0591", - "reference": "cc88b23d2dfb9fa38b989cd479477860235d0591", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.7", - "php": ">=7.2", - "symfony/finder": ">=3.4" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.21 || ^9", - "squizlabs/php_codesniffer": ">=2.7" - }, - "bin": [ - "bin/swagger" - ], - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Swagger\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Robert Allen", - "email": "zircote@gmail.com", - "homepage": "http://www.zircote.com" - }, - { - "name": "Bob Fanger", - "email": "bfanger@gmail.com", - "homepage": "http://bfanger.nl" - } - ], - "description": "Swagger-PHP - Generate interactive documentation for your RESTful API using phpdoc annotations", - "homepage": "https://github.com/zircote/swagger-php/", - "keywords": [ - "api", - "json", - "rest", - "service discovery" - ], - "support": { - "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/2.1.13" - }, - "time": "2023-09-12T22:12:26+00:00" } ], "packages-dev": [ diff --git a/config/swagger.php b/config/swagger.php deleted file mode 100644 index 6ff3ee1e..00000000 --- a/config/swagger.php +++ /dev/null @@ -1,51 +0,0 @@ - storage_path() . '/docs', - - /* - |-------------------------------------------------------------------------- - | Absolute path to directory containing the swagger annotations are stored. - |-------------------------------------------------------------------------- - */ - "app-dir" => "/app/Http/", - - /* - |-------------------------------------------------------------------------- - | Absolute path to directories that you would like to exclude from swagger generation - |-------------------------------------------------------------------------- - */ - "excludes" => array( - storage_path(), - base_path() . "/tests", - base_path() . "/resources/views", - base_path() . "/config", - base_path() . "/vendor" - ), - - /* - |-------------------------------------------------------------------------- - | Turn this off to remove swagger generation on production - |-------------------------------------------------------------------------- - */ - "generateAlways" => true, - - /* - |-------------------------------------------------------------------------- - | Edit to trust the proxy's ip address - needed for AWS Load Balancer - |-------------------------------------------------------------------------- - */ - "behind-reverse-proxy" => true, - -); \ No newline at end of file diff --git a/resources/views/swagger/index.blade.php b/resources/views/swagger/index.blade.php deleted file mode 100644 index c0a5da3b..00000000 --- a/resources/views/swagger/index.blade.php +++ /dev/null @@ -1,85 +0,0 @@ -@extends('layouts.bare') - -@section('meta-title') - Hackspace Manchester API Docs -@stop - -@section('page-title') - Hackspace Manchester API Docs -@stop - -@section('content') - - - -
- -
 
-
-
- -@stop - -@section('footer-js') - - - - - - - - - - - - -@stop \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 6cb9ce47..4c864235 100755 --- a/routes/web.php +++ b/routes/web.php @@ -285,78 +285,3 @@ ########################## Route::get('logs', ['uses' => '\Rap2hpoutre\LaravelLogViewer\LogViewerController@index', 'middleware' => 'role:admin'])->name('logs'); - - - - - - -Route::any('api-docs.json', function () { - $filePath = Config::get('swagger.doc-dir') . "/api-docs.json"; - - if (!File::Exists($filePath)) { - App::abort(404, "Cannot find {$filePath}"); - } - - $content = File::get($filePath); - return Response::make($content, 200, array( - 'Content-Type' => 'application/json' - )); -}); - -Route::get('api-docs', function () { - if (Config::get('swagger.generateAlways')) { - $appDir = base_path() . "/" . Config::get('swagger.app-dir'); - $docDir = Config::get('swagger.doc-dir'); - - - if (!File::exists($docDir) || is_writable($docDir)) { - // delete all existing documentation - if (File::exists($docDir)) { - File::deleteDirectory($docDir); - } - - File::makeDirectory($docDir); - - $excludeDirs = Config::get('swagger.excludes'); - - $swagger = \Swagger\scan($appDir, [ - 'exclude' => $excludeDirs - ]); - - $filename = $docDir . '/api-docs.json'; - file_put_contents($filename, $swagger); - } - } - - if (Config::get('swagger.behind-reverse-proxy')) { - $proxy = Request::server('REMOTE_ADDR'); - Request::setTrustedProxies(array($proxy)); - } - - //need the / at the end to avoid CORS errors on Homestead systems. - $response = response()->view( - 'swagger.index', - array( - 'secure' => Request::secure(), - 'urlToDocs' => url('api-docs.json'), - 'requestHeaders' => Config::get('swagger.requestHeaders'), - 'clientId' => Input::get("client_id"), - 'clientSecret' => Input::get("client_secret"), - 'realm' => Input::get("realm"), - 'appName' => Input::get("appName"), - ) - ); - - //need the / at the end to avoid CORS errors on Homestead systems. - /*$response = Response::make( - View::make('swaggervel::index', array( - 'secure' => Request::secure(), - 'urlToDocs' => url('api-docs.json'), - 'requestHeaders' => Config::get('swaggervel.requestHeaders') ) - ), - 200 - );*/ - - return $response; -}); diff --git a/storage/docs/api-docs.json b/storage/docs/api-docs.json deleted file mode 100644 index e463fc70..00000000 --- a/storage/docs/api-docs.json +++ /dev/null @@ -1,208 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "title": "Hackspace Manchester API", - "version": "1" - }, - "paths": { - "/acs/activity": { - "post": { - "tags": [ - "activity" - ], - "summary": "Record the start of a new session", - "description": "Record the start of a period of activity, e.g. someone signing into the laser cutter. If an entry device is specified no equipment access record is started but an activity log is created", - "parameters": [ - { - "name": "activity", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Activity" - } - } - ], - "responses": { - "201": { - "description": "Activity started, the body will contain the new activityId" - }, - "404": { - "description": "Key fob not found" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/acs/activity/{activityId}": { - "put": { - "tags": [ - "activity" - ], - "summary": "Update an ongoing activity", - "description": "Record a heartbeat message for a period of activity, used to ensure activity periods are correctly recorded", - "parameters": [ - { - "name": "activityId", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "Activity Heartbeat recorded" - } - }, - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "tags": [ - "activity" - ], - "summary": "Show the form for creating a new resource.", - "description": "End a period of an activity", - "parameters": [ - { - "name": "activityId", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "204": { - "description": "Activity ended/deleted" - }, - "400": { - "description": "Session invalid" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/acs/node/boot": { - "post": { - "tags": [ - "acs" - ], - "summary": "Display a listing of the resource.", - "description": "Record a bootup/startup of an acs node", - "responses": { - "200": { - "description": "Boot recorded" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/acs/node/heartbeat": { - "post": { - "tags": [ - "acs" - ], - "summary": "Show the form for creating a new resource.", - "description": "Record a heartbeat message, used to determin if the device is online", - "responses": { - "200": { - "description": "Heartbeat recorded" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/acs/status/{tagId}": { - "get": { - "tags": [ - "acs" - ], - "summary": "Display the specified resource.", - "description": "Get information about a specific tag and its user, this doesn't generate any activity", - "consumes": [ - "application/json" - ], - "parameters": [ - { - "name": "tagId", - "in": "path", - "type": "string" - } - ], - "responses": { - "200": { - "description": "Tag found" - }, - "404": { - "description": "Tag not found" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/acs/test": { - "get": { - "tags": [ - "acs" - ], - "summary": "Display a listing of the resource.", - "description": "Returns an OK message, useful for verifying the api access token works", - "responses": { - "200": { - "description": "OK" - } - } - } - } - }, - "definitions": { - "Activity": { - "properties": { - "tagId": { - "description": "The RFID Tag ID, required", - "type": "string" - }, - "device": { - "description": "The Device ID of the device being controlled, required", - "type": "string" - }, - "occurredAt": { - "description": "Date Time of the event, UNIX timestamp, optional", - "type": "string" - } - }, - "xml": { - "name": "Activity" - } - } - }, - "securityDefinitions": { - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "header" - } - } -} \ No newline at end of file From 37aae547a89d6ee9b239214805cbd2e552b40437 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:03:35 +0100 Subject: [PATCH 03/13] Remove unused AccessControlController --- .../Controllers/AccessControlController.php | 131 ------------------ app/Services/BuildingAccess.php | 131 ------------------ routes/web.php | 7 - 3 files changed, 269 deletions(-) delete mode 100644 app/Http/Controllers/AccessControlController.php delete mode 100644 app/Services/BuildingAccess.php diff --git a/app/Http/Controllers/AccessControlController.php b/app/Http/Controllers/AccessControlController.php deleted file mode 100644 index 54b54cc2..00000000 --- a/app/Http/Controllers/AccessControlController.php +++ /dev/null @@ -1,131 +0,0 @@ -buildingAccess = $buildingAccess; - $this->acsNodeRepository = $acsNodeRepository; - } - - public function mainDoor() - { - $receivedData = trim(\Input::get('data')); - - //Log::debug("New System. Entry message received: ".$receivedData); - - //What access point is this? - $this->buildingAccess->setDeviceKey('main-door'); - - - try { - - //Decode the message and store the message parameters in the building access object - $this->buildingAccess->decodeDeviceCommand($receivedData); - - //Verify everything is good - $this->buildingAccess->validateData(); - - } catch (\BB\Exceptions\ValidationException $e) { - - Log::debug("Entry message received - failed: " . $receivedData); - - //The data was invalid or the user doesnt have access - $response = \Response::make(json_encode(['valid' => '0', 'msg' => $e->getMessage()]) . PHP_EOL, 200); - $response->headers->set('Content-Length', strlen($response->getContent())); - return $response; - } - - - //Is this a system message - if ($this->buildingAccess->isSystemMessage()) { - return $this->handleSystemMessage($receivedData); - } - - - $this->buildingAccess->logSuccess(); - - $userName = substr($this->buildingAccess->getUser()->given_name, 0, 20); - $responseBody = json_encode(['valid' => '1', 'msg' => $userName]); - - $response = \Response::make($responseBody . PHP_EOL, 200); - $response->headers->set('Content-Length', strlen($response->getContent())); - return $response; - } - - - public function status() - { - $keyId = \Input::get('data'); - try { - $keyFob = $this->lookupKeyFob($keyId); - } catch (\Exception $e) { - - return \Response::make(json_encode(['valid'=>'0']), 200); - } - $user = $keyFob->user()->first(); - - $log = new Activity(); - $log->key_fob_id = $keyFob->id; - $log->user_id = $user->id; - $log->service = 'status'; - $log->save(); - $statusString = $user->status; - return \Response::make(json_encode(['valid'=>'1', 'name'=>$user->name, 'status'=>$statusString]), 200); - } - - private function lookupKeyFob($keyId) - { - try { - $keyFob = KeyFob::lookup($keyId); - return $keyFob; - } catch (\Exception $e) { - $keyId = substr('BB' . $keyId, 0, 12); - $keyFob = KeyFob::lookup($keyId); - return $keyFob; - } - } - - /** - * @param string $receivedData - * @return \Illuminate\Http\Response - */ - public function handleSystemMessage($receivedData) - { - $receivedData = substr($receivedData, 1, strlen($receivedData)); - - $messageParts = ["", ""]; - if (strpos($receivedData, '|') !== false) { - $messageParts = explode('|', $receivedData); - } - - $device = $messageParts[0]; - $message = $messageParts[1]; - - if ($message == 'boot') { - $this->acsNodeRepository->logBoot($device); - } elseif ($message == 'heartbeat') { - $this->acsNodeRepository->logHeartbeat($device); - } - - //Log::debug("System Message: ".$receivedData); - - return \Response::make(PHP_EOL, 200); - } - -} \ No newline at end of file diff --git a/app/Services/BuildingAccess.php b/app/Services/BuildingAccess.php deleted file mode 100644 index 555f82e5..00000000 --- a/app/Services/BuildingAccess.php +++ /dev/null @@ -1,131 +0,0 @@ -setAccessTime(); - - if ($this->determinSystemMessage($receivedData)) { - - $this->systemMessage = true; - - $this->decodeSystemMessage($receivedData); - - } else { - - $this->decodeAccessRequest($receivedData); - - } - } - - /** - * @return boolean - */ - public function isSystemMessage() - { - return $this->systemMessage; - } - - - public function validateData() - { - //Verify the keyfob, device key and action - - //Validate the action - if ($this->isSystemMessage()) { - if ( ! in_array($this->action, $this->systemDeviceActions)) { - throw new ValidationException('Invalid Device Action'); - } - //Validate the device - if ( ! in_array($this->deviceKey, $this->devices)) { - throw new ValidationException('Invalid device key'); - } - - return; - } - - //Validate the action - if ( ! in_array($this->action, $this->deviceActions)) { - throw new ValidationException('Invalid Device Action'); - } - - //Validate the device - if ( ! in_array($this->deviceKey, $this->devices)) { - throw new ValidationException('Invalid device key'); - } - - //Validate the key fob - $this->keyFob = $this->lookupKeyFob($this->keyFobId); - - //Make sure the user is active - $this->user = $this->keyFob->user()->first(); - if ( ! $this->user || ! $this->user->active) { - $this->logFailure(); - throw new ValidationException('Not a member'); - } - - - } - - - private function determinSystemMessage($receivedData) - { - return strpos($receivedData, ':') === 0; - } - - private function decodeSystemMessage($receivedData) - { - //Remove the start : character - $receivedData = substr($receivedData, 1, strlen($receivedData)); - - //The system message consists of a device key and an action - if (strpos($receivedData, '|') === false) { - throw new ValidationException('Invalid System Message'); - } - $messageParts = explode('|', $receivedData); - - if (count($messageParts) !== 2) { - throw new ValidationException('Invalid System Message'); - } - $this->deviceKey = $messageParts[0]; - $this->action = $messageParts[1]; - } - - private function decodeAccessRequest($receivedData) - { - if (strpos($receivedData, '|') === false) { - //No separator character, just a key id - $this->keyFobId = $receivedData; - } else { - $keyParts = explode('|', $receivedData); - if (count($keyParts) !== 2) { - throw new ValidationException('Invalid System Message'); - } - $this->keyFobId = $keyParts[0]; - $this->action = $keyParts[1]; - if ($this->action === 'delayed') { - $this->messageDelayed = true; - } - } - } - -} \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 4c864235..99acb282 100755 --- a/routes/web.php +++ b/routes/web.php @@ -171,13 +171,6 @@ # Access Control & Devices ########################## -//Main Door -Route::post('access-control/main-door', ['uses' => 'AccessControlController@mainDoor']); - -//Status endpoint - testing - not in production -Route::post('access-control/status', ['uses' => 'AccessControlController@status']); -Route::get('access-control/status', ['uses' => 'AccessControlController@status']); - //Device control Route::post('access-control/device', ['uses' => 'DeviceAccessControlController@device']); From bf1e5b6a2aa2a3eb7e0ca6ccccb599e2ba21485f Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:11:59 +0100 Subject: [PATCH 04/13] Remove unused 'access-control/device' endpoint --- app/Entities/Activity.php | 1 + .../DeviceAccessControlController.php | 64 ------- app/Repo/EquipmentLogRepository.php | 1 + app/Services/DeviceSession.php | 164 ------------------ routes/web.php | 3 - 5 files changed, 2 insertions(+), 231 deletions(-) delete mode 100644 app/Http/Controllers/DeviceAccessControlController.php delete mode 100644 app/Services/DeviceSession.php diff --git a/app/Entities/Activity.php b/app/Entities/Activity.php index bed4e15f..565d9e7f 100644 --- a/app/Entities/Activity.php +++ b/app/Entities/Activity.php @@ -18,6 +18,7 @@ */ class Activity extends Model { + // TODO: Remove this, not used since 2022 /** * The database table used by the model. diff --git a/app/Http/Controllers/DeviceAccessControlController.php b/app/Http/Controllers/DeviceAccessControlController.php deleted file mode 100644 index 6f0d92ef..00000000 --- a/app/Http/Controllers/DeviceAccessControlController.php +++ /dev/null @@ -1,64 +0,0 @@ -activityRepository = $activityRepository; - $this->equipmentRepository = $equipmentRepository; - $this->equipmentLogRepository = $equipmentLogRepository; - $this->deviceSession = $deviceSession; - } - - public function device() - { - - //process and validate incoming data - - $receivedData = \Input::get('data'); - //Log::debug($receivedData); - - //Decode and validate the received command - try { - $this->deviceSession->decodeDeviceCommand($receivedData); - $this->deviceSession->validateData(); - } catch (\BB\Exceptions\ValidationException $e) { - Log::debug($e->getMessage()); - return \Response::make(json_encode(['valid'=>'0']), 200); - } - - - - //Process start, ping, end command - $this->deviceSession->processAction(); - - - return \Response::make(json_encode(['valid'=>'1', 'name'=>$this->deviceSession->getUser()->name]), 200); - } - -} \ No newline at end of file diff --git a/app/Repo/EquipmentLogRepository.php b/app/Repo/EquipmentLogRepository.php index c067b668..d9c97fe0 100644 --- a/app/Repo/EquipmentLogRepository.php +++ b/app/Repo/EquipmentLogRepository.php @@ -7,6 +7,7 @@ class EquipmentLogRepository extends DBRepository { + // TODO: Remove this, no usages in production. /** * @var EquipmentLog diff --git a/app/Services/DeviceSession.php b/app/Services/DeviceSession.php deleted file mode 100644 index dcd76bba..00000000 --- a/app/Services/DeviceSession.php +++ /dev/null @@ -1,164 +0,0 @@ -equipmentRepository = $equipmentRepository; - $this->inductionRepository = $inductionRepository; - $this->equipmentLogRepository = $equipmentLogRepository; - $this->bbCredit = $bbCredit; - $this->activityRepository = $activityRepository; - } - - - public function validateData() - { - //Verify the keyfob, device key and action - - //Validate the action - if ( ! in_array($this->action, $this->deviceActions)) { - throw new ValidationException('Invalid Device Action'); - } - //Validate the device - try { - $this->device = $this->equipmentRepository->findBySlug($this->deviceKey); - } catch (ModelNotFoundException $e) { - throw new ValidationException('Invalid Device Key'); - } - //Confirm the device is working - if ( ! $this->device->working) { - throw new ValidationException('Device Not Working'); - } - //Validate the key fob - $this->keyFob = $this->lookupKeyFob($this->keyFobId); - - //Make sure the user is active - $this->user = $this->keyFob->user()->first(); - if ( ! $this->user || ! $this->user->active) { - throw new ValidationException('User Invalid'); - } - - //Make sure the user is allowed to use the device - if ($this->device->requires_induction) { - //Verify the user has training - if ( ! $this->inductionRepository->isUserTrained($this->user->id, $this->deviceKey)) { - throw new ValidationException('User Not Trained'); - } - } - - - //Make sure the member has enough money on their account - $minimumBalance = $this->bbCredit->acceptableNegativeBalance('equipment-fee'); - if (($this->user->cash_balance + ($minimumBalance * 100)) <= 0) { - throw new ValidationException('User doesn\'t have enough credit'); - } - - } - - public function decodeDeviceCommand($receivedData) - { - $dataPacket = explode('|', $receivedData); - if (count($dataPacket) != 3) { - throw new ValidationException('Invalid Device String'); - } - - $this->keyFobId = trim(strtolower($dataPacket[0])); - $this->deviceKey = trim(strtolower($dataPacket[1])); - $this->action = trim(strtolower($dataPacket[2])); - } - - - public function processAction() - { - if ($this->action == 'start') { - $this->processStartAction(); - } elseif ($this->action == 'ping') { - $this->processPingAction(); - } elseif ($this->action == 'end') { - $this->processEndAction(); - } - } - - private function processStartAction() - { - $this->equipmentLogRepository->recordStartCloseExisting($this->user->id, $this->keyFob->id, $this->deviceKey); - - //Create a general entry in the activity log - //$this->activityRepository->recordMemberActivity($this->user->id, $this->keyFob->id, $this->deviceKey); - event(new MemberActivity($this->keyFob, $this->deviceKey)); - } - - private function processPingAction() - { - $sessionId = $this->equipmentLogRepository->findActiveUserSession($this->user->id, $this->deviceKey); - if ($sessionId !== false) { - $this->equipmentLogRepository->recordActivity($sessionId); - } else { - //We don't have an active session, there could have been a network failure so start now - $this->equipmentLogRepository->recordStartCloseExisting($this->user->id, $this->keyFob->id, $this->deviceKey, 'inaccurate start'); - } - } - - private function processEndAction() - { - //Close the session - $sessionId = $this->equipmentLogRepository->findActiveUserSession($this->user->id, $this->deviceKey); - if ($sessionId !== false) { - $this->equipmentLogRepository->endSession($sessionId); - } else { - $sessionId = $this->equipmentLogRepository->recordStartCloseExisting($this->user->id, $this->keyFob->id, $this->deviceKey, 'inaccurate start'); - $this->equipmentLogRepository->endSession($sessionId); - } - } - - -} \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 99acb282..8aa839e2 100755 --- a/routes/web.php +++ b/routes/web.php @@ -171,9 +171,6 @@ # Access Control & Devices ########################## -//Device control -Route::post('access-control/device', ['uses' => 'DeviceAccessControlController@device']); - //New ACS System Route::post('acs', ['uses' => 'ACSController@store']); //Route::get('acs', ['uses' => 'ACSController@get']); From dc5117fdd15e0bcdc815c9653a943c62736405c2 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:41:08 +0100 Subject: [PATCH 05/13] Remove unused ACSController --- app/Http/Controllers/ACSController.php | 198 ------------------------- app/Validators/ACSValidator.php | 17 --- routes/web.php | 4 - 3 files changed, 219 deletions(-) delete mode 100644 app/Http/Controllers/ACSController.php delete mode 100644 app/Validators/ACSValidator.php diff --git a/app/Http/Controllers/ACSController.php b/app/Http/Controllers/ACSController.php deleted file mode 100644 index aabba650..00000000 --- a/app/Http/Controllers/ACSController.php +++ /dev/null @@ -1,198 +0,0 @@ -acsNodeRepository = $acsNodeRepository; - $this->ACSValidator = $ACSValidator; - $this->keyFobAccess = $keyFobAccess; - $this->equipmentLogRepository = $equipmentLogRepository; - } - - public function store() - { - $data = \Request::only('device', 'service', 'message', 'tag', 'time', 'payload', 'signature', 'nonce', 'session_id'); - - //device = the node id from the acs table - unique to each acs - //service = what the request is for, entry, usage, consumable - //message = system message, heartbeat, boot - //tag = the keyfob id - //time = the time of the action - //payload = any extra data relavent to the request - //signature = an encoded value generated using a secret key - oauth style - //nonce = a unique value suitable to stop replay attacks - //session_id = the id of the current session the user is maintaining - - $this->ACSValidator->validate($data); - - - //System messages - if (in_array($data['message'], ['boot', 'heartbeat'])) { - return $this->handleSystemCheckIn($data['message'], $data['device'], $data['service']); - } - - - switch ($data['service']) { - case 'entry': - return $this->handleDoor($data); - case 'usage': - return $this->handleDevice($data); - case 'consumable': - - break; - case 'shop': - - break; - case 'status': - return $this->handleStatus($data); - - break; - default: - Log::debug(json_encode($data)); - } - - } - - private function handleStatus($data) - { - try { - /** @var User $user */ - $user = $this->keyFobAccess->verifyForEntry($data['tag'], 'main-door', $data['time']); - } catch (\Exception $e) { - return $this->sendResponse(404, []); - } - - return $this->sendResponse(200, ['member' => $user->given_name]); - } - - private function handleDoor($data) - { - //Door entry is quite simple - this will just deal with lookups - - try { - /** @var User $user */ - $user = $this->keyFobAccess->verifyForEntry($data['tag'], 'main-door', $data['time']); - $this->keyFobAccess->logSuccess(); - } catch (\Exception $e) { - return $this->sendResponse(404, []); - } - - return $this->sendResponse(200, ['member' => $user->given_name]); - } - - - private function handleDevice($data) - { - $sessionId = null; - try { - $device = ACSNode::where('device_id', $data['device'])->firstOrFail(); - if ($device->entry_device) { - return $this->sendResponse(400, ['message' => 'This is an entry device only']); - } else { - $member = $this->keyFobAccess->verifyForDevice($data['tag'], $data['device'], $data['time']); - $keyFob = $this->keyFobAccess->getKeyFob(); - - if ($data['message'] == 'start') { - $sessionId = $this->equipmentLogRepository->recordStartCloseExisting($keyFob->user->id, $keyFob->id, $data['device']); - event(new MemberActivity($keyFob, $data['device'])); - } elseif ($data['message'] == 'stop') { - if (empty($data['session_id'])) { - $data['session_id'] = $this->equipmentLogRepository->findActiveUserSession($keyFob->user->id, $data['device']); - } - if (empty($data['session_id'])) { - return $this->sendResponse(404, ['message' => 'No active session to close']); - } - $this->equipmentLogRepository->endSession($data['session_id']); - } - } - } catch (ValidationException $e) { - return $this->sendResponse(400, ['message' => $e->getMessage()]); - } - return $this->sendResponse(200, ['member' => $member->given_name, 'session_id' => $sessionId]); - } - - /** - * System checkins are common across all devices - * Record the time and return pending status messages - * - * @param $message - * @param $device - * @return Response - */ - private function handleSystemCheckIn($message, $device, $service) - { - switch ($message) { - case 'boot': - $this->acsNodeRepository->logBoot($device); - break; - case 'heartbeat': - $this->acsNodeRepository->logHeartbeat($device); - break; - } - - //The command comes from the database and will instruct the door entry system to clear its memory if set - $cmd = $this->acsNodeRepository->popCommand($device); - - switch ($service) { - case 'entry': - //we don't have a system for this at the moment but could have a global shutdown option - $deviceStatus = '1'; - break; - case 'usage': - //lookup the piece of equipment from the device id and get the status - $deviceStatus = '1'; - break; - default: - $deviceStatus = '1'; - } - - $responseData = ['cmd' => $cmd, 'deviceStatus' => $deviceStatus]; - - return $this->sendResponse(200, $responseData); - } - - /** - * Json encode the response data and return - * - * @param int $statusCode - * @param array $responseData - * - * @return \Response - */ - private function sendResponse($statusCode = 200, array $responseData) - { - $responseData['time'] = time(); - $response = response()->json($responseData, $statusCode); - $response->headers->set('Content-Length', strlen($response->getContent())); - return $response; - } - -} diff --git a/app/Validators/ACSValidator.php b/app/Validators/ACSValidator.php deleted file mode 100644 index a7fc66c8..00000000 --- a/app/Validators/ACSValidator.php +++ /dev/null @@ -1,17 +0,0 @@ - 'required|max:25|exists:acs_nodes,device_id', - 'service' => 'required|in:entry,usage,consumable,shop,status,sensor', - 'message' => 'required|in:boot,heartbeat,lookup,start,stop,charge,error,update', - 'session_id' => '', - 'tag' => 'max:15', - 'time' => 'integer|date_format:U', - 'signature' => '', - 'nonce' => 'max:12', - ]; - -} diff --git a/routes/web.php b/routes/web.php index 8aa839e2..2659656d 100755 --- a/routes/web.php +++ b/routes/web.php @@ -171,10 +171,6 @@ # Access Control & Devices ########################## -//New ACS System -Route::post('acs', ['uses' => 'ACSController@store']); -//Route::get('acs', ['uses' => 'ACSController@get']); - //spark core - printer charges Route::post('acs/spark', ['uses' => 'ACSSparkController@handle']); From 230dfa070a32a373b17f9cbc79523daa44d778d4 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:42:19 +0100 Subject: [PATCH 06/13] Remove unused ACSSparkController --- app/Http/Controllers/ACSSparkController.php | 50 --------------------- routes/web.php | 3 -- 2 files changed, 53 deletions(-) delete mode 100644 app/Http/Controllers/ACSSparkController.php diff --git a/app/Http/Controllers/ACSSparkController.php b/app/Http/Controllers/ACSSparkController.php deleted file mode 100644 index ad4b7c31..00000000 --- a/app/Http/Controllers/ACSSparkController.php +++ /dev/null @@ -1,50 +0,0 @@ -acsNodeRepository = $acsNodeRepository; - $this->keyFobAccess = $keyFobAccess; - $this->paymentRepository = $paymentRepository; - } - - public function handle() - { - $data = \Request::only(['device', 'tag', 'service']); - - try { - $keyFob = $this->keyFobAccess->lookupKeyFob($data['tag']); - } catch (\Exception $e) { - Log::debug(json_encode($data)); - return \Response::make('Not found', 404); - } - $user = $keyFob->user()->first(); - - $this->paymentRepository->recordPayment($data['service'], $user->id, 'balance', null, 0.05, 'paid', 0, $data['device']); - - event(new MemberActivity($keyFob, $data['service'])); - - return \Response::make('OK', 201); - } -} \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 2659656d..b45c30cb 100755 --- a/routes/web.php +++ b/routes/web.php @@ -171,9 +171,6 @@ # Access Control & Devices ########################## -//spark core - printer charges -Route::post('acs/spark', ['uses' => 'ACSSparkController@handle']); - Route::group(array('middleware' => 'role:acs'), function () { Route::resource('devices', 'DeviceController'); }); From 08cc2f7f448637b2cc392e8b47eb5bdefaf23de4 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:46:53 +0100 Subject: [PATCH 07/13] Remove DeviceController --- app/Http/Controllers/DeviceController.php | 85 ------------------- resources/views/devices/create.blade.php | 29 ------- resources/views/devices/form.blade.php | 44 ---------- resources/views/devices/index-row.blade.php | 13 --- resources/views/devices/index.blade.php | 41 --------- .../views/partials/main-sidenav.blade.php | 4 - routes/web.php | 4 - tests/DevicesTest.php | 24 ------ 8 files changed, 244 deletions(-) delete mode 100644 app/Http/Controllers/DeviceController.php delete mode 100644 resources/views/devices/create.blade.php delete mode 100644 resources/views/devices/form.blade.php delete mode 100644 resources/views/devices/index-row.blade.php delete mode 100644 resources/views/devices/index.blade.php delete mode 100644 tests/DevicesTest.php diff --git a/app/Http/Controllers/DeviceController.php b/app/Http/Controllers/DeviceController.php deleted file mode 100644 index da94a683..00000000 --- a/app/Http/Controllers/DeviceController.php +++ /dev/null @@ -1,85 +0,0 @@ - $devices]); - } - - public function create() - { - return view('devices.create'); - } - - public function store() - { - $data = \Request::only([ - 'name', 'device_id', 'api_key', 'entry_device', - ]); - - ACSNode::create($data); - - return \Redirect::route('devices.index'); - } - - /** - * Display the specified resource. - * - * @param int $id - * @return Response - */ - public function show($id) - { - // - } - - /** - * Show the form for editing the specified resource. - * - * @param int $id - * @return Response - */ - public function edit($id) - { - // - } - - /** - * Update the specified resource in storage. - * - * @param int $id - * @return Response - */ - public function update($id) - { - // - } - - /** - * Remove the specified resource from storage. - * - * @param int $id - * @return Response - */ - public function destroy($id) - { - $device = ACSNode::findOrFail($id); - $device->delete(); - - return \Redirect::route('devices.index'); - } -} diff --git a/resources/views/devices/create.blade.php b/resources/views/devices/create.blade.php deleted file mode 100644 index 10d20d99..00000000 --- a/resources/views/devices/create.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -@extends('layouts.main') - -@section('meta-title') - Setup a new device -@stop - -@section('page-title') - Setup a new device -@stop - -@section('content') - -
- - {!! Form::open(array('route' => 'devices.store', 'class'=>'form-horizontal', 'files'=>true)) !!} - - @include('devices/form') - -
-
- {!! Form::submit('Save', array('class'=>'btn btn-primary')) !!} -
-
- - {!! Form::close() !!} - -
- -@stop diff --git a/resources/views/devices/form.blade.php b/resources/views/devices/form.blade.php deleted file mode 100644 index 90cecc49..00000000 --- a/resources/views/devices/form.blade.php +++ /dev/null @@ -1,44 +0,0 @@ - -
- {!! Form::label('name', 'Name', ['class'=>'col-sm-3 control-label']) !!} -
- {!! Form::text('name', null, ['class'=>'form-control']) !!} -

An optional display name.

- {!! FlashNotification::getErrorDetail('name') !!} -
-
- -
- {!! Form::label('device_id', 'Device ID', ['class'=>'col-sm-3 control-label']) !!} -
- {!! Form::text('device_id', null, ['class'=>'form-control']) !!} -

A device ID - Used in the api requests to identify the device being controlled

- {!! FlashNotification::getErrorDetail('device_id') !!} -
-
- -
- {!! Form::label('api_key', 'API Key', ['class'=>'col-sm-3 control-label']) !!} -
- {!! Form::text('api_key', null, ['class'=>'form-control']) !!} -

The key you will use to identify yourself when making requests.

- {!! FlashNotification::getErrorDetail('api_key') !!} -
-
- -
- {!! Form::label('monitor_heartbeat', 'Monitor device uptime?', ['class'=>'col-sm-3 control-label']) !!} -
- {!! Form::select('monitor_heartbeat', [0 => 'No', 1 => 'Yes'], null, ['class'=>'form-control']) !!} -

If the device fails to check-in for over an hour an alter will be raised.

- {!! FlashNotification::getErrorDetail('monitor_heartbeat') !!} -
-
-
- {!! Form::label('entry_device', 'Is this a door or other entry device?', ['class'=>'col-sm-3 control-label']) !!} -
- {!! Form::select('entry_device', [0 => 'No', 1 => 'Yes'], null, ['class'=>'form-control']) !!} -

Entry devices wont start a period of activity

- {!! FlashNotification::getErrorDetail('entry_device') !!} -
-
diff --git a/resources/views/devices/index-row.blade.php b/resources/views/devices/index-row.blade.php deleted file mode 100644 index 9cce6c42..00000000 --- a/resources/views/devices/index-row.blade.php +++ /dev/null @@ -1,13 +0,0 @@ -heartbeatWarning()) class="danger" @endif> - {{ $device->name }} - {{ $device->device_id }} - {{ $device->api_key }} - {{ $device->entry_device? 'Yes': '' }} - {{ ($device->last_heartbeat) ? \Carbon\Carbon::now()->diffForHumans($device->last_heartbeat, true) . ' ago': 'never' }} - {{ ($device->last_boot) ? \Carbon\Carbon::now()->diffForHumans($device->last_boot, true) . ' ago': 'never' }} - - {!! Form::open(array('method' => 'DELETE', 'route' => ['devices.destroy', $device->id], 'class'=>'form-horizontal', 'files'=>true)) !!} - {!! Form::submit('Delete', array('class'=>'btn btn-primary', 'onclick'=>'return confirm("Are you sure?")')) !!} - {!! Form::close() !!} - - diff --git a/resources/views/devices/index.blade.php b/resources/views/devices/index.blade.php deleted file mode 100644 index 347fe016..00000000 --- a/resources/views/devices/index.blade.php +++ /dev/null @@ -1,41 +0,0 @@ -@extends('layouts.main') - -@section('meta-title') - Devices -@stop - -@section('page-title') - Devices -@stop - -@section('page-action-buttons') - @if (!Auth::guest() && Auth::user()->hasRole('acs')) - Setup a new device - @endif -@stop - -@section('content') - - - - - - - - - - - - - - - - @each('devices.index-row', $devices, 'device') - -
NameDevice IDAPI KeyEntry DeviceLast HeartbeatLast Boot
- -

- API Docs -

- -@stop diff --git a/resources/views/partials/main-sidenav.blade.php b/resources/views/partials/main-sidenav.blade.php index 81d07654..474e714b 100644 --- a/resources/views/partials/main-sidenav.blade.php +++ b/resources/views/partials/main-sidenav.blade.php @@ -193,10 +193,6 @@ {!! HTML::sideNavLink('💌 Newsletter', 'newsletter') !!} @endif - @if (Auth::user()->hasRole('acs') || Auth::user()->isAdmin()) - {!! HTML::sideNavLink('🔑 Devices', 'devices.index') !!} - @endif - @if (Auth::user()->hasRole('finance') || Auth::user()->isAdmin()) {!! HTML::sideNavLink('💰 Payments', 'payments.index') !!} @endif diff --git a/routes/web.php b/routes/web.php index b45c30cb..6574402a 100755 --- a/routes/web.php +++ b/routes/web.php @@ -171,10 +171,6 @@ # Access Control & Devices ########################## -Route::group(array('middleware' => 'role:acs'), function () { - Route::resource('devices', 'DeviceController'); -}); - //New ACES Endpoint Route::get('acs/test', ['uses' => 'ACS\TestController@index', 'middleware' => 'acs']); Route::get('acs/status/{tagId}', ['uses' => 'ACS\StatusController@show', 'middleware' => 'acs']); diff --git a/tests/DevicesTest.php b/tests/DevicesTest.php deleted file mode 100644 index 78ceeb59..00000000 --- a/tests/DevicesTest.php +++ /dev/null @@ -1,24 +0,0 @@ -create(); - $this->withoutMiddleware() - ->visit('/devices') - ->see('Devices') - ->see($device->name); - } - - -} \ No newline at end of file From 22251d6fc6097901e694f319f6863d3f17b754fc Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:47:28 +0100 Subject: [PATCH 08/13] Remove 'acs/test' endpoint --- app/Http/Controllers/ACS/TestController.php | 36 ----------------- database/factories/ModelFactory.php | 11 ------ routes/web.php | 1 - tests/ACS/MiddlewareTest.php | 43 --------------------- tests/ACS/NodeTest.php | 32 --------------- 5 files changed, 123 deletions(-) delete mode 100644 app/Http/Controllers/ACS/TestController.php delete mode 100644 tests/ACS/MiddlewareTest.php delete mode 100644 tests/ACS/NodeTest.php diff --git a/app/Http/Controllers/ACS/TestController.php b/app/Http/Controllers/ACS/TestController.php deleted file mode 100644 index 6d90e517..00000000 --- a/app/Http/Controllers/ACS/TestController.php +++ /dev/null @@ -1,36 +0,0 @@ -define('BB\Entities\ACSNode', function ($faker) { - return [ - 'name' => $faker->word, - 'device_id' => $faker->word, - 'queued_command' => null, - 'monitor_heartbeat' => false, - 'api_key' => $faker->word, - 'entry_device' => false, - ]; -}); - $factory->define('BB\Entities\Role', function ($faker) { return [ 'name' => $faker->word, diff --git a/routes/web.php b/routes/web.php index 6574402a..1ece35cb 100755 --- a/routes/web.php +++ b/routes/web.php @@ -172,7 +172,6 @@ ########################## //New ACES Endpoint -Route::get('acs/test', ['uses' => 'ACS\TestController@index', 'middleware' => 'acs']); Route::get('acs/status/{tagId}', ['uses' => 'ACS\StatusController@show', 'middleware' => 'acs']); Route::post('acs/node/boot', ['uses' => 'ACS\NodeController@boot', 'middleware' => 'acs']); Route::post('acs/node/heartbeat', ['uses' => 'ACS\NodeController@heartbeat', 'middleware' => 'acs']); diff --git a/tests/ACS/MiddlewareTest.php b/tests/ACS/MiddlewareTest.php deleted file mode 100644 index d2305ede..00000000 --- a/tests/ACS/MiddlewareTest.php +++ /dev/null @@ -1,43 +0,0 @@ -withoutMiddleware(); - - $this->get('/acs/test', ['Accept' => 'application/json']); - - $this->seeStatusCode(200); - } - - /** - * @test - */ - public function invalid_api_key_returns_403() - { - $this->get('/acs/test', ['Accept' => 'application/json', 'ApiKey' => 'invalidkey']); - - $this->seeStatusCode(403); - } - - /** - * @test - */ - public function valid_api_key_returns_200() - { - $node = factory('BB\Entities\ACSNode')->create(); - $this->get('/acs/test', ['Accept' => 'application/json', 'ApiKey' => $node->api_key]); - - $this->seeStatusCode(200); - } -} diff --git a/tests/ACS/NodeTest.php b/tests/ACS/NodeTest.php deleted file mode 100644 index 5bf98c42..00000000 --- a/tests/ACS/NodeTest.php +++ /dev/null @@ -1,32 +0,0 @@ -create(); - //echo $node->id; - - $this->assertNull($node->last_boot); - - //$this->post('/acs/node/boot', ['Accept' => 'application/json', 'ApiKey' => $node->api_key]); - //$this->seeStatusCode(200); - - //$nodeUpdated = \BB\Entities\ACSNode::where('api_key', $node->api_key)->first(); - - //dd($nodeUpdated); - //echo $nodeUpdated->id; - //$this->assertNotNull($nodeUpdated->last_boot); - } -} From 65c4817db3b8663f02c7ab2ae5e043e85eb563ba Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:50:10 +0100 Subject: [PATCH 09/13] Remove 'acs/status' endpoint --- app/Http/Controllers/ACS/StatusController.php | 69 ------------------- routes/web.php | 1 - tests/ACS/StatusTest.php | 53 -------------- 3 files changed, 123 deletions(-) delete mode 100644 app/Http/Controllers/ACS/StatusController.php delete mode 100644 tests/ACS/StatusTest.php diff --git a/app/Http/Controllers/ACS/StatusController.php b/app/Http/Controllers/ACS/StatusController.php deleted file mode 100644 index b9939ff3..00000000 --- a/app/Http/Controllers/ACS/StatusController.php +++ /dev/null @@ -1,69 +0,0 @@ - [ - 'id' => $keyFob->user->id, - 'name' => $keyFob->user->name, - 'status' => $keyFob->user->status, - 'active' => $keyFob->user->active, - 'key_holder' => $keyFob->user->key_holder, - 'cash_balance' => $keyFob->user->cash_balance, - 'profile_private' => $keyFob->user->profile_private, - ]]; - } - -} diff --git a/routes/web.php b/routes/web.php index 1ece35cb..68761651 100755 --- a/routes/web.php +++ b/routes/web.php @@ -172,7 +172,6 @@ ########################## //New ACES Endpoint -Route::get('acs/status/{tagId}', ['uses' => 'ACS\StatusController@show', 'middleware' => 'acs']); Route::post('acs/node/boot', ['uses' => 'ACS\NodeController@boot', 'middleware' => 'acs']); Route::post('acs/node/heartbeat', ['uses' => 'ACS\NodeController@heartbeat', 'middleware' => 'acs']); diff --git a/tests/ACS/StatusTest.php b/tests/ACS/StatusTest.php deleted file mode 100644 index 788ffeed..00000000 --- a/tests/ACS/StatusTest.php +++ /dev/null @@ -1,53 +0,0 @@ -create(); - $tag = factory('BB\Entities\KeyFob')->create(['user_id' => $user->id]); - $this->get('/acs/status/' . $tag->key_id, ['Accept' => 'application/json']); - $this->assertResponseStatus(200); - $this->seeJson(['name' => $user->name]); - } - - /** - * @test - */ - public function status_endpoint_returns_details_for_partial_key_fob() - { - $user = factory('BB\Entities\User')->create(); - $tag = factory('BB\Entities\KeyFob')->create(['user_id' => $user->id]); - - $keyFob = substr($tag->key_id, 0, 10); - $keyFob{0} = 0; - - //Confirm the partial keyfob is in fact a partial keyfob - $this->assertEquals('0', substr($keyFob, 0, 1)); - $this->assertEquals(10, strlen($keyFob)); - - $this->get('/acs/status/' . $keyFob, ['Accept' => 'application/json']); - $this->assertResponseStatus(200); - $this->seeJson(['name' => $user->name]); - } - - /** - * @test - */ - public function status_endpoint_returns_404_for_invalid_key_fob() - { - $this->get('/acs/status/' . str_random(12), ['Accept' => 'application/json']); - $this->assertResponseStatus(404); - } -} From e7f8d2884246e151f5733ff6cd151352868af512 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 15:52:04 +0100 Subject: [PATCH 10/13] Remove 'acs/node' endpoints --- app/Http/Controllers/ACS/NodeController.php | 65 --------------------- routes/web.php | 4 -- 2 files changed, 69 deletions(-) delete mode 100644 app/Http/Controllers/ACS/NodeController.php diff --git a/app/Http/Controllers/ACS/NodeController.php b/app/Http/Controllers/ACS/NodeController.php deleted file mode 100644 index 31ed5844..00000000 --- a/app/Http/Controllers/ACS/NodeController.php +++ /dev/null @@ -1,65 +0,0 @@ -ACSNodeRepository = $ACSNodeRepository; - } - - /** - * Display a listing of the resource. - * - * @return \Illuminate\Http\Response - * - * @SWG\Post( - * path="/acs/node/boot", - * tags={"acs"}, - * description="Record a bootup/startup of an acs node", - * @SWG\Response(response="200", description="Boot recorded"), - * security={{"api_key": {}}} - * ) - */ - public function boot(Request $request) - { - $node = $this->ACSNodeRepository->findByAPIKey($request->header('ApiKey')); - $this->ACSNodeRepository->logBoot($node->device_id); - } - - /** - * Show the form for creating a new resource. - * - * @return \Illuminate\Http\Response - * - * @SWG\Post( - * path="/acs/node/heartbeat", - * tags={"acs"}, - * description="Record a heartbeat message, used to determin if the device is online", - * @SWG\Response(response="200", description="Heartbeat recorded"), - * security={{"api_key": {}}} - * ) - */ - public function heartbeat(Request $request) - { - $node = $this->ACSNodeRepository->findByAPIKey($request->header('ApiKey')); - $this->ACSNodeRepository->logHeartbeat($node->device_id); - } - -} diff --git a/routes/web.php b/routes/web.php index 68761651..a7f160a0 100755 --- a/routes/web.php +++ b/routes/web.php @@ -171,10 +171,6 @@ # Access Control & Devices ########################## -//New ACES Endpoint -Route::post('acs/node/boot', ['uses' => 'ACS\NodeController@boot', 'middleware' => 'acs']); -Route::post('acs/node/heartbeat', ['uses' => 'ACS\NodeController@heartbeat', 'middleware' => 'acs']); - Route::post('acs/activity', ['uses' => 'ACS\ActivityController@store', 'middleware' => 'acs']); Route::put('acs/activity/{sessionId}', ['uses' => 'ACS\ActivityController@update', 'middleware' => 'acs']); Route::delete('acs/activity/{sessionId}', ['uses' => 'ACS\ActivityController@destroy', 'middleware' => 'acs']); From 70f670752ca429f01ac14f243d482534d7a4ff8e Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Sun, 9 Jun 2024 16:13:48 +0100 Subject: [PATCH 11/13] Remove 'Activity' tracking --- ACSDocs.md | 39 --- app/Entities/ACSNode.php | 57 ---- app/Entities/Activity.php | 51 --- app/Entities/Equipment.php | 10 - app/Entities/KeyFob.php | 19 -- app/Entities/Settings.php | 2 - app/Events/MemberActivity.php | 56 --- app/Events/MemberActivityRecorded.php | 64 ---- .../Controllers/ACS/ActivityController.php | 135 -------- app/Http/Controllers/ActivityController.php | 72 ---- app/Http/Controllers/StatsController.php | 21 -- app/Http/Kernel.php | 3 - app/Http/Middleware/ACSAuthentication.php | 47 --- app/Http/Middleware/ACSSessionControl.php | 43 --- app/Http/Requests/ACS/Activity.php | 61 ---- .../Equipment/StoreEquipmentRequest.php | 2 +- app/Listeners/RecordMemberActivity.php | 41 --- app/Providers/EventServiceProvider.php | 4 - app/Providers/NotificationServiceProvider.php | 5 - app/Providers/ObserverServiceProvider.php | 2 - app/Repo/ACSNodeRepository.php | 102 ------ app/Repo/ActivityRepository.php | 101 ------ app/Repo/EquipmentLogRepository.php | 120 ------- app/Repo/EquipmentRepository.php | 10 - app/Services/KeyFobAccess.php | 319 ------------------ .../2024_06_09_151204_remove_activity.php | 36 ++ .../2024_06_09_151210_remove_acs_node.php | 39 +++ resources/assets/js/SiteInteraction.js | 17 - resources/assets/less/application.less | 1 - resources/assets/less/memberActivity.less | 29 -- resources/views/activity/index.blade.php | 87 ----- resources/views/activity/realtime.blade.php | 20 -- resources/views/admin.blade.php | 7 - resources/views/equipment/show.blade.php | 51 --- routes/web.php | 19 -- 35 files changed, 76 insertions(+), 1616 deletions(-) delete mode 100644 ACSDocs.md delete mode 100644 app/Entities/ACSNode.php delete mode 100644 app/Entities/Activity.php delete mode 100644 app/Events/MemberActivity.php delete mode 100644 app/Events/MemberActivityRecorded.php delete mode 100644 app/Http/Controllers/ACS/ActivityController.php delete mode 100644 app/Http/Controllers/ActivityController.php delete mode 100644 app/Http/Middleware/ACSAuthentication.php delete mode 100644 app/Http/Middleware/ACSSessionControl.php delete mode 100644 app/Http/Requests/ACS/Activity.php delete mode 100644 app/Listeners/RecordMemberActivity.php delete mode 100644 app/Repo/ACSNodeRepository.php delete mode 100644 app/Repo/ActivityRepository.php delete mode 100644 app/Services/KeyFobAccess.php create mode 100644 database/migrations/2024_06_09_151204_remove_activity.php create mode 100644 database/migrations/2024_06_09_151210_remove_acs_node.php delete mode 100644 resources/assets/less/memberActivity.less delete mode 100644 resources/views/activity/index.blade.php delete mode 100644 resources/views/activity/realtime.blade.php diff --git a/ACSDocs.md b/ACSDocs.md deleted file mode 100644 index ebcc6ea4..00000000 --- a/ACSDocs.md +++ /dev/null @@ -1,39 +0,0 @@ -This api is incomplete and only supports some basic functions. -It was intended to work with hardware with few resources which is why there is one endpoint and some of the fields and messages are very terse. - -To use it a valid device id needs to be supplied - -__Request__ - - POST members.hacman.org.uk/acs - -Field | Required | Value ---------- | -------- | ----- -device | yes | The id specific to the current ACS device -service | yes | entry, usage, consumable, shop, status, device-scanner, sensor -message | yes | boot, heartbeat, lookup, start, stop, charge, error, update -tag | yes* | RFID Tag Number, needed for lookup, start, stop, charge -time | | Unix timestamp -signature | | -nonce | | - - -__Response__ - -_200_ - -``` -{ - "vaild": "1", - "cmd": "Bearer", - "member": 7200, - "time": 01234567890 -} -``` - -Field | Value ------- | ----- -valid | Did the request match a real user, used for lookup, start, stop and charge messages -cmd | Any commands being passed down to the acs device, i.e. purge, disable, etc... -member | A display name for the current member if any -time | The current unix timestamp, useful for setting internal clocks \ No newline at end of file diff --git a/app/Entities/ACSNode.php b/app/Entities/ACSNode.php deleted file mode 100644 index 01146989..00000000 --- a/app/Entities/ACSNode.php +++ /dev/null @@ -1,57 +0,0 @@ -monitor_heartbeat && ($this->last_heartbeat < Carbon::now()->subHour())) { - return true; - } - - return false; - } - -} diff --git a/app/Entities/Activity.php b/app/Entities/Activity.php deleted file mode 100644 index 565d9e7f..00000000 --- a/app/Entities/Activity.php +++ /dev/null @@ -1,51 +0,0 @@ -belongsTo('\BB\Entities\User'); - } - - public function keyFob() - { - return $this->belongsTo('\BB\Entities\KeyFob'); - } - -} \ No newline at end of file diff --git a/app/Entities/Equipment.php b/app/Entities/Equipment.php index 2810675d..7f45a4c8 100644 --- a/app/Entities/Equipment.php +++ b/app/Entities/Equipment.php @@ -108,16 +108,6 @@ public function role() return $this->belongsTo('\BB\Entities\Role', 'managing_role_id'); } - /** - * Does the equipment have activity recorded against it - * - * @return bool - */ - public function hasActivity() - { - return !empty($this->device_key); - } - /** * Does the equipment need an induction to use it * diff --git a/app/Entities/KeyFob.php b/app/Entities/KeyFob.php index 228e301c..6cc6696a 100644 --- a/app/Entities/KeyFob.php +++ b/app/Entities/KeyFob.php @@ -48,23 +48,4 @@ public function scopeActive($query) { return $query->whereActive(true); } - - public static function lookup($fobId) - { - $record = self::where('key_id', '=', strtoupper($fobId))->active()->first(); - if ( ! $record) { - throw new ModelNotFoundException; - } - return $record; - } - - public static function lookupPartialTag($fobId) - { - $record = self::where('key_id', 'LIKE', '%' . strtoupper($fobId) . '%')->active()->first(); - if ( ! $record) { - throw new ModelNotFoundException; - } - return $record; - } - } \ No newline at end of file diff --git a/app/Entities/Settings.php b/app/Entities/Settings.php index ca609e28..2a314ed3 100644 --- a/app/Entities/Settings.php +++ b/app/Entities/Settings.php @@ -4,8 +4,6 @@ use Illuminate\Database\Eloquent\Model; /** - * Class Activity - * * @property integer $id * @property integer $key_fob_id * @property integer $user_id diff --git a/app/Events/MemberActivity.php b/app/Events/MemberActivity.php deleted file mode 100644 index 8def49a5..00000000 --- a/app/Events/MemberActivity.php +++ /dev/null @@ -1,56 +0,0 @@ -keyFob = $keyFob; - $this->service = $service; - $this->date = $date; - $this->delayed = $delayed; - } - - /** - * Get the channels the event should be broadcast on. - * - * @return array - */ - public function broadcastOn() - { - return []; - } -} diff --git a/app/Events/MemberActivityRecorded.php b/app/Events/MemberActivityRecorded.php deleted file mode 100644 index 06f9106f..00000000 --- a/app/Events/MemberActivityRecorded.php +++ /dev/null @@ -1,64 +0,0 @@ -activity = $activity; - } - - /** - * Get the channels the event should be broadcast on. - * - * @return array - */ - public function broadcastOn() - { - return ['activity']; - } - - /** - * @return array - */ - public function broadcastWith() - { - $data = [ - 'activity' => [ - 'id' => $this->activity->id, - 'service' => $this->activity->service, - 'response' => $this->activity->response, - 'key_fob_id' => $this->activity->key_fob_id, - 'time' => $this->activity->created_at->toTimeString(), - ] - ]; - if ($this->activity->user) { - $data['user'] = [ - 'id' => $this->activity->user->id, - 'name' => $this->activity->user->name, - 'hash' => $this->activity->user->hash, - ]; - } - - return $data; - } -} diff --git a/app/Http/Controllers/ACS/ActivityController.php b/app/Http/Controllers/ACS/ActivityController.php deleted file mode 100644 index b7b03bb9..00000000 --- a/app/Http/Controllers/ACS/ActivityController.php +++ /dev/null @@ -1,135 +0,0 @@ -ACSNodeRepository = $ACSNodeRepository; - $this->equipmentLogRepository = $equipmentLogRepository; - $this->fobAccess = $fobAccess; - } - - /** - * Record the start of a new session - * - * @return \Illuminate\Http\Response - * - * @SWG\Post( - * path="/acs/activity", - * tags={"activity"}, - * description="Record the start of a period of activity, e.g. someone signing into the laser cutter. If an entry device is specified no equipment access record is started but an activity log is created", - * @SWG\Parameter(name="activity", in="body", required=true, @SWG\Schema(ref="#/definitions/Activity")), - * @SWG\Response(response="201", description="Activity started, the body will contain the new activityId"), - * @SWG\Response(response="404", description="Key fob not found"), - * security={{"api_key": {}}} - * ) - */ - public function store(Request $request) - { - $activityRequest = new Requests\ACS\Activity($request); - - $keyFob = $this->fobAccess->extendedKeyFobLookup($activityRequest->getTagId()); - - // lookup the acs node - $node = ACSNode::where('device_id', $activityRequest->getDevice())->firstOrFail(); - if ($node->entry_device) { - $this->fobAccess->verifyForEntry($activityRequest->getTagId(), $activityRequest->getDevice(), $activityRequest->getOccurredAt()); - $this->fobAccess->logSuccess(); - } else { - $activityId = $this->equipmentLogRepository->recordStartCloseExisting($keyFob->user->id, $keyFob->id, $activityRequest->getDevice()); - event(new MemberActivity($keyFob, $activityRequest->getDevice())); - } - - - - return response()->json([ - 'activityId' => isset($activityId)? $activityId: null, - 'user' => [ - 'id' => $keyFob->user->id, - 'name' => $keyFob->user->name, - 'status' => $keyFob->user->status, - 'active' => $keyFob->user->active, - 'key_holder' => $keyFob->user->key_holder, - 'cash_balance' => $keyFob->user->cash_balance, - 'profile_private' => $keyFob->user->profile_private, - ] - ], 201); - } - - /** - * Update an ongoing activity - * - * @return \Illuminate\Http\Response - * - * @SWG\Put( - * path="/acs/activity/{activityId}", - * tags={"activity"}, - * description="Record a heartbeat message for a period of activity, used to ensure activity periods are correctly recorded", - * @SWG\Parameter(name="activityId", in="path", type="string", required=true), - * @SWG\Response(response="200", description="Activity Heartbeat recorded"), - * security={{"api_key": {}}} - * ) - */ - public function update(Request $request, $activityId) - { - $keyFob = $this->fobAccess->extendedKeyFobLookup($request->get('tagId')); - - $this->equipmentLogRepository->recordActivity($activityId); - - return response()->json([], 200); - } - - /** - * Show the form for creating a new resource. - * - * @return \Illuminate\Http\Response - * - * @SWG\Delete( - * path="/acs/activity/{activityId}", - * tags={"activity"}, - * description="End a period of an activity", - * @SWG\Parameter(name="activityId", in="path", type="string", required=true), - * @SWG\Response(response="204", description="Activity ended/deleted"), - * @SWG\Response(response="400", description="Session invalid"), - * security={{"api_key": {}}} - * ) - */ - public function destroy(Request $request, $activityId) - { - $keyFob = $this->fobAccess->extendedKeyFobLookup($request->get('tagId')); - - $this->equipmentLogRepository->endSession($activityId); - - return response()->json([], 204); - } - -} diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php deleted file mode 100644 index a01dcd0e..00000000 --- a/app/Http/Controllers/ActivityController.php +++ /dev/null @@ -1,72 +0,0 @@ -activityRepository = $activityRepository; - } - - /** - * Display a listing of the resource. - * - * @return Response - */ - public function index() - { - $date = \Input::get('date', \Carbon\Carbon::now()->format('Y-m-d')); - $date = \Carbon\Carbon::createFromFormat('Y-m-d', $date)->setTime(0, 0, 0); - $today = \Carbon\Carbon::now()->setTime(0, 0, 0); - $doorPin = \Input::get('doorPin'); - - $logEntries = $this->activityRepository->getForDate($date); - - $nextDate = null; - if ($date->lt($today)) { - $nextDate = $date->copy()->addDay(); - } - $previousDate = $date->copy()->subDay(); - - - - return \View::make('activity.index') - ->with('logEntries', $logEntries) - ->with('date', $date) - ->with('nextDate', $nextDate) - ->with('previousDate', $previousDate) - ->with('doorPin', $doorPin); - } - - public function create() - { - $keyFob = Auth::user()->keyFob(); - event(new MemberActivity($keyFob, 'main-door', Carbon::now(), true)); - - $doorPin = Settings::get('emergency_door_key_storage_pin'); - - return redirect(route('activity.index', ['doorPin' => $doorPin])); - } - - - /** - * @return Response - */ - public function realtime() - { - return \View::make('activity.realtime'); - } - - - -} diff --git a/app/Http/Controllers/StatsController.php b/app/Http/Controllers/StatsController.php index 3c1186d8..c27d08da 100644 --- a/app/Http/Controllers/StatsController.php +++ b/app/Http/Controllers/StatsController.php @@ -9,17 +9,14 @@ class StatsController extends Controller protected $layout = 'layouts.main'; private $userRepository; - private $activityRepository; private $statRepository; function __construct( \BB\Repo\UserRepository $userRepository, - \BB\Repo\ActivityRepository $activityRepository, \BB\Repo\StatRepository $statRepository ) { $this->userRepository = $userRepository; - $this->activityRepository = $activityRepository; $this->statRepository = $statRepository; } @@ -152,22 +149,6 @@ public function index() //Number of Users $numMembers = count($users); - - //door access logs - $logEntrys = $this->activityRepository->activeUsersForPeriod(\Carbon\Carbon::now()->subMonth(), \Carbon\Carbon::now()); - $userArray = []; - foreach ($logEntrys as $entry) { - $userArray[] = $entry->user_id; - } - $numActiveUsers = count(array_unique($userArray)); - - $logEntrys = $this->activityRepository->activeUsersForPeriod(\Carbon\Carbon::now()->subMonths(3), \Carbon\Carbon::now()); - $userArray = []; - foreach ($logEntrys as $entry) { - $userArray[] = $entry->user_id; - } - $numActiveUsersQuarter = count(array_unique($userArray)); - return \View::make('stats.index') ->with('user', $user) ->with('expectedIncome', $expectedIncome) @@ -181,8 +162,6 @@ public function index() ->with('numMembers', $numMembers) ->with('recommendedPayment', $recommendedPayment) ->with('payingRecommendedOrAbove', $payingRecommendedOrAbove) - ->with('numActiveUsers', $numActiveUsers) - ->with('numActiveUsersQuarter', $numActiveUsersQuarter) ->with('paymentMethods', $paymentMethods) ->with('monthlyAmountsData', $monthlyAmountsData); } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 78570026..bbeab78b 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -31,8 +31,6 @@ class Kernel extends HttpKernel */ protected $middlewareGroups = [ 'web' => [ - \BB\Http\Middleware\ACSSessionControl::class, - \BB\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, @@ -65,7 +63,6 @@ class Kernel extends HttpKernel 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'role' => \BB\Http\Middleware\HasRole::class, 'trusted' => \BB\Http\Middleware\IsTrusted::class, - 'acs' => \BB\Http\Middleware\ACSAuthentication::class, ]; /** diff --git a/app/Http/Middleware/ACSAuthentication.php b/app/Http/Middleware/ACSAuthentication.php deleted file mode 100644 index 093d136b..00000000 --- a/app/Http/Middleware/ACSAuthentication.php +++ /dev/null @@ -1,47 +0,0 @@ -ACSNodeRepository = $ACSNodeRepository; - } - - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * - * @return mixed - * @throws AuthenticationException - */ - public function handle($request, Closure $next) - { - try { - $node = $this->ACSNodeRepository->findByAPIKey($request->header('ApiKey')); - } catch (\Exception $e) { - throw new AuthenticationException("API Key Invalid"); - } - - //Possibly do some checking here on the access rights for the acs node - - return $next($request); - } -} diff --git a/app/Http/Middleware/ACSSessionControl.php b/app/Http/Middleware/ACSSessionControl.php deleted file mode 100644 index a7630157..00000000 --- a/app/Http/Middleware/ACSSessionControl.php +++ /dev/null @@ -1,43 +0,0 @@ -app = $app; - } - - /** - * Disable sessions for requests to the acs endpoint - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @return mixed - */ - public function handle($request, Closure $next) - { - - if ((strpos($request->path(), 'access-control/') === 0) || ($request->path() === 'acs') || ($request->path() === 'acs/spark')) { - $this->app['config']->set('session.driver', 'array'); - } - - - return $next($request); - } -} diff --git a/app/Http/Requests/ACS/Activity.php b/app/Http/Requests/ACS/Activity.php deleted file mode 100644 index 95c04af1..00000000 --- a/app/Http/Requests/ACS/Activity.php +++ /dev/null @@ -1,61 +0,0 @@ -tagId = $request->get('tagId'); - $this->device = $request->get('device'); - $this->occurredAt = $request->get('occurredAt'); - } - - /** - * @return string - */ - public function getTagId() - { - return $this->tagId; - } - - /** - * @return string - */ - public function getDevice() - { - return $this->device; - } - - /** - * @return string - */ - public function getOccurredAt() - { - return $this->occurredAt; - } -} diff --git a/app/Http/Requests/Equipment/StoreEquipmentRequest.php b/app/Http/Requests/Equipment/StoreEquipmentRequest.php index e439bf16..641d19f9 100644 --- a/app/Http/Requests/Equipment/StoreEquipmentRequest.php +++ b/app/Http/Requests/Equipment/StoreEquipmentRequest.php @@ -32,7 +32,7 @@ public function rules() 'room' => 'required', 'detail' => '', 'slug' => 'required|alpha_dash|unique:equipment,slug', - 'device_key' => 'exists:acs_nodes,device_id', + 'device_key' => '', 'description' => '', 'help_text' => '', 'managing_role_id' => 'exists:roles,id', diff --git a/app/Listeners/RecordMemberActivity.php b/app/Listeners/RecordMemberActivity.php deleted file mode 100644 index 3d07867e..00000000 --- a/app/Listeners/RecordMemberActivity.php +++ /dev/null @@ -1,41 +0,0 @@ -activityRepository = $activityRepository; - } - - /** - * Handle the event. - * - * @param MemberActivity $event - */ - public function handle(MemberActivity $event) - { - $activity = $this->activityRepository->recordMemberActivity($event->keyFob->user->id, $event->keyFob->id, $event->service, $event->date); - - //The old door entry system may send over historical records, make sure these are marked as such - if ($event->delayed) { - $activity->delayed = true; - $activity->save(); - } - } -} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 809cf8ac..8db0e153 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -15,7 +15,6 @@ use BB\Listeners\Notifications\Inductions\InductionCompletedListener; use BB\Listeners\Notifications\Inductions\InductionMarkedAsTrainerListener; use BB\Listeners\Notifications\Inductions\InductionRequestedListener; -use BB\Listeners\RecordMemberActivity; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider @@ -50,9 +49,6 @@ class EventServiceProvider extends ServiceProvider 'BB\Events\MemberPhotoWasDeclined' => [ EmailMemberAboutDeclinedPhoto::class, ], - 'BB\Events\MemberActivity' => [ - RecordMemberActivity::class, - ], 'BB\Events\MemberGivenTrustedStatus' => [ EmailMemberAboutTrustedStatus::class ], diff --git a/app/Providers/NotificationServiceProvider.php b/app/Providers/NotificationServiceProvider.php index 170c8e3a..edda9580 100644 --- a/app/Providers/NotificationServiceProvider.php +++ b/app/Providers/NotificationServiceProvider.php @@ -2,11 +2,6 @@ namespace BB\Providers; -use BB\Entities\Activity; -use BB\Entities\User; -use BB\Observer\ActivityObserver; -use BB\Observer\UserAuditObserver; -use BB\Observer\UserObserver; use Illuminate\Support\ServiceProvider; /** diff --git a/app/Providers/ObserverServiceProvider.php b/app/Providers/ObserverServiceProvider.php index a210cae8..16a9beec 100644 --- a/app/Providers/ObserverServiceProvider.php +++ b/app/Providers/ObserverServiceProvider.php @@ -2,9 +2,7 @@ namespace BB\Providers; -use BB\Entities\Activity; use BB\Entities\User; -use BB\Observer\ActivityObserver; use BB\Observer\UserAuditObserver; use BB\Observer\UserObserver; use Illuminate\Support\ServiceProvider; diff --git a/app/Repo/ACSNodeRepository.php b/app/Repo/ACSNodeRepository.php deleted file mode 100644 index 3443a46d..00000000 --- a/app/Repo/ACSNodeRepository.php +++ /dev/null @@ -1,102 +0,0 @@ -model = $model; - } - - /** - * Fetch a record by name - * - * @param $device - * @return mixed - */ - public function getByName($device) - { - $record = $this->model->where('device_id', $device)->first(); - if ( ! $record) { - throw new ModelNotFoundException(); - } - return $record; - } - - /** - * @param $apiKey - * - * @return ACSNode - */ - public function findByAPIKey($apiKey) - { - if (empty($apiKey)) { - throw new ModelNotFoundException(); - } - $node = $this->model->where('api_key', $apiKey)->first(); - if (!$node) { - throw new ModelNotFoundException(); - } - return $node; - } - - /** - * @param $device string - */ - public function logBoot($device) - { - $record = $this->model->where('device_id', $device)->first(); - if (!$record) { - $record = $this->createRecord($device); - } - $record->last_boot = Carbon::now(); - $record->save(); - } - - /** - * @param $device string - */ - public function logHeartbeat($device) - { - $record = $this->model->where('device_id', $device)->first(); - if ( ! $record) { - $record = $this->createRecord($device); - } - $record->last_heartbeat = Carbon::now(); - $record->save(); - } - - /** - * @param $device string - * @return mixed - */ - private function createRecord($device) - { - $record = new $this->model(); - $record->device_id = $device; - $record->save(); - return $record; - } - - public function popCommand($device) - { - $record = $this->model->where('device_id', $device)->first(); - $commandToSend = null; - if ($record) { - $commands = explode(',', $record->queued_command); - $commandToSend = array_shift($commands); - $record->queued_command = implode(',', $commands); - $record->save(); - } - return $commandToSend; - } -} \ No newline at end of file diff --git a/app/Repo/ActivityRepository.php b/app/Repo/ActivityRepository.php deleted file mode 100644 index 8ea26a5c..00000000 --- a/app/Repo/ActivityRepository.php +++ /dev/null @@ -1,101 +0,0 @@ -model = $model; - } - - /** - * Fetch all entries for a particular date - * - * @param \DateTime $startDate - * @return mixed - */ - public function getForDate(\DateTime $startDate) - { - $startDate = $startDate->setTime(0, 0, 0); - $endDate = $startDate->copy()->addDay(); - - return $this->model->with('user', 'user.profile')->where('created_at', '>', $startDate) - ->where('created_at', '<', $endDate) - ->where('response', '200') - ->orderBy('created_at', 'desc') - ->get(); - } - - - /** - * Record an access attempt - * - * @param array $data - * @return Activity - */ - public function logAccessAttempt($data) - { - return $this->model->create($data); - } - - - /** - * @param \DateTime $startDate - * @param \DateTime $endDate - * @return mixed - */ - public function activeUsersForPeriod(\DateTime $startDate, \DateTime $endDate) - { - $startDate = $startDate->setTime(0, 0, 0); - $endDate = $endDate->setTime(23, 59, 59); - - return $this->model - ->where('created_at', '>', $startDate) - ->where('created_at', '<', $endDate) - ->where('service', 'main-door') - ->where('response', '200') - ->orderBy('created_at', 'desc') - ->get(); - } - - /** - * Record a generic activity entry for the user - * - * @param integer $userId - * @param integer $keyFobId - * @param string $deviceKey - * @param Carbon $time - * @return Activity - */ - public function recordMemberActivity($userId, $keyFobId, $deviceKey, Carbon $time = null) - { - if (empty($time)) { - $time = Carbon::now(); - } - $activity = $this->model->create([ - 'user_id' => $userId, - 'key_fob_id' => $keyFobId, - 'service' => $deviceKey, - 'response' => 200, - 'created_at' => $time - ]); - - if ($activity) { - event(new MemberActivityRecorded($activity)); - } - - return $activity; - } - - -} \ No newline at end of file diff --git a/app/Repo/EquipmentLogRepository.php b/app/Repo/EquipmentLogRepository.php index d9c97fe0..667015a2 100644 --- a/app/Repo/EquipmentLogRepository.php +++ b/app/Repo/EquipmentLogRepository.php @@ -20,117 +20,6 @@ public function __construct(EquipmentLog $model) $this->perPage = 25; } - /** - * Record the start of device activity - * @param integer $userId - * @param integer $keyFobId - * @param string $deviceKey - * @param string $notes - * @return integer - */ - public function recordStart($userId, $keyFobId, $deviceKey, $notes = '') - { - $session = new $this->model; - $session->user_id = $userId; - $session->key_fob_id = $keyFobId; - $session->device = $deviceKey; - $session->active = 1; - $session->started = Carbon::now(); - $session->notes = $notes; - $session->save(); - return $session->id; - } - - - /** - * Record a device start but close any existing user sessions first - * @param integer $userId - * @param integer $keyFobId - * @param string $deviceKey - * @param string $notes - * @return integer - */ - public function recordStartCloseExisting($userId, $keyFobId, $deviceKey, $notes = '') - { - $existingSessionId = $this->findActiveDeviceSession($deviceKey); - if ($existingSessionId !== false) { - $this->endSession($existingSessionId); - } - return $this->recordStart($userId, $keyFobId, $deviceKey, $notes); - } - - /** - * Locate a users active session - * @param integer $userId - * @param string $deviceKey - * @return integer|false - */ - public function findActiveUserSession($userId, $deviceKey) - { - $existingSession = $this->model->where('user_id', $userId)->where('device', $deviceKey)->where('active', 1)->orderBy('created_at', 'DESC')->first(); - if ($existingSession) { - return $existingSession->id; - } - return false; - } - - - /** - * Return an existing active session for the device, if any - * @param $deviceKey - * @return integer|false - */ - public function findActiveDeviceSession($deviceKey) - { - $existingSession = $this->model->where('device', $deviceKey)->where('active', 1)->orderBy('created_at', 'DESC')->first(); - if ($existingSession) { - return $existingSession->id; - } - return false; - } - - /** - * Record some activity on an existing session - * @param integer $sessionId - */ - public function recordActivity($sessionId) - { - $existingSession = $this->model->findOrFail($sessionId); - if ($existingSession->finished) { - throw new DeviceException(400, "Session already finished"); - } - $existingSession->last_update = Carbon::now(); - $existingSession->save(); - } - - /** - * Record the end of a session - * @param integer $sessionId - * @param \DateTime $finishedDate - */ - public function endSession($sessionId, $finishedDate = null) - { - $existingSession = $this->model->findOrFail($sessionId); - if ($finishedDate === null) { - $finishedDate = Carbon::now(); - } - if ($existingSession->finished) { - throw new DeviceException(400, "Session already finished"); - } - $existingSession->finished = $finishedDate; - $existingSession->active = 0; - $existingSession->save(); - } - - /** - * @param $deviceKey - * @return \Illuminate\Database\Eloquent\Collection - */ - public function getAllForEquipment($deviceKey) - { - return $this->model->where('device', $deviceKey)->orderBy('created_at', 'DESC')->get(); - } - /** * Return records that have been checked over * @param $deviceKey @@ -173,15 +62,6 @@ public function getTotalTime($deviceKey, $billedTime = null, $reason = null) return (int) ($totalTime / 60); } - /** - * Return all records that are currently listed as active - * @return \Illuminate\Database\Eloquent\Collection - */ - public function getActiveRecords() - { - return $this->model->where('active', true)->orderBy('created_at', 'DESC')->get(); - } - /** * Return all records that have been checked over but not billed * @return \Illuminate\Database\Eloquent\Collection diff --git a/app/Repo/EquipmentRepository.php b/app/Repo/EquipmentRepository.php index c2193773..e976bdea 100644 --- a/app/Repo/EquipmentRepository.php +++ b/app/Repo/EquipmentRepository.php @@ -57,16 +57,6 @@ public function findBySlug($slug) throw new ModelNotFoundException(); } - /** - * Return a device by its slug - * @param $slug - * @return Equipment - */ - public function findByDeviceKey($device) - { - return $this->model->where('device_key', $device)->firstOrFail(); - } - /** * @param $induction_category * @return Collection diff --git a/app/Services/KeyFobAccess.php b/app/Services/KeyFobAccess.php deleted file mode 100644 index 4662fbdf..00000000 --- a/app/Services/KeyFobAccess.php +++ /dev/null @@ -1,319 +0,0 @@ -activityRepository = $activityRepository; - $this->equipmentRepository = $equipmentRepository; - $this->inductionRepository = $inductionRepository; - $this->bbCredit = $bbCredit; - } - - - /** - * @param string $keyFobId - */ - public function setKeyFobId($keyFobId) - { - $this->keyFobId = $keyFobId; - } - - /** - * @param string $deviceKey - */ - public function setDeviceKey($deviceKey) - { - $this->deviceKey = $deviceKey; - } - - /** - * @param string $action - */ - public function setAction($action) - { - $this->action = $action; - } - - /** - * @return string - */ - public function getKeyFobId() - { - return $this->keyFobId; - } - - /** - * @return - */ - public function getKeyFob() - { - return $this->keyFob; - } - - /** - * @return string - */ - public function getDeviceKey() - { - return $this->deviceKey; - } - - /** - * @return string - */ - public function getAction() - { - return $this->action; - } - - /** - * @return User - */ - public function getUser() - { - return $this->user; - } - - /** - * Check a fob id is valid for door entry and return the member if it is - * @param $keyId - * @param string $doorName - * @param $time - * @return \User - * @throws ValidationException - */ - public function verifyForEntry($keyId, $doorName, $time) - { - $this->keyFob = $this->lookupKeyFob($keyId); - - $this->setAccessTime($time); - - //Make sure the user is active - $this->user = $this->keyFob->user; - if ( ! $this->user || ! $this->user->active) { - $this->logFailure(); - throw new ValidationException('Not a member'); - } - - $this->memberName = $this->user->given_name; - - - //Fetch any commands that need to be returned to the device - - return $this->keyFob->user; - } - - - public function verifyForDevice($keyId, $device, $time) - { - $this->keyFob = $this->lookupKeyFob($keyId); - $this->setAccessTime($time); - - //Make sure the user is active - $this->user = $this->keyFob->user; - if ( ! $this->user || ! $this->user->active) { - $this->logFailure(); - throw new ValidationException('Not a member'); - } - - //Validate the device - try { - /** @var Equipment $equipment */ - $equipment = $this->equipmentRepository->findByDeviceKey($device); - } catch (ModelNotFoundException $e) { - throw new ValidationException('Invalid Device Key'); - } - - //Make sure the user is allowed to use the device - if ($equipment->requires_induction) { - //Verify the user has training - if ( ! $this->inductionRepository->isUserTrained($this->user->id, $equipment->slug)) { - throw new ValidationException('User Not Trained'); - } - } - - - //Make sure the member has enough money on their account - $minimumBalance = $this->bbCredit->acceptableNegativeBalance('equipment-fee'); - if (($this->user->cash_balance + ($minimumBalance * 100)) <= 0) { - throw new ValidationException('User doesn\'t have enough credit'); - } - - return $this->user; - } - - public function lookupKeyFob($keyId) - { - try { - $keyFob = KeyFob::lookup($keyId); - return $keyFob; - } catch (\Exception $e) { - $keyId = substr('BB' . $keyId, 0, 12); - try { - $keyFob = KeyFob::lookup($keyId); - } catch (\Exception $e) { - throw new ValidationException('Key fob ID not valid'); - } - return $keyFob; - } - } - - - /** - * @param $keyId - * - * @return KeyFob - */ - public function extendedKeyFobLookup($keyId) - { - try { - $keyFob = KeyFob::lookup($keyId); - } catch (\Exception $e) { - $oldTagId = substr('BB' . $keyId, 0, 12); - try { - $keyFob = KeyFob::lookup($oldTagId); - } catch (\Exception $e) { - - //The ids coming in will have no checksum (last 2 digits) and the first digit will be incorrect - - //Remove the first character - $keyId = substr($keyId, 1); - - try { - $keyFob = KeyFob::lookupPartialTag($keyId); - } catch (\Exception $e) { - throw new ModelNotFoundException('Key fob ID not found'); - } - } - } - return $keyFob; - } - - public function logFailure() - { - $log = []; - $log['key_fob_id'] = $this->keyFob->id; - $log['user_id'] = $this->user->id; - $log['service'] = 'main-door'; - $log['delayed'] = $this->messageDelayed; - $log['response'] = 402; - $log['created_at'] = $this->time; - $this->activityRepository->logAccessAttempt($log); - - } - - public function logSuccess() - { - event(new MemberActivity($this->keyFob, 'main-door', $this->time, $this->messageDelayed)); - - /* - $activity = $this->activityRepository->recordMemberActivity($this->user->id, $this->keyFob->id, 'main-door', $this->time); - - if ($this->messageDelayed) { - $activity->delayed = true; - $activity->save(); - } - */ - } - - /** - * @return mixed - */ - public function getMemberName() - { - return $this->memberName; - } - - /** - * Set the time to a specific timestamp - the new entry system will be passing a local time with the requests - * @param null $time - */ - protected function setAccessTime($time = null) - { - if ( ! empty($time)) { - $this->time = Carbon::createFromTimestamp($time); - $this->messageDelayed = true; - } else { - $this->time = Carbon::now(); - } - } - -} diff --git a/database/migrations/2024_06_09_151204_remove_activity.php b/database/migrations/2024_06_09_151204_remove_activity.php new file mode 100644 index 00000000..9b428ce7 --- /dev/null +++ b/database/migrations/2024_06_09_151204_remove_activity.php @@ -0,0 +1,36 @@ +increments('id'); + $table->integer('user_id'); + $table->integer('key_fob_id'); + $table->string('response', 5); //Status code + $table->string('service', 50); + $table->boolean('delayed'); + $table->timestamps(); + }); + } +} diff --git a/database/migrations/2024_06_09_151210_remove_acs_node.php b/database/migrations/2024_06_09_151210_remove_acs_node.php new file mode 100644 index 00000000..4eddfdeb --- /dev/null +++ b/database/migrations/2024_06_09_151210_remove_acs_node.php @@ -0,0 +1,39 @@ +increments('id'); + $table->string('name', 100); + $table->string('device_id', 30); + $table->string('queued_command', 100)->nullable(); + $table->boolean('monitor_heartbeat'); + $table->boolean('entry_device')->default(null); + $table->string('api_key')->nullable(); + $table->dateTime('last_boot')->nullable(); + $table->dateTime('last_heartbeat')->nullable(); + $table->timestamps(); + }); + } +} diff --git a/resources/assets/js/SiteInteraction.js b/resources/assets/js/SiteInteraction.js index f5dfc066..2855d772 100644 --- a/resources/assets/js/SiteInteraction.js +++ b/resources/assets/js/SiteInteraction.js @@ -55,23 +55,6 @@ class SiteInteraction { jQuery(this).hide(); }); - - //Input date picker - /* - jQuery('.js-date-select').datepicker({ - format: "yyyy-mm-dd", - autoclose: true, - todayHighlight: true - }); - - - //Activity page - Date picker, auto form submit - jQuery('#activityDatePicker').find('.js-date-select').datepicker() - .on('changeDate', function(e) { - jQuery('#activityDatePicker').submit(); - }); - */ - console.log("Site Interaction Loaded"); } diff --git a/resources/assets/less/application.less b/resources/assets/less/application.less index 2d277192..a5e7477f 100644 --- a/resources/assets/less/application.less +++ b/resources/assets/less/application.less @@ -60,7 +60,6 @@ //Page specific styles @import "memberIndex.less"; -@import "memberActivity.less"; @import "memberPage.less"; @import "snackBar.less"; @import "equipment.less"; diff --git a/resources/assets/less/memberActivity.less b/resources/assets/less/memberActivity.less deleted file mode 100644 index 81decea5..00000000 --- a/resources/assets/less/memberActivity.less +++ /dev/null @@ -1,29 +0,0 @@ -.memberActivityGrid { - text-align: center; - a:hover { - text-decoration: none; - } - - .activityBlock { - background-color: @brand-primary; - margin-bottom: 20px; - border: 1px solid @gray-lightest; - - .profilePhoto { - min-width: 125px; - width: 100%; - height: 100%; - } - .activityDetails { - margin: 10px 5px; - height: 60px; - color: white; - } - a { - color: white; - &:hover { - text-decoration: none; - } - } - } -} \ No newline at end of file diff --git a/resources/views/activity/index.blade.php b/resources/views/activity/index.blade.php deleted file mode 100644 index 605ead8f..00000000 --- a/resources/views/activity/index.blade.php +++ /dev/null @@ -1,87 +0,0 @@ -@extends('layouts.main') - -@section('meta-title') -Activity Log -@stop - -@section('page-title') -Activity Log -@stop - -@section('content') - - - -
-
- @foreach ($logEntries as $logEntry) -
-
- - {!! HTML::memberPhoto($logEntry->user->profile, $logEntry->user->hash, 200) !!} - -
- {{ $logEntry->user->name }}
- {{ $logEntry->service }}
- @if ($logEntry->delayed) - (delayed) - @else - {{ $logEntry->created_at->toTimeString() }} - @endif -
- -
-
- @endforeach -
-
- -@stop diff --git a/resources/views/activity/realtime.blade.php b/resources/views/activity/realtime.blade.php deleted file mode 100644 index 4ef3fea1..00000000 --- a/resources/views/activity/realtime.blade.php +++ /dev/null @@ -1,20 +0,0 @@ -@extends('layouts.main') - -@section('meta-title') -Realtime Activity Log -@stop - -@section('page-title') -Realtime Activity Log -@stop - -@section('content') - -

Door Access

-
-
- -
-
- -@stop \ No newline at end of file diff --git a/resources/views/admin.blade.php b/resources/views/admin.blade.php index a0422ff3..7ec7fce7 100644 --- a/resources/views/admin.blade.php +++ b/resources/views/admin.blade.php @@ -38,13 +38,6 @@
  • Subscription Charges
  • -
    -

    Activity

    - -
    @stop diff --git a/resources/views/equipment/show.blade.php b/resources/views/equipment/show.blade.php index cd354404..a0eaf5fc 100644 --- a/resources/views/equipment/show.blade.php +++ b/resources/views/equipment/show.blade.php @@ -448,57 +448,6 @@ - - @if ($equipment->hasActivity()) -

    Activity Log

    - - - - - - - - @can('update', $equipment) - - @endcan - - - - - - - - - @foreach($equipmentLog as $log) - - - - - - @can('update', $equipment) - - @endcan - - @endforeach - -
    DateUsed forMemberReason
    - Total times in minutes: - Billed: {{ number_format($usageTimes['billed']) }} | - Unbilled: {{ number_format($usageTimes['unbilled']) }} | - Training: {{ number_format($usageTimes['training']) }} | - Testing: {{ number_format($usageTimes['testing']) }} -
    {{ $log->present()->started }}{{ $log->present()->timeUsed }}{{ $log->user->name }}{{ $log->present()->reason }} - @if (empty($log->reason)) - {!! Form::open(['method'=>'POST', 'route'=>['equipment_log.update', $log->id], 'name'=>'equipmentLog']) !!} - {!! Form::select('reason', ['testing'=>'Testing', 'training'=>'Training'], $log->reason, ['class'=>'']) !!} - {!! Form::submit('Update', ['class'=>'btn btn-primary btn-xs']) !!} - {!! Form::close() !!} - @endif -
    - - @endif @can('delete', $equipment) -
    - {!! Form::label('device_key', 'Device Key', ['class'=>'col-sm-3 control-label']) !!} -
    - {!! Form::text('device_key', null, ['class'=>'form-control']) !!} -

    The id of a ACS device already setup in the database

    - @if($errors->has('device_key')) - - @foreach($errors->get('device_key') as $error) -
  • {{ $error }}
  • - @endforeach -
    - @endif -
    -
    - {{-- Allow anybody to set on creation, but only admins/trainers to edit --}}
    {!! Form::label('obtained_at', 'Date Obtained', ['class'=>'col-sm-3 control-label']) !!}