Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
D
Doorcode
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
5
Issues
5
List
Boards
Labels
Service Desk
Milestones
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Guardians of the Kretschmar Elock System
Doorcode
Commits
42f65df0
Commit
42f65df0
authored
May 21, 2020
by
Jacob Priddy
👌
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '69-add-door-controller-update-route' into 'master'
Resolve "Add door controller update route" Closes
#69
See merge request
!59
parents
2b779212
50b21281
Pipeline
#9791
canceled with stages
in 2 minutes and 14 seconds
Changes
19
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
571 additions
and
0 deletions
+571
-0
src/backend/app/Http/Controllers/DoorController.php
src/backend/app/Http/Controllers/DoorController.php
+18
-0
src/backend/app/Providers/AppServiceProvider.php
src/backend/app/Providers/AppServiceProvider.php
+4
-0
src/backend/config/filesystems.php
src/backend/config/filesystems.php
+2
-0
src/backend/routes/door.php
src/backend/routes/door.php
+2
-0
src/backend/src/Gateways/Filesystem/FilesystemRepository.php
src/backend/src/Gateways/Filesystem/FilesystemRepository.php
+23
-0
src/backend/src/Gateways/Filesystem/FilesystemRepositoryServiceProvider.php
...teways/Filesystem/FilesystemRepositoryServiceProvider.php
+51
-0
src/backend/src/Gateways/Filesystem/InMemoryFilesystemRepository.php
.../src/Gateways/Filesystem/InMemoryFilesystemRepository.php
+46
-0
src/backend/src/Gateways/Filesystem/OperatingSystemFilesystemRepository.php
...teways/Filesystem/OperatingSystemFilesystemRepository.php
+41
-0
src/backend/src/UseCases/Door/UpdateBinary/FilePresenter.php
src/backend/src/UseCases/Door/UpdateBinary/FilePresenter.php
+25
-0
src/backend/src/UseCases/Door/UpdateBinary/Presenter.php
src/backend/src/UseCases/Door/UpdateBinary/Presenter.php
+17
-0
src/backend/src/UseCases/Door/UpdateBinary/ResponseModel.php
src/backend/src/UseCases/Door/UpdateBinary/ResponseModel.php
+21
-0
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinary.php
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinary.php
+46
-0
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinaryUseCase.php
...nd/src/UseCases/Door/UpdateBinary/UpdateBinaryUseCase.php
+17
-0
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinaryUseCaseServiceProvider.php
.../Door/UpdateBinary/UpdateBinaryUseCaseServiceProvider.php
+47
-0
src/backend/storage/app/.gitignore
src/backend/storage/app/.gitignore
+1
-0
src/backend/storage/app/controller/.gitignore
src/backend/storage/app/controller/.gitignore
+3
-0
src/backend/storage/app/controller/binaries/.gitignore
src/backend/storage/app/controller/binaries/.gitignore
+2
-0
src/backend/tests/Feature/Door/DoorUpdateTest.php
src/backend/tests/Feature/Door/DoorUpdateTest.php
+89
-0
src/backend/tests/Unit/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php
...it/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php
+116
-0
No files found.
src/backend/app/Http/Controllers/DoorController.php
View file @
42f65df0
...
...
@@ -8,7 +8,10 @@ use Illuminate\Http\Request;
use
Illuminate\Http\JsonResponse
;
use
Source\Authorization\Authorizer
;
use
Source\UseCases\Door\Access\AccessUseCase
;
use
Source\UseCases\Door\UpdateBinary\FilePresenter
;
use
Source\UseCases\Door\StatusResponse\JsonPresenter
;
use
Symfony\Component\HttpFoundation\BinaryFileResponse
;
use
Source\UseCases\Door\UpdateBinary\UpdateBinaryUseCase
;
use
Source\UseCases\Door\StatusResponse\StatusResponseUseCase
;
class
DoorController
extends
ApiController
...
...
@@ -68,4 +71,19 @@ class DoorController extends ApiController
{
return
$this
->
respondStatus
();
}
/**
* @param \Source\UseCases\Door\UpdateBinary\UpdateBinaryUseCase $updateBinaryUseCase
* @param \App\Guards\DoorGuard $doorGuard
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* @throws \Source\Exceptions\EntityNotFoundException
*/
public
function
getUpdateBinary
(
UpdateBinaryUseCase
$updateBinaryUseCase
,
DoorGuard
$doorGuard
):
BinaryFileResponse
{
$presenter
=
new
FilePresenter
();
$updateBinaryUseCase
->
getUpdateFile
(
$doorGuard
->
id
(),
$presenter
);
return
response
()
->
download
(
$presenter
->
getUpdateFilePath
());
}
}
src/backend/app/Providers/AppServiceProvider.php
View file @
42f65df0
...
...
@@ -20,6 +20,7 @@ use Source\Gateways\DoorGroup\DoorGroupRepositoryServiceProvider;
use
Source\Gateways\GroupUser\GroupUserRepositoryServiceProvider
;
use
Source\Gateways\Overrides\OverridesRepositoryServiceProvider
;
use
Source\Gateways\Schedules\SchedulesRepositoryServiceProvider
;
use
Source\Gateways\Filesystem\FilesystemRepositoryServiceProvider
;
use
Source\UseCases\Groups\GetGroup\GetGroupUseCaseServiceProvider
;
use
Source\UseCases\Tokens\GetToken\GetTokenUseCaseServiceProvider
;
use
Source\UseCases\Doors\CreateDoor\CreateDoorUseCaseServiceProvider
;
...
...
@@ -32,6 +33,7 @@ use Source\Gateways\DoorSchedule\DoorScheduleRepositoryServiceProvider;
use
Source\UseCases\Doors\GetAllDoors\GetAllDoorsUseCaseServiceProvider
;
use
Source\UseCases\Users\GetAllUsers\GetAllUsersUseCaseServiceProvider
;
use
Source\Gateways\RecurrenceSet\RecurrenceSetRepositoryServiceProvider
;
use
Source\UseCases\Door\UpdateBinary\UpdateBinaryUseCaseServiceProvider
;
use
Source\UseCases\Groups\CreateGroup\CreateGroupUseCaseServiceProvider
;
use
Source\UseCases\Groups\DeleteGroup\DeleteGroupUseCaseServiceProvider
;
use
Source\UseCases\Groups\UpdateGroup\UpdateGroupUseCaseServiceProvider
;
...
...
@@ -93,6 +95,7 @@ class AppServiceProvider extends ServiceProvider
DoorGroupRepositoryServiceProvider
::
class
,
GroupUserRepositoryServiceProvider
::
class
,
OverridesRepositoryServiceProvider
::
class
,
FilesystemRepositoryServiceProvider
::
class
,
DoorScheduleRepositoryServiceProvider
::
class
,
RecurrenceSetRepositoryServiceProvider
::
class
,
];
...
...
@@ -132,6 +135,7 @@ class AppServiceProvider extends ServiceProvider
// Door
AccessUseCaseServiceProvider
::
class
,
UpdateBinaryUseCaseServiceProvider
::
class
,
StatusResponseUseCaseServiceProvider
::
class
,
DoorAuthenticateUseCaseServiceProvider
::
class
,
...
...
src/backend/config/filesystems.php
View file @
42f65df0
...
...
@@ -28,6 +28,8 @@ return [
'cloud'
=>
env
(
'FILESYSTEM_CLOUD'
,
's3'
),
'controller_update_path'
=>
'controller/binaries/'
,
/*
|--------------------------------------------------------------------------
| Filesystem Disks
...
...
src/backend/routes/door.php
View file @
42f65df0
...
...
@@ -22,3 +22,5 @@ Route::get('ping', static function () {
Route
::
get
(
'access/{doorcode}'
,
[
DoorController
::
class
,
'access'
]);
Route
::
get
(
'status'
,
[
DoorController
::
class
,
'status'
]);
Route
::
get
(
'update'
,
[
DoorController
::
class
,
'getUpdateBinary'
]);
src/backend/src/Gateways/Filesystem/FilesystemRepository.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\Gateways\Filesystem
;
interface
FilesystemRepository
{
/**
* Returns a list of files in a directory (Not recursive).
*
* @param string $directory
* @return string[]
*/
public
function
getFilesForDirectory
(
string
$directory
):
array
;
/**
* Gets the full path to the file
*
* @param string $file
* @return string
*/
public
function
getFullPathForFIle
(
string
$file
):
string
;
}
src/backend/src/Gateways/Filesystem/FilesystemRepositoryServiceProvider.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\Gateways\Filesystem
;
use
Illuminate\Support\ServiceProvider
;
use
Illuminate\Filesystem\FilesystemManager
;
use
Illuminate\Contracts\Foundation\Application
;
use
Illuminate\Contracts\Support\DeferrableProvider
;
/**
* Service provider must be registered in AppServiceProvider
*/
class
FilesystemRepositoryServiceProvider
extends
ServiceProvider
implements
DeferrableProvider
{
/**
* Register any application services.
*
* @return void
*/
public
function
register
()
{
$this
->
app
->
singleton
(
FilesystemRepository
::
class
,
static
function
(
Application
$app
)
{
if
(
env
(
'APP_ENV'
)
===
'testing'
)
{
return
new
InMemoryFilesystemRepository
();
}
/** @var FilesystemManager $fsManager */
$fsManager
=
$app
->
make
(
FilesystemManager
::
class
);
return
new
OperatingSystemFilesystemRepository
(
$fsManager
->
disk
(
'local'
));
});
}
/**
* Bootstrap any application services.
*
* @return void
*/
public
function
boot
():
void
{
}
/**
* @return array
*/
public
function
provides
()
{
return
[
FilesystemRepository
::
class
];
}
}
src/backend/src/Gateways/Filesystem/InMemoryFilesystemRepository.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\Gateways\Filesystem
;
class
InMemoryFilesystemRepository
implements
FilesystemRepository
{
/**
* @var string
*/
public
string
$basePath
=
''
;
/**
* @var string[][]
*/
protected
array
$files
=
[];
/**
* @param string $directory
* @param string $file
*/
public
function
addFileToDirectory
(
string
$directory
,
string
$file
):
void
{
if
(
isset
(
$this
->
files
[
$directory
]))
{
$this
->
files
[
$directory
][]
=
$file
;
}
else
{
$this
->
files
[
$directory
]
=
[
$file
];
}
}
/**
* @inheritDoc
*/
public
function
getFilesForDirectory
(
string
$directory
):
array
{
return
$this
->
files
[
$directory
]
??
[];
}
/**
* @inheritDoc
*/
public
function
getFullPathForFIle
(
string
$file
):
string
{
return
$this
->
basePath
.
$file
;
}
}
src/backend/src/Gateways/Filesystem/OperatingSystemFilesystemRepository.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\Gateways\Filesystem
;
use
Illuminate\Contracts\Filesystem\Filesystem
;
class
OperatingSystemFilesystemRepository
implements
FilesystemRepository
{
/**
* @var \Illuminate\Contracts\Filesystem\Filesystem
*/
protected
Filesystem
$fs
;
/**
* @param \Illuminate\Contracts\Filesystem\Filesystem $fs
*/
public
function
__construct
(
Filesystem
$fs
)
{
$this
->
fs
=
$fs
;
}
/**
* @inheritDoc
*/
public
function
getFullPathForFIle
(
string
$file
):
string
{
return
$this
->
fs
->
getDriver
()
->
getAdapter
()
->
getPathPrefix
()
.
$file
;
}
/**
* @inheritDoc
*/
public
function
getFilesForDirectory
(
string
$directory
):
array
{
return
array_filter
(
$this
->
fs
->
files
(
$directory
),
static
function
(
string
$file
)
{
// Filter out .gitignore file
return
strpos
(
$file
,
'.gitignore'
)
===
false
;
});
}
}
src/backend/src/UseCases/Door/UpdateBinary/FilePresenter.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\UseCases\Door\UpdateBinary
;
use
Source\UseCases\BasePresenter
;
class
FilePresenter
extends
BasePresenter
implements
Presenter
{
/**
* @var string
*/
protected
string
$updateFile
;
/** @inheritDoc */
public
function
present
(
ResponseModel
$responseModel
):
void
{
$this
->
updateFile
=
$responseModel
->
getPath
();
}
/** @inheritDoc */
public
function
getUpdateFilePath
():
string
{
return
$this
->
updateFile
;
}
}
src/backend/src/UseCases/Door/UpdateBinary/Presenter.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\UseCases\Door\UpdateBinary
;
interface
Presenter
{
/**
* @param ResponseModel $responseModel
* @return void
*/
public
function
present
(
ResponseModel
$responseModel
):
void
;
/**
* @return string
*/
public
function
getUpdateFilePath
():
string
;
}
src/backend/src/UseCases/Door/UpdateBinary/ResponseModel.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\UseCases\Door\UpdateBinary
;
class
ResponseModel
{
protected
string
$path
;
public
function
__construct
(
string
$path
)
{
$this
->
path
=
$path
;
}
/**
* @return string
*/
public
function
getPath
():
string
{
return
$this
->
path
;
}
}
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinary.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\UseCases\Door\UpdateBinary
;
use
Source\Exceptions\EntityNotFoundException
;
use
Source\Gateways\Filesystem\FilesystemRepository
;
class
UpdateBinary
implements
UpdateBinaryUseCase
{
/**
* @var \Source\Gateways\Filesystem\FilesystemRepository
*/
protected
FilesystemRepository
$fs
;
protected
string
$updateBinaryDirectory
;
public
function
__construct
(
FilesystemRepository
$fs
,
string
$updateBinaryDirectory
)
{
$this
->
fs
=
$fs
;
$this
->
updateBinaryDirectory
=
$updateBinaryDirectory
;
}
/**
* @inheritDoc
*/
public
function
getUpdateFile
(
?string
$doorId
,
Presenter
$presenter
):
void
{
if
(
!
$doorId
||
!
$this
->
updateBinaryDirectory
)
{
// no door exists to find an update for
// Or there is no update directory specified
throw
new
EntityNotFoundException
();
}
$binaries
=
$this
->
fs
->
getFilesForDirectory
(
$this
->
updateBinaryDirectory
);
if
(
!
$binaries
)
{
throw
new
EntityNotFoundException
();
}
rsort
(
$binaries
);
$response
=
new
ResponseModel
(
$this
->
fs
->
getFullPathForFIle
(
$binaries
[
0
]));
$presenter
->
present
(
$response
);
}
}
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinaryUseCase.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\UseCases\Door\UpdateBinary
;
interface
UpdateBinaryUseCase
{
/**
* Determines the update binary to send to the specified door for an update
* Throws EntityNotFoundException if it cannot find a suitable update file
*
* @param string $doorId
* @param \Source\UseCases\Door\UpdateBinary\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
*/
public
function
getUpdateFile
(
?string
$doorId
,
Presenter
$presenter
):
void
;
}
src/backend/src/UseCases/Door/UpdateBinary/UpdateBinaryUseCaseServiceProvider.php
0 → 100644
View file @
42f65df0
<?php
namespace
Source\UseCases\Door\UpdateBinary
;
use
Illuminate\Support\ServiceProvider
;
use
Illuminate\Contracts\Foundation\Application
;
use
Illuminate\Contracts\Support\DeferrableProvider
;
use
Source\Gateways\Filesystem\FilesystemRepository
;
/**
* Service provider must be registered in AppServiceProvider
*/
class
UpdateBinaryUseCaseServiceProvider
extends
ServiceProvider
implements
DeferrableProvider
{
/**
* Register any application services.
*
* @return void
*/
public
function
register
()
{
$this
->
app
->
bind
(
UpdateBinaryUseCase
::
class
,
static
function
(
Application
$app
)
{
return
new
UpdateBinary
(
$app
->
make
(
FilesystemRepository
::
class
),
config
(
'filesystems.controller_update_path'
,
''
)
);
});
}
/**
* Bootstrap any application services.
*
* @return void
*/
public
function
boot
():
void
{
}
/**
* @return array
*/
public
function
provides
()
{
return
[
UpdateBinaryUseCase
::
class
];
}
}
src/backend/storage/app/.gitignore
View file @
42f65df0
*
!public/
!controller/
!.gitignore
src/backend/storage/app/controller/.gitignore
0 → 100644
View file @
42f65df0
*
!binaries/
!.gitignore
src/backend/storage/app/controller/binaries/.gitignore
0 → 100644
View file @
42f65df0
*
!.gitignore
src/backend/tests/Feature/Door/DoorUpdateTest.php
0 → 100644
View file @
42f65df0
<?php
namespace
Tests\Feature\Door
;
use
Illuminate\Testing\TestResponse
;
use
Illuminate\Filesystem\FilesystemManager
;
use
Illuminate\Contracts\Filesystem\Filesystem
;
use
Source\UseCases\Door\UpdateBinary\UpdateBinary
;
use
Tests\Feature\AuthenticatesWithApplicationTestCase
;
use
Source\UseCases\Door\UpdateBinary\UpdateBinaryUseCase
;
use
Source\Gateways\Filesystem\OperatingSystemFilesystemRepository
;
class
DoorUpdateTest
extends
AuthenticatesWithApplicationTestCase
{
protected
const
LATEST_BIN_NAME
=
'z'
;
protected
TestResponse
$response
;
protected
string
$path
;
/**
* @var \Illuminate\Contracts\Filesystem\Filesystem
*/
protected
Filesystem
$disk
;
public
function
setUp
():
void
{
parent
::
setUp
();
/** @var FilesystemManager $fs */
$fs
=
$this
->
app
->
make
(
FilesystemManager
::
class
);
$this
->
disk
=
$fs
->
disk
(
'local'
);
$this
->
path
=
config
(
'filesystems.controller_update_path'
);
$this
->
app
->
bind
(
UpdateBinaryUseCase
::
class
,
function
()
{
return
new
UpdateBinary
(
new
OperatingSystemFilesystemRepository
(
$this
->
disk
),
$this
->
path
);
});
}
protected
function
handleTest
():
void
{
$this
->
response
=
$this
->
get
(
'/api/door/update'
,
[
'Authorization'
=>
'Bearer '
.
$this
->
doorToken
]);
}
/**
* @param string $name
* @param string $contents
*/
protected
function
addFile
(
string
$name
,
string
$contents
):
void
{
$this
->
disk
->
put
(
$this
->
path
.
$name
,
$contents
);
}
/**
* @param string $name
*/
protected
function
removeFile
(
string
$name
):
void
{
$this
->
disk
->
delete
(
$this
->
path
.
$name
);
}
/**
* @test
*/
public
function
it_denies_unauthenticated_doors
():
void
{
$this
->
handleTest
();
$this
->
response
->
assertStatus
(
401
);
}
/**
* @test
* @throws \Source\Exceptions\EntityExistsException
*/
public
function
it_gets_a_file_update
():
void
{
$this
->
addFile
(
self
::
LATEST_BIN_NAME
,
'file contents'
);
$this
->
authenticateAsDoor
();
$this
->
handleTest
();
$this
->
removeFile
(
self
::
LATEST_BIN_NAME
);
$this
->
response
->
assertStatus
(
200
);
$this
->
response
->
assertHeader
(
'content-length'
,
13
);
}
}
src/backend/tests/Unit/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php
0 → 100644
View file @
42f65df0
<?php
namespace
Tests\Unit\Source\UseCases\Door\UpdateBinary
;
use
PHPUnit\Framework\TestCase
;
use
Source\Exceptions\EntityNotFoundException
;
use
Source\UseCases\Door\UpdateBinary\UpdateBinary
;
use
Source\UseCases\Door\UpdateBinary\FilePresenter
;
use
Source\Gateways\Filesystem\InMemoryFilesystemRepository
;
class
UpdateBinaryTest
extends
TestCase
{
protected
const
UPDATE_BINARY_DIR
=
'265918'
;
protected
const
DOOR_ID
=
'264557'
;
/**
* @var \Source\Gateways\Filesystem\InMemoryFilesystemRepository
*/
protected
InMemoryFilesystemRepository
$fs
;
/**
* @var \Source\UseCases\Door\UpdateBinary\UpdateBinary
*/
protected
UpdateBinary
$useCase
;
protected
string
$returnedPath
;
public
function
setUp
():
void
{
parent
::
setUp
();
$this
->
fs
=
new
InMemoryFilesystemRepository
();
$this
->
useCase
=
new
UpdateBinary
(
$this
->
fs
,
self
::
UPDATE_BINARY_DIR
);
}
/**
* @param string|null $doorId
* @throws \Source\Exceptions\EntityNotFoundException
*/
protected
function
handleTest
(
?string
$doorId
):
void
{
$presenter
=
new
FilePresenter
();
$this
->
useCase
->
getUpdateFile
(
$doorId
,
$presenter
);
$this
->
returnedPath
=
$presenter
->
getUpdateFilePath
();
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public
function
it_fails_when_there_is_no_door
():
void
{
$this
->
expectException
(
EntityNotFoundException
::
class
);
$this
->
handleTest
(
null
);
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public
function
it_fails_when_there_is_no_specified_update_directory
():
void
{