Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c1253ee45 | ||
|
|
70bf811b1d | ||
|
|
3269151e9b | ||
|
|
1da2188bdf | ||
|
|
7cf7e04d17 |
@@ -0,0 +1,34 @@
|
|||||||
|
name: Push Develop
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
- 'develop'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: |
|
||||||
|
${{ vars.DOCKERHUB_TARGET }}:develop
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
name: Push Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*.*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: |
|
||||||
|
${{ vars.DOCKERHUB_TARGET }}:latest
|
||||||
|
${{ vars.DOCKERHUB_TARGET }}:${{ github.ref_name }}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: Sync GitHub
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Configure Git
|
||||||
|
run: |
|
||||||
|
git config --global user.name "Andrew Sync"
|
||||||
|
git config --global user.email "sync@digitaladapt.com"
|
||||||
|
|
||||||
|
- name: Add GitHub Remote
|
||||||
|
env:
|
||||||
|
SYNC_TOKEN: ${{ secrets.SYNC_GITHUB_TOKEN }}
|
||||||
|
SYNC_TARGET: ${{ vars.SYNC_GITHUB_TARGET }}
|
||||||
|
run: |
|
||||||
|
git remote add github "https://digitaladapt:${SYNC_TOKEN}@github.com/$SYNC_TARGET"
|
||||||
|
|
||||||
|
- name: Push Current Branch
|
||||||
|
run: |
|
||||||
|
git push github HEAD:${GITHUB_REF_NAME}
|
||||||
|
|
||||||
|
- name: Push Tags
|
||||||
|
run: |
|
||||||
|
git push github --tags
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Command;
|
namespace App\Command;
|
||||||
|
|
||||||
use App\PersistCache;
|
use App\PersistCache;
|
||||||
use App\Service\BackupCodeManager;
|
use App\Service\BackupCodeInterface;
|
||||||
use Psr\Cache\InvalidArgumentException;
|
use Psr\Cache\InvalidArgumentException;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
@@ -15,8 +15,8 @@ use Symfony\Component\Console\Output\OutputInterface;
|
|||||||
* usage: php bin/console app:generate-backup-codes [count] */
|
* usage: php bin/console app:generate-backup-codes [count] */
|
||||||
final class GenerateBackupCodesCommand extends Command {
|
final class GenerateBackupCodesCommand extends Command {
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly BackupCodeManager $manager,
|
private readonly BackupCodeInterface $manager,
|
||||||
private readonly PersistCache $persistCache,
|
private readonly PersistCache $persistCache,
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Listener;
|
namespace App\Listener;
|
||||||
|
|
||||||
use App\Service\DomainManager;
|
use App\Service\DomainInterface;
|
||||||
use App\Trait\CookieNameTrait;
|
use App\Trait\CookieNameTrait;
|
||||||
use App\Trait\HasLoggerTrait;
|
use App\Trait\HasLoggerTrait;
|
||||||
use App\Trait\StringTrait;
|
use App\Trait\StringTrait;
|
||||||
@@ -20,7 +20,7 @@ final readonly class AcceptListener {
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private CacheItemPoolInterface $sessionCache,
|
private CacheItemPoolInterface $sessionCache,
|
||||||
private DomainManager $domainManager,
|
private DomainInterface $domainManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/** @throws InvalidArgumentException */
|
/** @throws InvalidArgumentException */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Listener;
|
namespace App\Listener;
|
||||||
|
|
||||||
use App\ConfigBag;
|
use App\ConfigBag;
|
||||||
use App\Service\DomainManager;
|
use App\Service\DomainInterface;
|
||||||
use App\Trait\CookieNameTrait;
|
use App\Trait\CookieNameTrait;
|
||||||
use App\Trait\HasLoggerTrait;
|
use App\Trait\HasLoggerTrait;
|
||||||
use App\Trait\MakeNonceTrait;
|
use App\Trait\MakeNonceTrait;
|
||||||
@@ -24,9 +24,9 @@ final readonly class InterceptListener {
|
|||||||
use MakeNonceTrait;
|
use MakeNonceTrait;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ConfigBag $config,
|
private ConfigBag $config,
|
||||||
private DomainManager $domainManager,
|
private DomainInterface $domainManager,
|
||||||
private Environment $twig,
|
private Environment $twig,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/** @throws InvalidArgumentException|RuntimeError|SyntaxError|LoaderError */
|
/** @throws InvalidArgumentException|RuntimeError|SyntaxError|LoaderError */
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ namespace App\Listener;
|
|||||||
|
|
||||||
use App\ConfigBag;
|
use App\ConfigBag;
|
||||||
use App\Data\Payload;
|
use App\Data\Payload;
|
||||||
use App\Service\DomainManager;
|
use App\Service\DomainInterface;
|
||||||
use App\Service\LoginManager;
|
use App\Service\LoginInterface;
|
||||||
use App\Trait\CookieNameTrait;
|
use App\Trait\CookieNameTrait;
|
||||||
use App\Trait\HasLoggerTrait;
|
use App\Trait\HasLoggerTrait;
|
||||||
use App\Trait\MakeNonceTrait;
|
use App\Trait\MakeNonceTrait;
|
||||||
@@ -34,8 +34,8 @@ final readonly class LoginListener {
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private Environment $twig,
|
private Environment $twig,
|
||||||
#[Target('login_limiter')] RateLimiterFactoryInterface $rateLimiter,
|
#[Target('login_limiter')] RateLimiterFactoryInterface $rateLimiter,
|
||||||
private DomainManager $domainManager,
|
private DomainInterface $domainManager,
|
||||||
private LoginManager $loginManager,
|
private LoginInterface $loginManager,
|
||||||
private ConfigBag $config,
|
private ConfigBag $config,
|
||||||
) {
|
) {
|
||||||
$this->rateLimiter = $rateLimiter;
|
$this->rateLimiter = $rateLimiter;
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Psr\Cache\InvalidArgumentException;
|
||||||
|
|
||||||
|
/** backup-codes are case‑insensitive alphanumeric strings
|
||||||
|
* they are single-use and marked as used after successful authentication */
|
||||||
|
interface BackupCodeInterface {
|
||||||
|
/** generate a set of backup-codes and return them
|
||||||
|
* @param int $count Number of codes to generate
|
||||||
|
* @return string[] Generated backup codes
|
||||||
|
* @throws InvalidArgumentException|Exception */
|
||||||
|
public function generate(int $count = 0): array;
|
||||||
|
|
||||||
|
/** @throws InvalidArgumentException */
|
||||||
|
public function expire(): void;
|
||||||
|
|
||||||
|
/** check if backup-code is valid and mark it as used
|
||||||
|
* @param string $code Code supplied by the client
|
||||||
|
* @return bool true if the code is valid and unused
|
||||||
|
* @throws InvalidArgumentException */
|
||||||
|
public function verifyAndConsume(string $code): bool;
|
||||||
|
}
|
||||||
@@ -13,9 +13,8 @@ use Psr\Cache\InvalidArgumentException;
|
|||||||
use App\Trait\GetTotpTrait;
|
use App\Trait\GetTotpTrait;
|
||||||
|
|
||||||
/** backup-codes are case‑insensitive alphanumeric strings
|
/** backup-codes are case‑insensitive alphanumeric strings
|
||||||
* they are single-use and marked as used after successful authentication
|
* they are single-use and marked as used after successful authentication */
|
||||||
*/
|
final readonly class BackupCodeManager implements BackupCodeInterface {
|
||||||
final readonly class BackupCodeManager {
|
|
||||||
use GetTotpTrait;
|
use GetTotpTrait;
|
||||||
use HasLoggerTrait;
|
use HasLoggerTrait;
|
||||||
use StringTrait;
|
use StringTrait;
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
interface DomainInterface {
|
||||||
|
/** IE: "auth.example.com" or null if not using a separate subdomain
|
||||||
|
* @return ?string Returns auth subdomain if configured, otherwise null */
|
||||||
|
public function getAuthSubdomain(): ?string;
|
||||||
|
|
||||||
|
/** check if given url is an acceptable url for redirection
|
||||||
|
* @param string $url Where we are thinking of sending the user
|
||||||
|
* @return bool Returns true if it is acceptable to send the user there */
|
||||||
|
public function validReturn(string $url): bool;
|
||||||
|
|
||||||
|
/** check if host-base matches auth-base
|
||||||
|
* @param string $host
|
||||||
|
* @return bool returns true if and only if host matches base domain of auth */
|
||||||
|
public function matchesAuth(string $host): bool;
|
||||||
|
|
||||||
|
/** IE: "example.com" if central auth is something like "auth.example.com"
|
||||||
|
* @return string|null returns base domain if we are doing central auth */
|
||||||
|
public function authBase(): ?string;
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace App\Service;
|
|||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
final readonly class DomainManager {
|
final readonly class DomainManager implements DomainInterface {
|
||||||
/* top-level-domains which are known to have multiple parts */
|
/* top-level-domains which are known to have multiple parts */
|
||||||
private const array TLD = [
|
private const array TLD = [
|
||||||
'ai' => ['com','net','off','org'],
|
'ai' => ['com','net','off','org'],
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Data\Payload;
|
||||||
|
use Psr\Cache\InvalidArgumentException;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
interface LoginInterface {
|
||||||
|
/** @throws InvalidArgumentException */
|
||||||
|
public function checkToken(Payload $payload, Request $request): ?Response;
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
use Symfony\Component\Uid\Ulid;
|
use Symfony\Component\Uid\Ulid;
|
||||||
|
|
||||||
final readonly class LoginManager {
|
final readonly class LoginManager implements LoginInterface {
|
||||||
use CookieNameTrait;
|
use CookieNameTrait;
|
||||||
use GetTotpTrait;
|
use GetTotpTrait;
|
||||||
use MakeNonceTrait;
|
use MakeNonceTrait;
|
||||||
@@ -29,8 +29,8 @@ final readonly class LoginManager {
|
|||||||
/** @throws InvalidArgumentException */
|
/** @throws InvalidArgumentException */
|
||||||
public function __construct(
|
public function __construct(
|
||||||
CacheItemPoolInterface $sessionCache,
|
CacheItemPoolInterface $sessionCache,
|
||||||
private BackupCodeManager $backupCodeManager,
|
private BackupCodeInterface $backupCodeManager,
|
||||||
private DomainManager $domainManager,
|
private DomainInterface $domainManager,
|
||||||
) {
|
) {
|
||||||
$this->sessionCache = new MonitorCacheKeys($sessionCache);
|
$this->sessionCache = new MonitorCacheKeys($sessionCache);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user