Update last of existing services to use repositories, includes unit tests

Also update PHPDocs on all the repository interfaces and classes to be correct.
This commit is contained in:
Dane Everitt 2017-07-08 14:07:51 -05:00
parent 50588a1f54
commit 0deb022093
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
21 changed files with 808 additions and 207 deletions

View file

@ -0,0 +1,30 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Contracts\Repository;
interface ApiKeyRepositoryInterface extends RepositoryInterface
{
//
}

View file

@ -0,0 +1,30 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Contracts\Repository;
interface ApiPermissionRepositoryInterface extends RepositoryInterface
{
//
}

View file

@ -26,5 +26,11 @@ namespace Pterodactyl\Contracts\Repository\Attributes;
interface SearchableInterface interface SearchableInterface
{ {
/**
* Filter results by search term.
*
* @param string $term
* @return $this
*/
public function search($term); public function search($term);
} }

View file

@ -26,5 +26,14 @@ namespace Pterodactyl\Contracts\Repository;
interface DatabaseHostInterface extends RepositoryInterface interface DatabaseHostInterface extends RepositoryInterface
{ {
/**
* Delete a database host from the DB if there are no databases using it.
*
* @param int $id
* @return bool|null
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function deleteIfNoDatabases($id); public function deleteIfNoDatabases($id);
} }

View file

@ -28,5 +28,14 @@ use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
interface LocationRepositoryInterface extends RepositoryInterface, SearchableInterface interface LocationRepositoryInterface extends RepositoryInterface, SearchableInterface
{ {
/**
* Delete a location only if there are no nodes attached to it.
*
* @param $id
* @return bool|mixed|null
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function deleteIfNoNodes($id); public function deleteIfNoNodes($id);
} }

View file

@ -26,25 +26,108 @@ namespace Pterodactyl\Contracts\Repository;
interface RepositoryInterface interface RepositoryInterface
{ {
/**
* Return an identifier or Model object to be used by the repository.
*
* @return string|\Closure|object
*/
public function model(); public function model();
/**
* Return the model being used for this repository instance.
*
* @return mixed
*/
public function getModel(); public function getModel();
/**
* Returns an instance of a query builder.
*
* @return mixed
*/
public function getBuilder(); public function getBuilder();
/**
* Returns the colummns to be selected or returned by the query.
*
* @return mixed
*/
public function getColumns(); public function getColumns();
/**
* An array of columns to filter the response by.
*
* @param array $columns
* @return $this
*/
public function withColumns($columns = ['*']); public function withColumns($columns = ['*']);
public function create($fields); /**
* Disable returning a fresh model when data is inserted or updated.
*
* @return $this
*/
public function withoutFresh();
/**
* Create a new model instance and persist it to the database.
*
* @param array $fields
* @param bool $validate
* @return mixed
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
*/
public function create(array $fields, $validate = true);
/**
* Delete a given record from the database.
*
* @param int $id
* @return bool|null
*/
public function delete($id); public function delete($id);
/**
* Find a model that has the specific ID passed.
*
* @param int $id
* @return mixed
*
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function find($id); public function find($id);
public function findWhere($fields); /**
* Find a model matching an array of where clauses.
*
* @param array $fields
* @return mixed
*
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function findWhere(array $fields);
public function update($id, $fields); /**
* Update a given ID with the passed array of fields.
*
* @param int $id
* @param array $fields
* @param bool $validate
* @param bool $force
* @return mixed
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function update($id, array $fields, $validate = true, $force = false);
public function massUpdate($fields); /**
* Update multiple records matching the passed clauses.
*
* @param array $where
* @param array $fields
* @return mixed
*/
public function massUpdate(array $where, array $fields);
} }

View file

@ -28,7 +28,20 @@ use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
interface UserRepositoryInterface extends RepositoryInterface, SearchableInterface interface UserRepositoryInterface extends RepositoryInterface, SearchableInterface
{ {
/**
* Return all users with counts of servers and subusers of servers.
*
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
public function getAllUsersWithCounts(); public function getAllUsersWithCounts();
/**
* Delete a user if they have no servers attached to their account.
*
* @param int $id
* @return bool
*
* @throws \Pterodactyl\Exceptions\DisplayException
*/
public function deleteIfNoServers($id); public function deleteIfNoServers($id);
} }

View file

@ -36,7 +36,7 @@ class APIPermission extends Model implements ValidableContract
/** /**
* List of permissions available for the API. * List of permissions available for the API.
*/ */
const PERMISSIONS = [ const CONST_PERMISSIONS = [
// Items within this block are available to non-adminitrative users. // Items within this block are available to non-adminitrative users.
'_user' => [ '_user' => [
'server' => [ 'server' => [

View file

@ -25,8 +25,12 @@
namespace Pterodactyl\Providers; namespace Pterodactyl\Providers;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
use Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface;
use Pterodactyl\Contracts\Repository\DatabaseHostInterface; use Pterodactyl\Contracts\Repository\DatabaseHostInterface;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
use Pterodactyl\Repositories\Eloquent\ApiKeyRepository;
use Pterodactyl\Repositories\Eloquent\ApiPermissionRepository;
use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository; use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository;
use Pterodactyl\Repositories\Eloquent\LocationRepository; use Pterodactyl\Repositories\Eloquent\LocationRepository;
use Pterodactyl\Repositories\Eloquent\UserRepository; use Pterodactyl\Repositories\Eloquent\UserRepository;
@ -39,6 +43,8 @@ class RepositoryServiceProvider extends ServiceProvider
*/ */
public function register() public function register()
{ {
$this->app->bind(ApiKeyRepositoryInterface::class, ApiKeyRepository::class);
$this->app->bind(ApiPermissionRepositoryInterface::class, ApiPermissionRepository::class);
$this->app->bind(DatabaseHostInterface::class, DatabaseHostRepository::class); $this->app->bind(DatabaseHostInterface::class, DatabaseHostRepository::class);
$this->app->bind(LocationRepositoryInterface::class, LocationRepository::class); $this->app->bind(LocationRepositoryInterface::class, LocationRepository::class);
$this->app->bind(UserRepositoryInterface::class, UserRepository::class); $this->app->bind(UserRepositoryInterface::class, UserRepository::class);

View file

@ -0,0 +1,39 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\APIKey;
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
class ApiKeyRepository extends EloquentRepository implements ApiKeyRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function model()
{
return APIKey::class;
}
}

View file

@ -0,0 +1,39 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\APIPermission;
use Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface;
class ApiPermissionRepository extends EloquentRepository implements ApiPermissionRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function model()
{
return APIPermission::class;
}
}

View file

@ -32,9 +32,7 @@ use Pterodactyl\Models\DatabaseHost;
class DatabaseHostRepository extends EloquentRepository implements DatabaseHostInterface class DatabaseHostRepository extends EloquentRepository implements DatabaseHostInterface
{ {
/** /**
* Setup the model to be used. * {@inheritdoc}
*
* @return string
*/ */
public function model() public function model()
{ {
@ -42,13 +40,7 @@ class DatabaseHostRepository extends EloquentRepository implements DatabaseHostI
} }
/** /**
* Delete a database host from the DB if there are no databases using it. * {@inheritdoc}
*
* @param int $id
* @return bool|null
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */
public function deleteIfNoDatabases($id) public function deleteIfNoDatabases($id)
{ {

View file

@ -24,14 +24,15 @@
namespace Pterodactyl\Repositories\Eloquent; namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Exceptions\Model\DataValidationException;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Repository\Repository; use Pterodactyl\Repository\Repository;
use Pterodactyl\Contracts\Repository\RepositoryInterface; use Pterodactyl\Contracts\Repository\RepositoryInterface;
use Pterodactyl\Exceptions\Model\DataValidationException;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
abstract class EloquentRepository extends Repository implements RepositoryInterface abstract class EloquentRepository extends Repository implements RepositoryInterface
{ {
/** /**
* {@inheritdoc}
* @return \Illuminate\Database\Eloquent\Builder * @return \Illuminate\Database\Eloquent\Builder
*/ */
public function getBuilder() public function getBuilder()
@ -40,14 +41,11 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf
} }
/** /**
* Create a new model instance and persist it to the database. * {@inheritdoc}
* @param array $fields
* @param bool $validate
* @param bool $force * @param bool $force
* @return bool|\Illuminate\Database\Eloquent\Model * @return \Illuminate\Database\Eloquent\Model|bool
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
*/ */
public function create($fields, $validate = true, $force = false) public function create(array $fields, $validate = true, $force = false)
{ {
$instance = $this->getBuilder()->newModelInstance(); $instance = $this->getBuilder()->newModelInstance();
@ -69,12 +67,8 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf
} }
/** /**
* Return a record from the database for a given ID. * {@inheritdoc}
*
* @param int $id
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
*
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */
public function find($id) public function find($id)
{ {
@ -87,17 +81,16 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf
return $instance; return $instance;
} }
public function findWhere($fields) /**
* {@inheritdoc}
*/
public function findWhere(array $fields)
{ {
// TODO: Implement findWhere() method. // TODO: Implement findWhere() method.
} }
/** /**
* Delete a record from the DB given an ID. * {@inheritdoc}
*
* @param int $id
* @param bool $destroy
* @return bool|null
*/ */
public function delete($id, $destroy = false) public function delete($id, $destroy = false)
{ {
@ -109,16 +102,9 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf
} }
/** /**
* @param int $id * {@inheritdoc}
* @param array $fields
* @param bool $validate
* @param bool $force
* @return mixed
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */
public function update($id, $fields, $validate = true, $force = false) public function update($id, array $fields, $validate = true, $force = false)
{ {
$instance = $this->getBuilder()->where('id', $id)->first(); $instance = $this->getBuilder()->where('id', $id)->first();
@ -143,7 +129,10 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf
return ($this->withFresh) ? $instance->fresh($this->getColumns()) : $saved; return ($this->withFresh) ? $instance->fresh($this->getColumns()) : $saved;
} }
public function massUpdate($fields) /**
* {@inheritdoc}
*/
public function massUpdate(array $where, array $fields)
{ {
// TODO: Implement massUpdate() method. // TODO: Implement massUpdate() method.
} }

View file

@ -37,9 +37,7 @@ class LocationRepository extends EloquentRepository implements LocationRepositor
protected $searchTerm; protected $searchTerm;
/** /**
* Setup model. * {@inheritdoc}
*
* @return string
*/ */
public function model() public function model()
{ {
@ -47,10 +45,7 @@ class LocationRepository extends EloquentRepository implements LocationRepositor
} }
/** /**
* Setup the model for search abilities. * {@inheritdoc}
*
* @param $term
* @return $this
*/ */
public function search($term) public function search($term)
{ {
@ -65,13 +60,7 @@ class LocationRepository extends EloquentRepository implements LocationRepositor
} }
/** /**
* Delete a location only if there are no nodes attached to it. * {@inheritdoc}
*
* @param $id
* @return bool|mixed|null
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */
public function deleteIfNoNodes($id) public function deleteIfNoNodes($id)
{ {

View file

@ -56,11 +56,17 @@ class UserRepository extends EloquentRepository implements UserRepositoryInterfa
$this->config = $config; $this->config = $config;
} }
/**
* {@inheritdoc}
*/
public function model() public function model()
{ {
return User::class; return User::class;
} }
/**
* {@inheritdoc}
*/
public function search($term) public function search($term)
{ {
if (empty($term)) { if (empty($term)) {
@ -73,6 +79,9 @@ class UserRepository extends EloquentRepository implements UserRepositoryInterfa
return $clone; return $clone;
} }
/**
* {@inheritdoc}
*/
public function getAllUsersWithCounts() public function getAllUsersWithCounts()
{ {
$users = $this->getBuilder()->withCount('servers', 'subuserOf'); $users = $this->getBuilder()->withCount('servers', 'subuserOf');
@ -87,12 +96,7 @@ class UserRepository extends EloquentRepository implements UserRepositoryInterfa
} }
/** /**
* Delete a user if they have no servers attached to their account. * {@inheritdoc}
*
* @param int $id
* @return bool
*
* @throws \Pterodactyl\Exceptions\DisplayException
*/ */
public function deleteIfNoServers($id) public function deleteIfNoServers($id)
{ {

View file

@ -24,48 +24,52 @@
namespace Pterodactyl\Services; namespace Pterodactyl\Services;
use Pterodactyl\Models\APIKey; use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\Connection;
use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Contracts\Encryption\Encrypter;
use Pterodactyl\Exceptions\Model\DataValidationException; use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
class ApiKeyService class ApiKeyService
{ {
const PUB_CRYPTO_BYTES = 8; const PUB_CRYPTO_BYTES = 8;
const PRIV_CRYPTO_BYTES = 32; const PRIV_CRYPTO_BYTES = 32;
/**
* @var \Illuminate\Database\ConnectionInterface
*/
protected $database;
/** /**
* @var \Illuminate\Contracts\Encryption\Encrypter * @var \Illuminate\Contracts\Encryption\Encrypter
*/ */
protected $encrypter; protected $encrypter;
/**
* @var \Pterodactyl\Models\APIKey
*/
protected $model;
/** /**
* @var \Pterodactyl\Services\ApiPermissionService * @var \Pterodactyl\Services\ApiPermissionService
*/ */
protected $permissionService; protected $permissionService;
/**
* @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface
*/
protected $repository;
/** /**
* ApiKeyService constructor. * ApiKeyService constructor.
* *
* @param \Pterodactyl\Models\APIKey $model * @param \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface $repository
* @param \Illuminate\Database\Connection $database * @param \Illuminate\Database\ConnectionInterface $database
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
* @param \Pterodactyl\Services\ApiPermissionService $permissionService * @param \Pterodactyl\Services\ApiPermissionService $permissionService
*/ */
public function __construct( public function __construct(
APIKey $model, ApiKeyRepositoryInterface $repository,
Connection $database, ConnectionInterface $database,
Encrypter $encrypter, Encrypter $encrypter,
ApiPermissionService $permissionService ApiPermissionService $permissionService
) { ) {
$this->repository = $repository;
$this->database = $database; $this->database = $database;
$this->encrypter = $encrypter; $this->encrypter = $encrypter;
$this->model = $model;
$this->permissionService = $permissionService; $this->permissionService = $permissionService;
} }
@ -88,16 +92,12 @@ class ApiKeyService
// Start a Transaction // Start a Transaction
$this->database->beginTransaction(); $this->database->beginTransaction();
$instance = $this->model->newInstance($data); $data = array_merge($data, [
$instance->public = $publicKey; 'public' => $publicKey,
$instance->secret = $this->encrypter->encrypt($secretKey); 'secret' => $this->encrypter->encrypt($secretKey),
]);
if (! $instance->save()) { $instance = $this->repository->create($data, true, true);
$this->database->rollBack();
throw new DataValidationException($instance->getValidator());
}
$key = $instance->fresh();
$nodes = $this->permissionService->getPermissions(); $nodes = $this->permissionService->getPermissions();
foreach ($permissions as $permission) { foreach ($permissions as $permission) {
@ -111,7 +111,7 @@ class ApiKeyService
continue; continue;
} }
$this->permissionService->create($key->id, sprintf('user.%s', $permission)); $this->permissionService->create($instance->id, sprintf('user.%s', $permission));
} }
foreach ($administrative as $permission) { foreach ($administrative as $permission) {
@ -125,7 +125,7 @@ class ApiKeyService
continue; continue;
} }
$this->permissionService->create($key->id, $permission); $this->permissionService->create($instance->id, $permission);
} }
$this->database->commit(); $this->database->commit();
@ -136,18 +136,11 @@ class ApiKeyService
/** /**
* Delete the API key and associated permissions from the database. * Delete the API key and associated permissions from the database.
* *
* @param int|\Pterodactyl\Models\APIKey $key * @param int $id
* @return bool|null * @return bool|null
*
* @throws \Exception
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/ */
public function revoke($key) public function revoke($id)
{ {
if (! $key instanceof APIKey) { return $this->repository->delete($id);
$key = $this->model->findOrFail($key);
}
return $key->delete();
} }
} }

View file

@ -24,24 +24,23 @@
namespace Pterodactyl\Services; namespace Pterodactyl\Services;
use Pterodactyl\Models\APIPermission; use Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface;
use Pterodactyl\Exceptions\Model\DataValidationException;
class ApiPermissionService class ApiPermissionService
{ {
/** /**
* @var \Pterodactyl\Models\APIPermission * @var \Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface
*/ */
protected $model; protected $repository;
/** /**
* ApiPermissionService constructor. * ApiPermissionService constructor.
* *
* @param \Pterodactyl\Models\APIPermission $model * @param \Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface $repository
*/ */
public function __construct(APIPermission $model) public function __construct(ApiPermissionRepositoryInterface $repository)
{ {
$this->model = $model; $this->repository = $repository;
} }
/** /**
@ -55,16 +54,11 @@ class ApiPermissionService
*/ */
public function create($key, $permission) public function create($key, $permission)
{ {
$instance = $this->model->newInstance([ // @todo handle an array of permissions to do a mass assignment?
return $this->repository->withoutFresh()->create([
'key_id' => $key, 'key_id' => $key,
'permission' => $permission, 'permission' => $permission,
]); ]);
if (! $instance->save()) {
throw new DataValidationException($instance->getValidator());
}
return true;
} }
/** /**
@ -74,6 +68,6 @@ class ApiPermissionService
*/ */
public function getPermissions() public function getPermissions()
{ {
return APIPermission::PERMISSIONS; return $this->repository->getModel()::CONST_PERMISSIONS;
} }
} }

View file

@ -44,6 +44,7 @@
"friendsofphp/php-cs-fixer": "1.*", "friendsofphp/php-cs-fixer": "1.*",
"fzaninotto/faker": "~1.4", "fzaninotto/faker": "~1.4",
"mockery/mockery": "0.9.*", "mockery/mockery": "0.9.*",
"php-mock/php-mock-phpunit": "^1.1",
"phpunit/phpunit": "~5.7", "phpunit/phpunit": "~5.7",
"sllh/php-cs-fixer-styleci-bridge": "^2.1" "sllh/php-cs-fixer-styleci-bridge": "^2.1"
}, },

353
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "d3edf73b6618705ee34a76fa0319f0de", "content-hash": "f1afab5cf73088c6034bfb2b13631600",
"packages": [ "packages": [
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
@ -803,16 +803,16 @@
}, },
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
"version": "1.6.2", "version": "1.6.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/erusev/parsedown.git", "url": "https://github.com/erusev/parsedown.git",
"reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01" "reference": "728952b90a333b5c6f77f06ea9422b94b585878d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01", "url": "https://api.github.com/repos/erusev/parsedown/zipball/728952b90a333b5c6f77f06ea9422b94b585878d",
"reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01", "reference": "728952b90a333b5c6f77f06ea9422b94b585878d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -841,7 +841,7 @@
"markdown", "markdown",
"parser" "parser"
], ],
"time": "2017-03-29T16:04:15+00:00" "time": "2017-05-14T14:47:48+00:00"
}, },
{ {
"name": "fideloper/proxy", "name": "fideloper/proxy",
@ -1989,16 +1989,16 @@
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v3.0.5", "version": "v3.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "2b9e2f71b722f7c53918ab0c25f7646c2013f17d" "reference": "0808939f81c1347a3c8a82a5925385a08074b0f1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2b9e2f71b722f7c53918ab0c25f7646c2013f17d", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0808939f81c1347a3c8a82a5925385a08074b0f1",
"reference": "2b9e2f71b722f7c53918ab0c25f7646c2013f17d", "reference": "0808939f81c1347a3c8a82a5925385a08074b0f1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2036,7 +2036,7 @@
"parser", "parser",
"php" "php"
], ],
"time": "2017-03-05T18:23:57+00:00" "time": "2017-06-28T20:53:48+00:00"
}, },
{ {
"name": "paragonie/random_compat", "name": "paragonie/random_compat",
@ -2346,16 +2346,16 @@
}, },
{ {
"name": "psy/psysh", "name": "psy/psysh",
"version": "v0.8.8", "version": "v0.8.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/bobthecow/psysh.git", "url": "https://github.com/bobthecow/psysh.git",
"reference": "fe65c30cbc55c71e61ba3a38b5a581149be31b8e" "reference": "58a31cc4404c8f632d8c557bc72056af2d3a83db"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/fe65c30cbc55c71e61ba3a38b5a581149be31b8e", "url": "https://api.github.com/repos/bobthecow/psysh/zipball/58a31cc4404c8f632d8c557bc72056af2d3a83db",
"reference": "fe65c30cbc55c71e61ba3a38b5a581149be31b8e", "reference": "58a31cc4404c8f632d8c557bc72056af2d3a83db",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2415,7 +2415,7 @@
"interactive", "interactive",
"shell" "shell"
], ],
"time": "2017-06-24T06:16:19+00:00" "time": "2017-07-06T14:53:52+00:00"
}, },
{ {
"name": "ramsey/uuid", "name": "ramsey/uuid",
@ -2653,16 +2653,16 @@
}, },
{ {
"name": "spatie/fractalistic", "name": "spatie/fractalistic",
"version": "2.2.0", "version": "2.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/fractalistic.git", "url": "https://github.com/spatie/fractalistic.git",
"reference": "8f00c666a8b8dfb06f79286f97255e6ab1c89639" "reference": "79a48d949bc053a1c60c934f727f5901bf35fa74"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/fractalistic/zipball/8f00c666a8b8dfb06f79286f97255e6ab1c89639", "url": "https://api.github.com/repos/spatie/fractalistic/zipball/79a48d949bc053a1c60c934f727f5901bf35fa74",
"reference": "8f00c666a8b8dfb06f79286f97255e6ab1c89639", "reference": "79a48d949bc053a1c60c934f727f5901bf35fa74",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2700,7 +2700,7 @@
"spatie", "spatie",
"transform" "transform"
], ],
"time": "2017-05-29T14:16:20+00:00" "time": "2017-07-03T08:20:31+00:00"
}, },
{ {
"name": "spatie/laravel-fractal", "name": "spatie/laravel-fractal",
@ -2816,16 +2816,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "70d2a29b2911cbdc91a7e268046c395278238b2e" "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/70d2a29b2911cbdc91a7e268046c395278238b2e", "url": "https://api.github.com/repos/symfony/console/zipball/a97e45d98c59510f085fa05225a1acb74dfe0546",
"reference": "70d2a29b2911cbdc91a7e268046c395278238b2e", "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2881,11 +2881,11 @@
], ],
"description": "Symfony Console Component", "description": "Symfony Console Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-02T19:24:58+00:00" "time": "2017-07-03T13:19:36+00:00"
}, },
{ {
"name": "symfony/css-selector", "name": "symfony/css-selector",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/css-selector.git", "url": "https://github.com/symfony/css-selector.git",
@ -2938,16 +2938,16 @@
}, },
{ {
"name": "symfony/debug", "name": "symfony/debug",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/debug.git", "url": "https://github.com/symfony/debug.git",
"reference": "e9c50482841ef696e8fa1470d950a79c8921f45d" "reference": "63b85a968486d95ff9542228dc2e4247f16f9743"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/e9c50482841ef696e8fa1470d950a79c8921f45d", "url": "https://api.github.com/repos/symfony/debug/zipball/63b85a968486d95ff9542228dc2e4247f16f9743",
"reference": "e9c50482841ef696e8fa1470d950a79c8921f45d", "reference": "63b85a968486d95ff9542228dc2e4247f16f9743",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2990,20 +2990,20 @@
], ],
"description": "Symfony Debug Component", "description": "Symfony Debug Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-01T21:01:25+00:00" "time": "2017-07-05T13:02:37+00:00"
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
"reference": "4054a102470665451108f9b59305c79176ef98f0" "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4054a102470665451108f9b59305c79176ef98f0", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67535f1e3fd662bdc68d7ba317c93eecd973617e",
"reference": "4054a102470665451108f9b59305c79176ef98f0", "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3053,11 +3053,11 @@
], ],
"description": "Symfony EventDispatcher Component", "description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-04T18:15:29+00:00" "time": "2017-06-09T14:53:08+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
@ -3106,16 +3106,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "80eb5a1f968448b77da9e8b2c0827f6e8d767846" "reference": "f347a5f561b03db95ed666959db42bbbf429b7e5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/80eb5a1f968448b77da9e8b2c0827f6e8d767846", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f347a5f561b03db95ed666959db42bbbf429b7e5",
"reference": "80eb5a1f968448b77da9e8b2c0827f6e8d767846", "reference": "f347a5f561b03db95ed666959db42bbbf429b7e5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3155,20 +3155,20 @@
], ],
"description": "Symfony HttpFoundation Component", "description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-05T13:06:51+00:00" "time": "2017-06-24T09:29:48+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "be8280f7fa8e95b86514f1e1be997668a53b2888" "reference": "33f87c957122cfbd9d90de48698ee074b71106ea"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/be8280f7fa8e95b86514f1e1be997668a53b2888", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/33f87c957122cfbd9d90de48698ee074b71106ea",
"reference": "be8280f7fa8e95b86514f1e1be997668a53b2888", "reference": "33f87c957122cfbd9d90de48698ee074b71106ea",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3241,7 +3241,7 @@
], ],
"description": "Symfony HttpKernel Component", "description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-06T03:59:58+00:00" "time": "2017-07-05T13:28:15+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
@ -3412,16 +3412,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "8e30690c67aafb6c7992d6d8eb0d707807dd3eaf" "reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/8e30690c67aafb6c7992d6d8eb0d707807dd3eaf", "url": "https://api.github.com/repos/symfony/process/zipball/5ab8949b682b1bf9d4511a228b5e045c96758c30",
"reference": "8e30690c67aafb6c7992d6d8eb0d707807dd3eaf", "reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3457,20 +3457,20 @@
], ],
"description": "Symfony Process Component", "description": "Symfony Process Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-05-22T12:32:03+00:00" "time": "2017-07-03T08:12:02+00:00"
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "39804eeafea5cca851946e1eed122eb94459fdb4" "reference": "dc70bbd0ca7b19259f63cdacc8af370bc32a4728"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/39804eeafea5cca851946e1eed122eb94459fdb4", "url": "https://api.github.com/repos/symfony/routing/zipball/dc70bbd0ca7b19259f63cdacc8af370bc32a4728",
"reference": "39804eeafea5cca851946e1eed122eb94459fdb4", "reference": "dc70bbd0ca7b19259f63cdacc8af370bc32a4728",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3535,20 +3535,20 @@
"uri", "uri",
"url" "url"
], ],
"time": "2017-06-02T09:51:43+00:00" "time": "2017-06-24T09:29:48+00:00"
}, },
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation.git", "url": "https://github.com/symfony/translation.git",
"reference": "dc3b2a0c6cfff60327ba1c043a82092735397543" "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/dc3b2a0c6cfff60327ba1c043a82092735397543", "url": "https://api.github.com/repos/symfony/translation/zipball/35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
"reference": "dc3b2a0c6cfff60327ba1c043a82092735397543", "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3600,20 +3600,20 @@
], ],
"description": "Symfony Translation Component", "description": "Symfony Translation Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-05-22T07:42:36+00:00" "time": "2017-06-24T16:45:30+00:00"
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "347c4247a3e40018810b476fcd5dec36d46d08dc" "reference": "9ee920bba1d2ce877496dcafca7cbffff4dbe08a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/347c4247a3e40018810b476fcd5dec36d46d08dc", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9ee920bba1d2ce877496dcafca7cbffff4dbe08a",
"reference": "347c4247a3e40018810b476fcd5dec36d46d08dc", "reference": "9ee920bba1d2ce877496dcafca7cbffff4dbe08a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3668,7 +3668,7 @@
"debug", "debug",
"dump" "dump"
], ],
"time": "2017-06-02T09:10:29+00:00" "time": "2017-07-05T13:02:37+00:00"
}, },
{ {
"name": "tijsverkoyen/css-to-inline-styles", "name": "tijsverkoyen/css-to-inline-styles",
@ -4362,6 +4362,175 @@
], ],
"time": "2017-04-12T18:52:22+00:00" "time": "2017-04-12T18:52:22+00:00"
}, },
{
"name": "php-mock/php-mock",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock.git",
"reference": "bfa2d17d64dbf129073a7ba2051a96ce52749570"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock/zipball/bfa2d17d64dbf129073a7ba2051a96ce52749570",
"reference": "bfa2d17d64dbf129073a7ba2051a96ce52749570",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpunit/php-text-template": "^1"
},
"replace": {
"malkusch/php-mock": "*"
},
"require-dev": {
"phpunit/phpunit": "^4|^5"
},
"suggest": {
"php-mock/php-mock-mockery": "Allows using PHPMockery for Mockery integration",
"php-mock/php-mock-phpunit": "Allows integration into PHPUnit testcase with the trait PHPMock."
},
"type": "library",
"autoload": {
"psr-4": {
"phpmock\\": [
"classes/",
"tests/unit/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.",
"homepage": "https://github.com/php-mock/php-mock",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"stub",
"test",
"test double"
],
"time": "2015-11-11T22:37:09+00:00"
},
{
"name": "php-mock/php-mock-integration",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-integration.git",
"reference": "e83fb65dd20cd3cf250d554cbd4682b96b684f4b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/e83fb65dd20cd3cf250d554cbd4682b96b684f4b",
"reference": "e83fb65dd20cd3cf250d554cbd4682b96b684f4b",
"shasum": ""
},
"require": {
"php": ">=5.5",
"php-mock/php-mock": "^1",
"phpunit/php-text-template": "^1"
},
"require-dev": {
"phpunit/phpunit": "^4|^5"
},
"type": "library",
"autoload": {
"psr-4": {
"phpmock\\integration\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "Integration package for PHP-Mock",
"homepage": "https://github.com/php-mock/php-mock-integration",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"stub",
"test",
"test double"
],
"time": "2015-10-26T21:21:42+00:00"
},
{
"name": "php-mock/php-mock-phpunit",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-phpunit.git",
"reference": "359e3038c016cee4c8f8db6387bcab3fcdebada0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/359e3038c016cee4c8f8db6387bcab3fcdebada0",
"reference": "359e3038c016cee4c8f8db6387bcab3fcdebada0",
"shasum": ""
},
"require": {
"php": ">=5.5",
"php-mock/php-mock-integration": "^1",
"phpunit/phpunit": "^4.0.0 || ^5.0.0"
},
"conflict": {
"phpunit/phpunit-mock-objects": "3.2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"phpmock\\phpunit\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.",
"homepage": "https://github.com/php-mock/php-mock-phpunit",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"phpunit",
"stub",
"test",
"test double"
],
"time": "2016-06-15T23:36:13+00:00"
},
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
"version": "1.0", "version": "1.0",
@ -4904,16 +5073,16 @@
}, },
{ {
"name": "phpunit/phpunit-mock-objects", "name": "phpunit/phpunit-mock-objects",
"version": "3.4.3", "version": "3.4.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" "reference": "a23b761686d50a560cc56233b9ecf49597cc9118"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118",
"reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "reference": "a23b761686d50a560cc56233b9ecf49597cc9118",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4959,7 +5128,7 @@
"mock", "mock",
"xunit" "xunit"
], ],
"time": "2016-12-08T20:27:08+00:00" "time": "2017-06-30T09:13:00+00:00"
}, },
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
@ -5586,7 +5755,7 @@
}, },
{ {
"name": "symfony/class-loader", "name": "symfony/class-loader",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/class-loader.git", "url": "https://github.com/symfony/class-loader.git",
@ -5642,16 +5811,16 @@
}, },
{ {
"name": "symfony/config", "name": "symfony/config",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/config.git", "url": "https://github.com/symfony/config.git",
"reference": "35716d4904e0506a7a5a9bcf23f854aeb5719bca" "reference": "a094618deb9a3fe1c3cf500a796e167d0495a274"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/35716d4904e0506a7a5a9bcf23f854aeb5719bca", "url": "https://api.github.com/repos/symfony/config/zipball/a094618deb9a3fe1c3cf500a796e167d0495a274",
"reference": "35716d4904e0506a7a5a9bcf23f854aeb5719bca", "reference": "a094618deb9a3fe1c3cf500a796e167d0495a274",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5659,10 +5828,12 @@
"symfony/filesystem": "~2.8|~3.0" "symfony/filesystem": "~2.8|~3.0"
}, },
"conflict": { "conflict": {
"symfony/dependency-injection": "<3.3" "symfony/dependency-injection": "<3.3",
"symfony/finder": "<3.3"
}, },
"require-dev": { "require-dev": {
"symfony/dependency-injection": "~3.3", "symfony/dependency-injection": "~3.3",
"symfony/finder": "~3.3",
"symfony/yaml": "~3.0" "symfony/yaml": "~3.0"
}, },
"suggest": { "suggest": {
@ -5698,20 +5869,20 @@
], ],
"description": "Symfony Config Component", "description": "Symfony Config Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-02T18:07:20+00:00" "time": "2017-06-16T12:40:34+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "c709670bf64721202ddbe4162846f250735842c0" "reference": "311fa718389efbd8b627c272b9324a62437018cc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/c709670bf64721202ddbe4162846f250735842c0", "url": "https://api.github.com/repos/symfony/filesystem/zipball/311fa718389efbd8b627c272b9324a62437018cc",
"reference": "c709670bf64721202ddbe4162846f250735842c0", "reference": "311fa718389efbd8b627c272b9324a62437018cc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5747,11 +5918,11 @@
], ],
"description": "Symfony Filesystem Component", "description": "Symfony Filesystem Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-05-28T14:08:56+00:00" "time": "2017-06-24T09:29:48+00:00"
}, },
{ {
"name": "symfony/stopwatch", "name": "symfony/stopwatch",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/stopwatch.git", "url": "https://github.com/symfony/stopwatch.git",
@ -5800,16 +5971,16 @@
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v3.3.2", "version": "v3.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063" "reference": "1f93a8d19b8241617f5074a123e282575b821df8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/9752a30000a8ca9f4b34b5227d15d0101b96b063", "url": "https://api.github.com/repos/symfony/yaml/zipball/1f93a8d19b8241617f5074a123e282575b821df8",
"reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063", "reference": "1f93a8d19b8241617f5074a123e282575b821df8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5851,7 +6022,7 @@
], ],
"description": "Symfony Yaml Component", "description": "Symfony Yaml Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-02T22:05:06+00:00" "time": "2017-06-15T12:58:50+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",

View file

@ -0,0 +1,127 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Tests\Unit\Services;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Database\ConnectionInterface;
use Mockery as m;
use phpmock\phpunit\PHPMock;
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
use Pterodactyl\Services\ApiKeyService;
use Pterodactyl\Services\ApiPermissionService;
use Tests\TestCase;
class ApiKeyServiceTest extends TestCase
{
use PHPMock;
/**
* @var \Illuminate\Database\ConnectionInterface
*/
protected $database;
/**
* @var \Illuminate\Contracts\Encryption\Encrypter
*/
protected $encrypter;
/**
* @var \Pterodactyl\Services\ApiPermissionService
*/
protected $permissions;
/**
* @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface
*/
protected $repository;
/**
* @var \Pterodactyl\Services\ApiKeyService
*/
protected $service;
public function setUp()
{
parent::setUp();
$this->database = m::mock(ConnectionInterface::class);
$this->encrypter = m::mock(Encrypter::class);
$this->permissions = m::mock(ApiPermissionService::class);
$this->repository = m::mock(ApiKeyRepositoryInterface::class);
$this->service = new ApiKeyService(
$this->repository, $this->database, $this->encrypter, $this->permissions
);
}
/**
* Test that the service is able to create a keypair and assign the correct permissions.
*/
public function test_create_function()
{
$this->getFunctionMock('\\Pterodactyl\\Services', 'random_bytes')
->expects($this->exactly(2))
->willReturnCallback(function ($bytes) {
return hex2bin(str_pad('', $bytes * 2, '0'));
});
$this->database->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
$this->encrypter->shouldReceive('encrypt')->with(str_pad('', 64, '0'))
->once()->andReturn('encrypted-secret');
$this->repository->shouldReceive('create')->with([
'test-data' => 'test',
'public' => str_pad('', 16, '0'),
'secret' => 'encrypted-secret',
], true, true)->once()->andReturn((object) ['id' => 1]);
$this->permissions->shouldReceive('getPermissions')->withNoArgs()->once()->andReturn([
'_user' => ['server' => ['list']],
'server' => ['create'],
]);
$this->permissions->shouldReceive('create')->with(1, 'user.server-list')->once()->andReturnNull();
$this->permissions->shouldReceive('create')->with(1, 'server-create')->once()->andReturnNull();
$this->database->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
$response = $this->service->create(
['test-data' => 'test'], ['invalid-node', 'server-list'], ['invalid-node', 'server-create']
);
$this->assertNotEmpty($response);
$this->assertEquals(str_pad('', 64, '0'), $response);
}
/**
* Test that an API key can be revoked.
*/
public function test_revoke_function()
{
$this->repository->shouldReceive('delete')->with(1)->once()->andReturn(true);
$this->assertTrue($this->service->revoke(1));
}
}

View file

@ -0,0 +1,77 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Tests\Unit\Services;
use Mockery as m;
use Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface;
use Pterodactyl\Models\APIPermission;
use Pterodactyl\Services\ApiPermissionService;
use Tests\TestCase;
class ApiPermissionServiceTest extends TestCase
{
/**
* @var \Pterodactyl\Contracts\Repository\ApiPermissionRepositoryInterface
*/
protected $repository;
/**
* @var \Pterodactyl\Services\ApiPermissionService
*/
protected $service;
/**
* Setup tests.
*/
public function setUp()
{
parent::setUp();
$this->repository = m::mock(ApiPermissionRepositoryInterface::class);
$this->service = new ApiPermissionService($this->repository);
}
/**
* Test that a new API permission can be assigned to a key.
*/
public function test_create_function()
{
$this->repository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf()
->shouldReceive('create')->with(['key_id' => 1, 'permission' => 'test-permission'])
->once()->andReturn(true);
$this->assertTrue($this->service->create(1, 'test-permission'));
}
/**
* Test that function returns an array of all the permissions available as defined on the model.
*/
public function test_get_permissions_function()
{
$this->repository->shouldReceive('getModel')->withNoArgs()->once()->andReturn(new APIPermission());
$this->assertEquals(APIPermission::CONST_PERMISSIONS, $this->service->getPermissions());
}
}