Commit 3e51d4cb authored by Jacob Priddy's avatar Jacob Priddy 👌

sort out doorcode hashing... Also progress on authorization

parent 7036407b
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
namespace App; namespace App;
class Group use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Group extends Model
{ {
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function groups(): BelongsToMany
{
return $this->belongsToMany(User::class);
}
} }
...@@ -5,6 +5,7 @@ namespace App; ...@@ -5,6 +5,7 @@ namespace App;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class User extends Authenticatable class User extends Authenticatable
{ {
...@@ -24,10 +25,18 @@ class User extends Authenticatable ...@@ -24,10 +25,18 @@ class User extends Authenticatable
]; ];
/** /**
* @return HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */
public function tokens(): HasMany public function tokens(): HasMany
{ {
return $this->hasMany(Token::class); return $this->hasMany(Token::class);
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function groups(): BelongsToMany
{
return $this->belongsToMany(Group::class);
}
} }
<?php
namespace Source\Authorization;
use Illuminate\Contracts\Auth\Guard;
use Source\Exceptions\AuthorizationException;
class ApiAuthorizer implements Authorizer
{
protected Guard $guard;
public function __construct(Guard $guard)
{
$this->guard = $guard;
}
/**
* @inheritDoc
*/
public function allows(array $permissions): bool
{
$user = $this->guard->user();
if (!$user) {
return false;
}
return true;
}
/**
* @inheritDoc
*/
public function protect(array $permissions): void
{
if (!$this->allows($permissions)) {
throw new AuthorizationException();
}
}
}
<?php
namespace Source\Authorization;
interface Authorizer
{
/**
* @param array $permissions
* @return bool
*/
public function allows(array $permissions): bool;
/**
* @param array $permissions
* @throws \Source\Exceptions\AuthorizationException
*/
public function protect(array $permissions): void;
}
<?php
namespace Source\Authorization;
class Permissions
{
public const ADMIN = 'admin';
public const MODIFY_USER = 'user:modify';
public const READ_USERS = 'user:read';
}
...@@ -5,8 +5,20 @@ namespace Source\Gateways\Users; ...@@ -5,8 +5,20 @@ namespace Source\Gateways\Users;
use Source\Entities\User; use Source\Entities\User;
// TODO: Write tests for this
class DatabaseUsersRepository implements UsersRepository class DatabaseUsersRepository implements UsersRepository
{ {
protected function secureDoorcode(string $doorcode): string
{
// As of PHP 7 the salt parameter to password_hash has been depreciated.
// As we need to be able to search for users by doorcode they either all need to have the same salt
// (in this case, the app key) or no salt (I'd prefer a salt). This way the doorcode can be hashed and
// then easily searched for in the database without having to check against every user and rehash every
// time with the new salt. As such it is not as easy to use BCRYPT :(
// So I'll just shred it twice using sha512 with with the application key.
return hash('sha512', hash('sha512', $doorcode . config('app.key')));
}
/** /**
* @inheritDoc * @inheritDoc
*/ */
...@@ -84,7 +96,7 @@ class DatabaseUsersRepository implements UsersRepository ...@@ -84,7 +96,7 @@ class DatabaseUsersRepository implements UsersRepository
); );
} }
protected function fillBasicUserAttrs(User $user, \App\User $dbUser): \App\User protected function fillBasicUserAttrs(User $user, \App\User $dbUser, bool $includeDoorcode = true): \App\User
{ {
$dbUser->first_name = $user->getFirstName(); $dbUser->first_name = $user->getFirstName();
$dbUser->last_name = $user->getLastName(); $dbUser->last_name = $user->getLastName();
...@@ -92,8 +104,14 @@ class DatabaseUsersRepository implements UsersRepository ...@@ -92,8 +104,14 @@ class DatabaseUsersRepository implements UsersRepository
$dbUser->emplid = $user->getEmplid(); $dbUser->emplid = $user->getEmplid();
$dbUser->email = $user->getEmail(); $dbUser->email = $user->getEmail();
$dbUser->password = bcrypt($user->getPassword()); $dbUser->password = bcrypt($user->getPassword());
$dbUser->doorcode = hash('sha256', $user->getDoorcode());
$dbUser->expires_at = $user->getExpiresAt(); $dbUser->expires_at = $user->getExpiresAt();
// If the doorcode exists and is the same as provided, don't change
// Else regenerate
if (!isset($dbUser->doorcode) || (isset($dbUser->doorcode) && $dbUser->doorcode !== $user->getDoorcode())) {
$dbUser->doorcode = $this->secureDoorcode($user->getDoorcode());
}
return $dbUser; return $dbUser;
} }
...@@ -179,7 +197,7 @@ class DatabaseUsersRepository implements UsersRepository ...@@ -179,7 +197,7 @@ class DatabaseUsersRepository implements UsersRepository
*/ */
public function findByDoorcode(string $doorcode): ?User public function findByDoorcode(string $doorcode): ?User
{ {
$doorcode = hash('sha256', $doorcode); $doorcode = $this->secureDoorcode($doorcode);
$user = \App\User::where('doorcode', $doorcode)->first(); $user = \App\User::where('doorcode', $doorcode)->first();
......
...@@ -136,7 +136,7 @@ class UseCaseTest extends TestCase ...@@ -136,7 +136,7 @@ class UseCaseTest extends TestCase
$this->handleTest('69', $this->createUserAttributes($updatedUser, null, null)); $this->handleTest('69', $this->createUserAttributes($updatedUser, null, null));
$this->assertEquals('pass', $this->response->getUser()->getPassword()); $this->assertEquals('pass', $this->response->getUser()->getPassword());
$this->assertEquals('door', $this->response->getUser()->getDoorcode()); $this->assertEquals(null, $this->response->getUser()->getDoorcode());
} }
/** /**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment