+
{_heading_crawler}
{control crawlerForm}
+
+
+
+
{_heading_azure_auth}
+
+
+ {control azureAuthForm}
+
diff --git a/src/Web/FrontModule/Presenter/OAuthPresenter.php b/src/Web/FrontModule/Presenter/OAuthPresenter.php
new file mode 100644
index 00000000..920b4cf0
--- /dev/null
+++ b/src/Web/FrontModule/Presenter/OAuthPresenter.php
@@ -0,0 +1,42 @@
+logger->error($error->getMessage(), [
+ 'exception' => $error,
+ ]);
+
+ $this->subscribeFlashMessage(FlashMessage::error('authentication_failure.' . $flowName));
+ $this->redirect(':Front:SignIn:');
+ }
+
+ protected function onAuthenticationFailed(string $flowName, OAuthExceptionInterface $error): never
+ {
+ $this->subscribeFlashMessage(FlashMessage::error('authentication_failure.' . $flowName));
+ $this->redirect(':Front:SignIn:');
+ }
+
+ protected function onUserAuthenticated(string $flowName): never
+ {
+ $this->redirect(':Admin:Dashboard:');
+ }
+}
diff --git a/src/Web/FrontModule/Presenter/SignInPresenter.php b/src/Web/FrontModule/Presenter/SignInPresenter.php
index a5005c73..267dadc9 100644
--- a/src/Web/FrontModule/Presenter/SignInPresenter.php
+++ b/src/Web/FrontModule/Presenter/SignInPresenter.php
@@ -9,6 +9,8 @@
use App\Web\FrontModule\Control\SignIn\SignInControl;
use App\Web\FrontModule\Control\SignIn\SignInControlFactoryInterface;
use SixtyEightPublishers\FlashMessageBundle\Domain\FlashMessage;
+use SixtyEightPublishers\OAuth\OAuthFlowInterface;
+use SixtyEightPublishers\OAuth\OAuthFlowProviderInterface;
final class SignInPresenter extends FrontPresenter
{
@@ -17,10 +19,28 @@ final class SignInPresenter extends FrontPresenter
public function __construct(
private readonly SignInControlFactoryInterface $signInControlFactory,
+ private readonly OAuthFlowProviderInterface $oauthFlowProvider,
) {
parent::__construct();
}
+ protected function beforeRender(): void
+ {
+ parent::beforeRender();
+
+ $template = $this->getTemplate();
+ assert($template instanceof SignInTemplate);
+
+ $template->backLink = !empty($this->backLink) ? $this->backLink : null;
+ $template->enabledOauthTypes = array_map(
+ static fn (OAuthFlowInterface $flow): string => $flow->getName(),
+ array_filter(
+ $this->oauthFlowProvider->all(),
+ static fn (OauthFlowInterface $flow): bool => $flow->isEnabled(),
+ ),
+ );
+ }
+
protected function createComponentSignIn(): SignInControl
{
$control = $this->signInControlFactory->create();
diff --git a/src/Web/FrontModule/Presenter/SignInTemplate.php b/src/Web/FrontModule/Presenter/SignInTemplate.php
index 6e5f3342..cf606df3 100644
--- a/src/Web/FrontModule/Presenter/SignInTemplate.php
+++ b/src/Web/FrontModule/Presenter/SignInTemplate.php
@@ -8,4 +8,8 @@
final class SignInTemplate extends DefaultPresenterTemplate
{
+ public ?string $backLink = null;
+
+ /** @var array
*/
+ public array $enabledOauthTypes;
}
diff --git a/src/Web/FrontModule/Presenter/templates/SignIn.default.latte b/src/Web/FrontModule/Presenter/templates/SignIn.default.latte
index c7e3bdbb..2964a072 100644
--- a/src/Web/FrontModule/Presenter/templates/SignIn.default.latte
+++ b/src/Web/FrontModule/Presenter/templates/SignIn.default.latte
@@ -1,9 +1,48 @@
+{templateType App\Web\FrontModule\Presenter\SignInTemplate}
+
{block #content}
+ {control signIn}
+
+
-{control signIn}
+
+{/block}
-
+{define login-icon-azure}
+
+{/define}
diff --git a/src/Web/Router/RouterFactory.php b/src/Web/Router/RouterFactory.php
index 0a168ad2..8d20e930 100644
--- a/src/Web/Router/RouterFactory.php
+++ b/src/Web/Router/RouterFactory.php
@@ -44,6 +44,11 @@ public function create(): RouteList
'locale' => $this->profiles->default()->locale(),
]);
+ $router->addRoute('oauth//', [
+ 'module' => 'Front',
+ 'presenter' => 'OAuth',
+ ]);
+
$router->addRoute('project//[/][/]', [
'module' => 'Admin:Project',
'action' => 'default',
diff --git a/src/Web/Ui/templates/forms/imports.latte b/src/Web/Ui/templates/forms/imports.latte
index 09f8622e..5988103a 100644
--- a/src/Web/Ui/templates/forms/imports.latte
+++ b/src/Web/Ui/templates/forms/imports.latte
@@ -117,10 +117,35 @@
{/define}
{define #input-type-text}
-
+ {if null === $control->getOption('clipboard')}
+
+ {else}
+ {var $clipboardAction = $control->isDisabled() ? 'copy' : $control->getOption('clipboard')}
+
+
+
+
+
+
+
+ {/if}
{/define}
{define #input-type-color-picker}
diff --git a/translations/App_Web_AdminModule_ApplicationModule_Control_AzureAuthSettingsForm_AzureAuthSettingsFormControl.cs.neon b/translations/App_Web_AdminModule_ApplicationModule_Control_AzureAuthSettingsForm_AzureAuthSettingsFormControl.cs.neon
new file mode 100644
index 00000000..5bbc4195
--- /dev/null
+++ b/translations/App_Web_AdminModule_ApplicationModule_Control_AzureAuthSettingsForm_AzureAuthSettingsFormControl.cs.neon
@@ -0,0 +1,17 @@
+enabled:
+ field: Zapnuto
+
+client_id:
+ field: 'ID aplikace (klienta)'
+ required: Vyplňte prosím ID aplikace.
+
+client_secret:
+ field: Tajný kód klienta
+ required: Vyplňte prosím tajný kód klienta.
+
+callback_uri:
+ field: Callback URI
+ description: 'V nastavení aplikace na webu Azure nastavte jako "Identifikátor URI pro přesměrování".'
+
+save:
+ field: Uložit
diff --git a/translations/App_Web_AdminModule_ApplicationModule_Control_AzureAuthSettingsForm_AzureAuthSettingsFormControl.en.neon b/translations/App_Web_AdminModule_ApplicationModule_Control_AzureAuthSettingsForm_AzureAuthSettingsFormControl.en.neon
new file mode 100644
index 00000000..1f54b838
--- /dev/null
+++ b/translations/App_Web_AdminModule_ApplicationModule_Control_AzureAuthSettingsForm_AzureAuthSettingsFormControl.en.neon
@@ -0,0 +1,17 @@
+enabled:
+ field: Enabled
+
+client_id:
+ field: 'Application ID (client)'
+ required: Please enter a application ID.
+
+client_secret:
+ field: Client secret code
+ required: Please enter a client secret code.
+
+callback_uri:
+ field: Callback URI
+ description: 'In the application settings on the Azure site, set as the "Redirect URI".'
+
+save:
+ field: Save
diff --git a/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.cs.neon b/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.cs.neon
index 00a79bbf..823e67e0 100644
--- a/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.cs.neon
+++ b/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.cs.neon
@@ -3,6 +3,7 @@ heading_localization: Lokalizace
heading_environments: Prostředí
heading_api_cache: Výkon
heading_crawler: Crawler
+heading_azure_auth: Autentizace pomocí Azure AD
message:
localization_settings_updated: Nastavení lokalizace bylo uloženo.
@@ -13,3 +14,5 @@ message:
crawler_settings_update_failed: Při ukládaní nastavení došlo k chybě.
environments_updated: Nastavení prostředí bylo uloženo.
environments_update_failed: Při ukládaní nastavení došlo k chybě.
+ azure_auth_updated: Nastavení Azure AD bylo uloženo.
+ azure_auth_update_failed: Při ukládaní nastavení došlo k chybě.
diff --git a/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.en.neon b/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.en.neon
index fb47cd3c..0f3942df 100644
--- a/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.en.neon
+++ b/translations/App_Web_AdminModule_ApplicationModule_Presenter_SettingsPresenter.en.neon
@@ -3,6 +3,7 @@ heading_localization: Localization
heading_environments: Environments
heading_api_cache: Performance
heading_crawler: Crawler
+heading_azure_auth: Authentication with Azure AD
message:
localization_settings_updated: The localization settings have been saved.
diff --git a/translations/App_Web_FrontModule_Presenter_OAuthPresenter.cs.neon b/translations/App_Web_FrontModule_Presenter_OAuthPresenter.cs.neon
new file mode 100644
index 00000000..5a0e921d
--- /dev/null
+++ b/translations/App_Web_FrontModule_Presenter_OAuthPresenter.cs.neon
@@ -0,0 +1,3 @@
+message:
+ authentication_failure:
+ azure: Přihlášení skrze Azure AD se nezdařilo.
diff --git a/translations/App_Web_FrontModule_Presenter_OAuthPresenter.en.neon b/translations/App_Web_FrontModule_Presenter_OAuthPresenter.en.neon
new file mode 100644
index 00000000..f17339ba
--- /dev/null
+++ b/translations/App_Web_FrontModule_Presenter_OAuthPresenter.en.neon
@@ -0,0 +1,3 @@
+message:
+ authentication_failure:
+ azure: Login via Azure AD failed.
diff --git a/translations/App_Web_FrontModule_Presenter_SignInPresenter.cs.neon b/translations/App_Web_FrontModule_Presenter_SignInPresenter.cs.neon
index cdd2c7dd..21952d89 100644
--- a/translations/App_Web_FrontModule_Presenter_SignInPresenter.cs.neon
+++ b/translations/App_Web_FrontModule_Presenter_SignInPresenter.cs.neon
@@ -1,5 +1,8 @@
page_title: Přihlášení
forgot_your_password: Zapomenuté heslo?
+login_with:
+ azure: Přihlásit se přes Azure
+
message:
user_authentication_failed: Nesprávné přihlašovací údaje.
diff --git a/translations/App_Web_FrontModule_Presenter_SignInPresenter.en.neon b/translations/App_Web_FrontModule_Presenter_SignInPresenter.en.neon
index 50206272..ba895973 100644
--- a/translations/App_Web_FrontModule_Presenter_SignInPresenter.en.neon
+++ b/translations/App_Web_FrontModule_Presenter_SignInPresenter.en.neon
@@ -1,5 +1,8 @@
page_title: Sign in
forgot_your_password: Forgot Password?
+login_with:
+ azure: Sign in with Azure
+
message:
user_authentication_failed: Incorrect credentials.
diff --git a/translations/layout.cs.neon b/translations/layout.cs.neon
index 47125acf..9351028d 100644
--- a/translations/layout.cs.neon
+++ b/translations/layout.cs.neon
@@ -51,5 +51,9 @@ alert:
text: Výchozí jazyk pro tento projekt není nastaven.
link_text: Nastavte jej prosím v editaci projektu.
+clipboard:
+ success_copy: Zkopírováno
+ error_copy: Kopírování se nezdařilo
+
message:
locale_change_failed: Jazyk se nepovedlo změnit.
diff --git a/translations/layout.en.neon b/translations/layout.en.neon
index 6f193e4f..efd70611 100644
--- a/translations/layout.en.neon
+++ b/translations/layout.en.neon
@@ -51,5 +51,9 @@ alert:
text: The default locale for this project is not set.
link_text: Please set it in the app settings.
+clipboard:
+ success_copy: Copied
+ error_copy: Copying failed
+
message:
locale_change_failed: The language could not be changed.
diff --git a/yarn.lock b/yarn.lock
index 88e74c06..dfaebb4f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2117,6 +2117,15 @@ cli-boxes@^2.2.1:
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
+clipboard@^2.0.11:
+ version "2.0.11"
+ resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5"
+ integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
+ dependencies:
+ good-listener "^1.2.2"
+ select "^1.1.2"
+ tiny-emitter "^2.0.0"
+
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@@ -2614,6 +2623,11 @@ del@^4.1.1:
pify "^4.0.1"
rimraf "^2.6.3"
+delegate@^3.1.2:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
+ integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
+
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@@ -3339,6 +3353,13 @@ globby@^6.1.0:
pify "^2.0.0"
pinkie-promise "^2.0.0"
+good-listener@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
+ integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==
+ dependencies:
+ delegate "^3.1.2"
+
got@^11.8.5, got@^9.6.0:
version "11.8.5"
resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046"
@@ -5370,6 +5391,11 @@ select-hose@^2.0.0:
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
+select@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
+ integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
+
selfsigned@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56"
@@ -5804,6 +5830,11 @@ thunky@^1.0.2:
resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
+tiny-emitter@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
+ integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
+
tippy.js@^6.3.7:
version "6.3.7"
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"