Skip to content

Commit

Permalink
testing
Browse files Browse the repository at this point in the history
  • Loading branch information
rohsyl committed Nov 24, 2022
1 parent 881016a commit a97ba42
Show file tree
Hide file tree
Showing 13 changed files with 711 additions and 68 deletions.
65 changes: 54 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ php artisan otc:install
## Configuration

Edit `config/otc.php`
```
<?php
```php
return [
'notifier_class' => \Illuminate\Support\Facades\Notification::class,
'notification_class' => \rohsyl\LaravelOtc\Notifications\OneTimeCodeNotification::class,
Expand All @@ -40,6 +39,44 @@ return [
];
```

### notifier_class
Define what class will be called to send the notification. By default it use the Notification facade of Laravel.
```php
'notifier_class' => \Illuminate\Support\Facades\Notification::class,
```

### notification_class
Define what notification will be sent.
```
'notification_class' => \rohsyl\LaravelOtc\Notifications\OneTimeCodeNotification::class,
```

You can replace this class by any other notification, you will recieve a `OtcToken $token` as constructor parameters
```php
public function __construct(OtcToken $token) {
$this->token = $token;
}
```

You can access the code that need to be sent from the `$token` variable
```php
$token->code
```

### authenticatables

This array will define a list of entites that can be used to get authentified.

- `user` is the name of the "guard"/type
- `model` is the corresponding eloquent model
- `identifier` is the identifier column that will be used to find the corresponding user
```php
'user' => [
'model' => \App\Models\User::class,
'identifier' => 'email',
]
```

## Usage

### Check
Expand All @@ -51,15 +88,15 @@ Otc::check()

If the user is not authentified you can return an error
```php
return Otc::unauthorizedResponse($lease);
return Otc::unauthorizedResponse($user);
```
This response will return 401 http error with the following body.
```
```json
{
"request_code_url": "http://localhost:8001/vendor/rohsyl/laravel-otc/auth/request-code",
"request_code_url": ".../vendor/rohsyl/laravel-otc/auth/request-code",
"request_code_body": {
"type": "lease",
"identifier": "LS-41203"
"type": "user",
"identifier": "[email protected]"
}
}
```
Expand All @@ -69,6 +106,9 @@ You must use the `request_code_url` as the url to request a code (ye seem obviou
Send a post request
```
POST /vendor/rohsyl/laravel-otc/auth/request-code
```
with body
```json
{
"type": "user",
"identifier": "[email protected]"
Expand All @@ -78,20 +118,23 @@ POST /vendor/rohsyl/laravel-otc/auth/request-code
An email will be sent to the corresponding entity if available. The email will contain the code.

### Request bearer token
### Request a token
Send a post request
```
POST /vendor/rohsyl/laravel-otc/auth/code
```
with body
```json
{
"type": "user",
"identifier": "[email protected]"
"identifier": "[email protected]",
"code": <code>
}
```
> You need to send the `code` that should have been retrieved from the user through a form or anything else.
You will recieve a token back
```
```json
{
"token": "9vov6FjW47v6JjH...4iPzPH0PwpwdE"
}
Expand All @@ -115,7 +158,7 @@ Or in the query string

### Testing

``` bash
```bash
composer test
```

Expand Down
22 changes: 22 additions & 0 deletions database/factories/OtcTokenFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
namespace rohsyl\LaravelOtc\Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use rohsyl\LaravelOtc\Models\OtcToken;

class OtcTokenFactory extends Factory
{
protected $model = OtcToken::class;

/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'ip' => '127.0.0.1',
];
}
}
21 changes: 21 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" backupStaticAttributes="false" colors="true" verbose="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
<html outputDirectory="build/coverage"/>
<text outputFile="build/coverage.txt"/>
</report>
</coverage>
<testsuites>
<testsuite name="Otc Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<logging>
<junit outputFile="build/report.junit.xml"/>
</logging>
</phpunit>
29 changes: 0 additions & 29 deletions phpunit.xml.dist

This file was deleted.

37 changes: 23 additions & 14 deletions src/LaravelOtcManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class LaravelOtcManager
{
private $generator;
private $request;

public function __construct(
GeneratorContract $generator
Expand All @@ -27,8 +28,8 @@ public function __construct(
*/
public function check()
{
$token = request()->bearerToken() ?? (
request()->has('token') ? request()->token : null
$token = $this->getRequest()->bearerToken() ?? (
$this->getRequest()->has('token') ? $this->getRequest()->token : null
);

if(!isset($token)) return false;
Expand All @@ -52,7 +53,7 @@ public function unauthorizedResponse(Model $related) : Response

$identifierColumn = config('otc.authenticatables.' . $slug . '.identifier');

if (request()->wantsJson()) {
if ($this->getRequest()->wantsJson()) {
return response()->json([
'request_code_url' => route('laravel-otc.request-code'),
'request_code_body' => [
Expand All @@ -70,16 +71,16 @@ public function storeCode(Model $related, $code) : OtcToken
return OtcToken::create([
'related_type' => get_class($related),
'related_id' => $related->id,
'ip' => request()->ip(),
'ip' => $this->getRequest()->ip(),
'code' => $code,
'code_valid_until' => now()->addMinutes(30),
]);
}

public function getModel() : Model
{
$slug = request()->type;
$identifier = request()->identifier;
$slug = $this->getRequest()->type;
$identifier = $this->getRequest()->identifier;

$modelClass = config('otc.authenticatables.' . $slug . '.model');
$identifierColumn = config('otc.authenticatables.' . $slug . '.identifier');
Expand All @@ -89,10 +90,10 @@ public function getModel() : Model

public function checkCode(OtcToken $token = null)
{
$token = $token ?? $this->findOtcTokenByRelatedAndCode($this->getModel(), request()->code);
$token = $token ?? $this->findOtcTokenByRelatedAndCode($this->getModel(), $this->getRequest()->code);

return isset($token)
&& $token->code == request()->code
&& $token->code == $this->getRequest()->code
&& $token->code_valid_until->isAfter(now());
}

Expand All @@ -117,10 +118,10 @@ public function sendCode(?Model $related = null, ?OtcToken $token = null)

$notifierClass = config('otc.notifier_class');
$notificationClass = config('otc.notification_class');
if(!class_exists($notifierClass)) {
if(!isset($notifierClass) || !class_exists($notifierClass)) {
$notifierClass = Notification::class;
}
if(!class_exists($notificationClass)) {
if(!isset($notificationClass) || !class_exists($notificationClass)) {
$notificationClass = OneTimeCodeNotification::class;
}
call_user_func_array(
Expand All @@ -142,21 +143,21 @@ public function findOtcTokenByRelatedAndCode(Model $related, $code) : ?OtcToken
return OtcToken::query()
->where('related_id', $related->id)
->where('related_type', get_class($related))
->where('ip', request()->ip())
->where('ip', $this->getRequest()->ip())
->where('code', $code)
->latest()
->first();
}

private function findOtcTokenByRelated(Model $related) : ?OtcToken
/*private function findOtcTokenByRelated(Model $related) : ?OtcToken
{
return OtcToken::query()
->where('related_id', $related->id)
->where('related_type', get_class($related))
->where('id', request()->ip())
->where('id', $this->getRequest()->ip())
->latest()
->first();
}
}*/

private function getModelSlug(Model $related) {
$authenticatables = config('otc.authenticatables');
Expand All @@ -167,4 +168,12 @@ private function getModelSlug(Model $related) {
}
return null;
}

private function getRequest() {
return $this->request ?? request();
}

public function setTestRequest($request) {
$this->request = $request;
}
}
8 changes: 8 additions & 0 deletions src/Models/OtcToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace rohsyl\LaravelOtc\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use rohsyl\LaravelOtc\Database\Factories\OtcTokenFactory;

class OtcToken extends Model
{
use HasFactory;

public $fillable = [
'related_id',
Expand All @@ -25,4 +28,9 @@ class OtcToken extends Model
public function related() {
return $this->morphTo('related');
}

protected static function newFactory()
{
return OtcTokenFactory::new();
}
}
Loading

0 comments on commit a97ba42

Please sign in to comment.