Skip to content

Commit

Permalink
Merge pull request #9 from hans-thomas/feature/adding-role-model-cont…
Browse files Browse the repository at this point in the history
…ract

Create a contract for models that responsable for roles;
  • Loading branch information
hans-thomas authored Aug 17, 2023
2 parents 870841c + 2af317d commit 0bd20f1
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 65 deletions.
7 changes: 0 additions & 7 deletions .styleci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@ use-tabs: false
finder:
exclude:
- "docs"
- "modules"
- "node_modules"
- "nova"
- "nova-components"
- "storage"
- "spark"
- "vendor"
name: "*.php"
not-name:
- "*.blade.php"
- "_ide_helper.php"
2 changes: 1 addition & 1 deletion docs/content/docs/facade.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ draft = false
weight = 10
description = "To make it easy to use Sphinx."
title = "Facade"
bref= "There is a facade class to make working easier. this facade contains several methods that we will introduce in continue."
bref= "There is a facade class to make working easier. this facade contains several methods that we will introduce in continue"
toc = false
+++

Expand Down
23 changes: 21 additions & 2 deletions docs/content/docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ draft = false
weight = 9
description = "Installation guidance to install and setup Sphinx."
title = "Installation"
bref= "To install Sphinx, follow the below steps."
bref= "To install Sphinx, follow the below steps"
toc = false
+++

Expand Down Expand Up @@ -85,4 +85,23 @@ And finally, you can set the `jwt` guard as default.
],
```

All sets. enjoy!
All sets.

## Role model

Sphinx expects the role model of your project, contains requested method
on `Hans\Sphinx\Models\Contracts\RoleMethods` interface class. So, you should implement this contract and for your
convenient, there is the `Hans\Sphinx\Models\Traits\RoleMethods` trait class that contains all the methods that you must
implement.

```
use Hans\Sphinx\Models\Contracts\RoleMethods as RoleContract;
use Hans\Sphinx\Models\Traits\RoleMethods;
use Spatie\Permission\Models\Role;
class RoleDelegate extends Role implements RoleContract {
use RoleMethods;
// ...
}
```
2 changes: 1 addition & 1 deletion docs/content/docs/trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ draft = false
weight = 20
description = "A bunch of useful and handy methods."
title = "Trait"
bref= "Sphinx adds some useful and necessary methods through the trait. there is the list of available methods."
bref= "Sphinx adds some useful and necessary methods through the trait. there is the list of available methods"
toc = false
+++

Expand Down
2 changes: 1 addition & 1 deletion docs/layouts/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1>{{.Title}}</h1>
<p>{{.Description}}</p>
</div>
<div id="action-buttons">
<a class="button primary big" href="/docs">Documentation</a>
<a class="button primary big" href="/docs/installation">Installation</a>
<a class="button outline big" href="https://github.com/hans-thomas/sphinx"
onclick="_gaq.push(['_trackEvent', 'sphinx', 'github']);">View on Github</a>
</div>
Expand Down
12 changes: 11 additions & 1 deletion src/Drivers/Constraints/RoleIdValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Hans\Sphinx\Exceptions\SphinxErrorCode;
use Hans\Sphinx\Exceptions\SphinxException;
use Hans\Sphinx\Models\Contracts\RoleMethods as RoleContract;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Validation\Constraint;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
Expand Down Expand Up @@ -35,7 +36,16 @@ public function assert(Token $token): void
);
}

$role = app(sphinx_config('role_model'))->findAndCache($role_id);
$model = app(sphinx_config('role_model'));
if (!$model instanceof RoleContract) {
$modelClass = get_class($model);

throw new SphinxException(
"Role model [$modelClass] must implement the ".RoleContract::class.' contract.',
SphinxErrorCode::MUST_IMPLEMENT_ROLE_CONTRACT,
);
}
$role = $model->findAndCache($role_id);

if ($role->getVersion() != $role_version) {
throw new SphinxException(
Expand Down
1 change: 1 addition & 0 deletions src/Exceptions/SphinxErrorCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ class SphinxErrorCode
public const FAILED_TO_SET_HEADER = 1013;
public const FAILED_TO_CREATE_TOKEN = 1014;
public const FAILED_TO_CREATE_REFRESH_TOKEN = 1015;
public const MUST_IMPLEMENT_ROLE_CONTRACT = 1016;
}
29 changes: 29 additions & 0 deletions src/Models/Contracts/RoleMethods.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Hans\Sphinx\Models\Contracts;

interface RoleMethods
{
/**
* Find the given id and cache the result.
*
* @param int $id
*
* @return static
*/
public static function findAndCache(int $id): self;

/**
* Return version of the current instance.
*
* @return int
*/
public function getVersion(): int;

/**
* Increase the version by one unit.
*
* @return bool
*/
public function increaseVersion(): bool;
}
59 changes: 59 additions & 0 deletions src/Models/Traits/RoleMethods.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Hans\Sphinx\Models\Traits;

use Illuminate\Support\Facades\Cache;
use Throwable;

trait RoleMethods
{
/**
* @param int $id
*
* @return static
*/
public static function findAndCache(int $id): self
{
return Cache::rememberForever(
static::cacheKey($id),
fn () => self::query()->findOrFail($id)
);
}

/**
* @return int
*/
public function getVersion(): int
{
return $this->version ?: self::query()->findOrFail($this->id, ['id', 'version'])->version;
}

/**
* @return bool
*/
public function increaseVersion(): bool
{
try {
$this->increment('version');
$this->fill(['version' => $this->getVersion() + 1])->saveQuietly();
Cache::forget(self::cacheKey($this->id));
Cache::forever(self::cacheKey($this->id), $this);
} catch (Throwable $e) {
return false;
}

return true;
}

/**
* Make the unique key for caching the instance.
*
* @param int $id
*
* @return string
*/
protected static function cacheKey(int $id): string
{
return "role_cache_$id";
}
}
56 changes: 4 additions & 52 deletions tests/skeleton/laravel-10.x/app/Models/RoleDelegate.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,11 @@

namespace App\Models;

use Hans\Horus\Helpers\Enums\CacheEnum;
use Illuminate\Support\Facades\Cache;
use Hans\Sphinx\Models\Contracts\RoleMethods as RoleContract;
use Hans\Sphinx\Models\Traits\RoleMethods;
use Spatie\Permission\Models\Role;
use Throwable;

// TODO: not documented in horus
class RoleDelegate extends Role
class RoleDelegate extends Role implements RoleContract
{
/**
* @param int $id
*
* @return static
*/
public static function findAndCache(int $id): self
{
return Cache::rememberForever(
self::cacheKey($id),
fn () => self::query()->findOrFail($id)
);
}

/**
* @return int
*/
public function getVersion(): int
{
return $this->version ?: self::query()->findOrFail($this->id, ['id', 'version'])->version;
}

/**
* @return bool
*/
public function increaseVersion(): bool
{
try {
$this->increment('version');
$this->fill(['version' => $this->getVersion() + 1])->saveQuietly();
Cache::forget(self::cacheKey($this->id));
Cache::forever(self::cacheKey($this->id), $this);
} catch (Throwable $e) {
return false;
}

return true;
}

/**
* @param int $id
*
* @return string
*/
private static function cacheKey(int $id): string
{
return CacheEnum::ROLE->value."_$id";
}
use RoleMethods;
}

0 comments on commit 0bd20f1

Please sign in to comment.