Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/customization/route_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ $routes->get('login', '\App\Controllers\Auth\LoginController::loginView');
$routes->get('register', '\App\Controllers\Auth\RegisterController::registerView');
```

If you only need a specific route (or a small set of routes), you can use the `only` option instead

```php
service('auth')->routes($routes, ['only' => ['login']]);
```

In this case, you must manage all other routes manually.

After customization, check your routes with the [spark routes](https://codeigniter.com/user_guide/incoming/routing.html#spark-routes) command.

## Change Namespace
Expand Down
8 changes: 8 additions & 0 deletions docs/quick_start_guide/using_session_auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ $routes->get('login', '\App\Controllers\Auth\LoginController::loginView');
$routes->get('register', '\App\Controllers\Auth\RegisterController::registerView');
```

If you only need a specific route (or a small set of routes), you can use the `only` option instead

```php
service('auth')->routes($routes, ['only' => ['login']]);
```

In this case, you must manage all other routes manually.

Check your routes with the [spark routes](https://codeigniter.com/user_guide/incoming/routing.html#spark-routes)
command.

Expand Down
12 changes: 0 additions & 12 deletions phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -427,18 +427,6 @@
'count' => 1,
'path' => __DIR__ . '/tests/Authentication/Authenticators/SessionAuthenticatorTest.php',
];
$ignoreErrors[] = [
'rawMessage' => 'Parameter #1 $headers of method Tests\\Authentication\\Filters\\AbstractFilterTestCase::withHeaders() expects array<string, CodeIgniter\\HTTP\\Header|list<CodeIgniter\\HTTP\\Header>>, array{Authorization: non-falsy-string} given.',
'identifier' => 'argument.type',
'count' => 7,
'path' => __DIR__ . '/tests/Authentication/Filters/HmacFilterTest.php',
];
$ignoreErrors[] = [
'rawMessage' => 'Parameter #1 $headers of method Tests\\Authentication\\Filters\\JWTFilterTest::withHeaders() expects array<string, CodeIgniter\\HTTP\\Header|list<CodeIgniter\\HTTP\\Header>>, array{Authorization: non-falsy-string} given.',
'identifier' => 'argument.type',
'count' => 1,
'path' => __DIR__ . '/tests/Authentication/Filters/JWTFilterTest.php',
];
$ignoreErrors[] = [
'rawMessage' => 'Implicit array creation is not allowed - variable $users might not exist.',
'identifier' => 'variable.implicitArray',
Expand Down
4 changes: 0 additions & 4 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php81\Rector\ClassMethod\NewInInitializerRector;
use Rector\PHPUnit\AnnotationsToAttributes\Rector\Class_\AnnotationWithValueToAttributeRector;
use Rector\PHPUnit\CodeQuality\Rector\Class_\YieldDataProviderRector;
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertEmptyNullableObjectToAssertInstanceofRector;
Expand Down Expand Up @@ -138,9 +137,6 @@
// Ignore some PHPUnit rules
AssertEmptyNullableObjectToAssertInstanceofRector::class,

// Ignore to prevent BC break
NewInInitializerRector::class,

// Ignore for readability
RemoveNullArgOnNullDefaultParamRector::class,
]);
Expand Down
17 changes: 16 additions & 1 deletion src/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use CodeIgniter\Shield\Config\Auth as AuthConfig;
use CodeIgniter\Shield\Entities\User;
use CodeIgniter\Shield\Models\UserModel;
use InvalidArgumentException;

/**
* Facade for Authentication
Expand Down Expand Up @@ -134,13 +135,27 @@ public function authenticate(array $credentials): Result
*/
public function routes(RouteCollection &$routes, array $config = []): void
{
if (isset($config['only'], $config['except'])) {
throw new InvalidArgumentException(
'The "only" and "except" options cannot be used at the same time.',
);
}

$authRoutes = config('AuthRoutes')->routes;

$namespace = $config['namespace'] ?? 'CodeIgniter\Shield\Controllers';

$routes->group('/', ['namespace' => $namespace], static function (RouteCollection $routes) use ($authRoutes, $config): void {
foreach ($authRoutes as $name => $row) {
if (! isset($config['except']) || ! in_array($name, $config['except'], true)) {
$shouldInclude = true;

if (isset($config['only'])) {
$shouldInclude = in_array($name, $config['only'], true);
} elseif (isset($config['except'])) {
$shouldInclude = ! in_array($name, $config['except'], true);
}

if ($shouldInclude) {
foreach ($row as $params) {
$options = isset($params[3])
? ['as' => $params[3]]
Expand Down
4 changes: 1 addition & 3 deletions src/Authentication/Authenticators/JWT.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,7 @@ public function getTokenFromRequest(RequestInterface $request): string
/** @var AuthJWT $config */
$config = config('AuthJWT');

$tokenHeader = $request->getHeaderLine(
$config->authenticatorHeader ?? 'Authorization',
);
$tokenHeader = $request->getHeaderLine($config->authenticatorHeader);

if (str_starts_with($tokenHeader, 'Bearer')) {
return trim(substr($tokenHeader, 6));
Expand Down
2 changes: 1 addition & 1 deletion src/Authentication/Authenticators/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ private function recordLoginAttempt(
// Determine the type of ID we're using.
// Standard fields would be email, username,
// but any column within config('Auth')->validFields can be used.
$field = array_intersect(config('Auth')->validFields ?? [], array_keys($credentials));
$field = array_intersect(config('Auth')->validFields, array_keys($credentials));

if (count($field) !== 1) {
throw new InvalidArgumentException('Invalid credentials passed to recordLoginAttempt.');
Expand Down
4 changes: 2 additions & 2 deletions src/Config/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

class Auth extends BaseConfig
{
/**
/*
* ////////////////////////////////////////////////////////////////////
* AUTHENTICATION
* ////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -378,7 +378,7 @@ class Auth extends BaseConfig
*/
public int $hashCost = 12;

/**
/*
* ////////////////////////////////////////////////////////////////////
* OTHER SETTINGS
* ////////////////////////////////////////////////////////////////////
Expand Down
9 changes: 3 additions & 6 deletions tests/Authentication/MagicLinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ public function testMagicLinkSubmitBadEmail(): void

public function testMagicLinkSubmitSuccess(): void
{
/**
* @phpstan-var User
*/
/** @phpstan-var User $user */
$user = fake(UserModel::class);
$user->createEmailIdentity(['email' => 'foo@example.com', 'password' => 'secret123']);

Expand Down Expand Up @@ -105,9 +103,8 @@ public function testMagicLinkVerifyNoToken(): void
public function testMagicLinkVerifyExpired(): void
{
$identities = new UserIdentityModel();
/**
* @phpstan-var User
*/

/** @phpstan-var User $user */
$user = fake(UserModel::class);
$user->createEmailIdentity(['email' => 'foo@example.com', 'password' => 'secret123']);
$identities->insert([
Expand Down
3 changes: 1 addition & 2 deletions tests/Language/AbstractTranslationTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,7 @@ final public function testAllIncludedLanguageKeysAreTranslated(string $locale):
{
// These keys are usually not translated because they contain either
// universal abbreviations or simply combine parameters with signs.
static $excludedKeyTranslations = [
];
static $excludedKeyTranslations = [];

$excludedKeys = array_unique(array_merge($excludedKeyTranslations, $this->excludedLocaleKeyTranslations));
$availableSets = array_intersect($this->expectedSets(), $this->foundSets($locale));
Expand Down
31 changes: 31 additions & 0 deletions tests/Unit/AuthRoutesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use CodeIgniter\CodeIgniter;
use CodeIgniter\Router\RouteCollection;
use CodeIgniter\Shield\Auth;
use InvalidArgumentException;
use Tests\Support\TestCase;

/**
Expand Down Expand Up @@ -65,6 +66,36 @@ public function testRoutesExcept(): void
$this->assertArrayHasKey('auth/a/show', $routes);
}

public function testRoutesOnly(): void
{
$collection = single_service('routes');
$auth = service('auth');

$auth->routes($collection, ['only' => ['login']]);

if (version_compare(CodeIgniter::CI_VERSION, '4.5') >= 0) {
$routes = $collection->getRoutes('GET');
} else {
$routes = $collection->getRoutes('get');
}

$this->assertArrayHasKey('login', $routes);
$this->assertArrayNotHasKey('register', $routes);
$this->assertArrayNotHasKey('login/magic-link', $routes);
$this->assertArrayNotHasKey('logout', $routes);
$this->assertArrayNotHasKey('auth/a/show', $routes);
}

public function testRoutesUseOnlyAndExceptOptionsSimultaneous(): void
{
$this->expectException(InvalidArgumentException::class);

$collection = single_service('routes');
$auth = service('auth');

$auth->routes($collection, ['only' => ['login'], 'except' => ['register']]);
}

public function testRoutesCustomNamespace(): void
{
$collection = single_service('routes');
Expand Down
1 change: 0 additions & 1 deletion tests/Unit/UserIdentityModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ public function testCreateCodeIdentityThrowsExceptionIfUniqueCodeIsNotGot(): voi

public function testForceMultiplePasswordReset(): void
{
/** @var Fabricator $fabricator */
$fabricator = new Fabricator(UserIdentityModel::class);
$fabricator->create(10);

Expand Down