Skip to content

Commit

Permalink
feat: auto assign users upon registration
Browse files Browse the repository at this point in the history
  • Loading branch information
fdalcin committed Feb 6, 2024
1 parent 3bf73f8 commit 91c78ac
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 2 deletions.
35 changes: 35 additions & 0 deletions src/Actions/AssignUserToInstitution.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace PressbooksMultiInstitution\Actions;

use Illuminate\Support\Str;
use PressbooksMultiInstitution\Models\Institution;

class AssignUserToInstitution
{
public function handle(int $userId): bool
{
$user = get_userdata($userId);

if (! $user) {
return false;
}

$email = Str::of($user->user_email);

$domain = (string) $email->after('@')->trim();

/** @var Institution $institution */
$institution = Institution::query()->whereRelation('domains', 'domain', $domain)->first();

if (! $institution) {
return false;
}

$institution->users()->create([
'user_id' => $userId,
]);

return true;
}
}
3 changes: 3 additions & 0 deletions src/Bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PressbooksMultiInstitution;

use Kucrut\Vite;
use PressbooksMultiInstitution\Actions\AssignUserToInstitution;
use PressbooksMultiInstitution\Controllers\InstitutionsController;

/**
Expand Down Expand Up @@ -72,6 +73,8 @@ private function registerActions(): void
{
add_action('network_admin_menu', [$this, 'registerMenus'], 11);
// TODO: register menu at the main site level

add_action('user_register', fn (int $id) => app(AssignUserToInstitution::class)->handle($id));
}

private function registerBlade(): void
Expand Down
Empty file removed tests/Feature/.gitkeep
Empty file.
190 changes: 190 additions & 0 deletions tests/Feature/Actions/AssignUserToInstitutionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?php

namespace Tests\Feature\Actions;

use Illuminate\Database\Capsule\Manager;
use PressbooksMultiInstitution\Bootstrap;
use PressbooksMultiInstitution\Models\Institution;
use PressbooksMultiInstitution\Actions\AssignUserToInstitution;
use PressbooksMultiInstitution\Models\InstitutionUser;
use ReflectionFunction;
use Tests\TestCase;

class AssignUserToInstitutionTest extends TestCase
{
/**
* @test
*/
public function it_register_hook_action(): void
{
$this->assertTrue(
has_action('user_register')
);

$this->assertHasCallbackAction('user_register', Bootstrap::class);
}

/**
* @test
*/
public function it_associates_users_with_institutions(): void
{
$id = $this->newUser([
'user_email' => 'johndoe@fakedomain.edu',
]);

/** @var Institution $institution */
$institution = Institution::query()->create([
'name' => 'Fake Institution',
]);

$institution->domains()->create([
'domain' => 'fakedomain.edu',
]);

$this->assertDatabaseEmpty('institutions_users');

$this->assertTrue(
(new AssignUserToInstitution)->handle($id)
);

$this->assertDatabaseCount('institutions_users', 1);

$this->assertEquals(
1,
InstitutionUser::query()
->where('user_id', $id)
->where('institution_id', $institution->id)
->count()
);
}

/**
* @test
*/
public function it_does_not_associate_when_email_domain_does_not_match(): void
{
$id = $this->newUser([
'user_email' => 'johndoe@anotherfakedomain.edu',
]);

/** @var Institution $institution */
$institution = Institution::query()->create([
'name' => 'Fake Institution',
]);

$institution->domains()->create([
'domain' => 'fakedomain.edu',
]);

$this->assertDatabaseEmpty('institutions_users');

$this->assertFalse(
(new AssignUserToInstitution)->handle($id)
);

$this->assertDatabaseEmpty('institutions_users');
}

/**
* @test
*/
public function it_does_not_associate_invalid_users(): void
{
$this->newUser([
'user_email' => 'johndoe@fakedomain.edu',
]);

/** @var Institution $institution */
$institution = Institution::query()->create([
'name' => 'Fake Institution',
]);

$institution->domains()->create([
'domain' => 'fakedomain.edu',
]);

$this->assertDatabaseEmpty('institutions_users');

$this->assertFalse(
(new AssignUserToInstitution)->handle(9999)
);

$this->assertDatabaseEmpty('institutions_users');
}

/**
* @test
*/
public function it_does_not_associate_when_there_are_no_institutions(): void
{
$id = $this->newUser([
'user_email' => 'johndoe@fakedomain.edu',
]);

$this->assertDatabaseEmpty('institutions_users');

$this->assertFalse(
(new AssignUserToInstitution)->handle($id)
);

$this->assertDatabaseEmpty('institutions_users');
}

protected function assertDatabaseCount(string $table, int $count): void
{
/** @var Manager $db */
$db = app('db');

$this->assertEquals($count, $db->table($table)->count());
}

protected function assertDatabaseEmpty(string $table): void
{
$this->assertDatabaseCount($table, 0);
}

protected function assertHasCallbackAction(string $hook, string $class): bool
{
global $wp_filter;

foreach ($wp_filter[$hook] ?? [] as $callbacks) {
foreach ($callbacks as $callback) {
if (is_array($callback['function'])) {
continue;
}

$closure = new ReflectionFunction($callback['function']);

if($closure->getClosureScopeClass()?->getName() === $class) {
return true;
}
}
}

return false;
}

protected function newUser(array $properties = []): int
{
global $wpdb;

$wpdb->query('START TRANSACTION');

$wpdb->delete($wpdb->users, [
'user_login' => $properties['user_login'] ?? 'johndoe',
]);

$user = $this->factory()->user->create([
'first_name' => 'John',
'last_name' => 'Doe',
'user_login' => 'johndoe',
'user_email' => 'johndoe@fakedomain.edu',
...$properties
]);

$wpdb->query('COMMIT');

return $user;
}
}
16 changes: 14 additions & 2 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@

class TestCase extends WP_UnitTestCase
{
public function setUp(): void
{
Migration::migrate();

parent::setUp();
}

public function tearDown(): void
{
parent::tearDown();

Migration::rollback();
}

public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();

Migration::migrate();

(new Bootstrap)->setUp();
}
}

0 comments on commit 91c78ac

Please sign in to comment.