Skip to content

Commit

Permalink
Merge pull request #16344 from craftcms/feature/cms-1350-front-end-2fa
Browse files Browse the repository at this point in the history
Front-end 2FA
  • Loading branch information
brandonkelly authored Dec 22, 2024
2 parents 3cf48d4 + 2374fb7 commit ddd41a5
Show file tree
Hide file tree
Showing 49 changed files with 787 additions and 379 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
- “Template” field layout UI elements now show suggestions for the Template input.
- Improved the error output for nested elements when they can’t be resaved via `resave` commands.
- `resave` commands’ `--drafts`, `--provisional-drafts`, and `--revisions` options can now be set to `null`, causing elements to be resaved regardless of whether they’re drafts/provisional drafts/revisions.
- Added the `systemTemplateCss` config setting. ([#16344](https://github.com/craftcms/cms/pull/16344))
- The `loginPath`, `logoutPath`, `setPasswordPath`, and `verifyEmailPath` config settings are now respected in headless mode. ([#16344](https://github.com/craftcms/cms/pull/16344))

### Development
- Added support for fallback element partial templates, e.g. `_partials/entry.twig` as opposed to `_partials/entry/typeHandle.twig`. ([#16125](https://github.com/craftcms/cms/pull/16125))
Expand Down Expand Up @@ -108,6 +110,9 @@

### System
- Craft now keeps track of which site users registered from. When sending an email from the control panel, the current site is now set to the user’s affiliated site, if known. ([#16174](https://github.com/craftcms/cms/pull/16174))
- The system Login template is now rendered from `/login` (per the `loginPath` config setting) if a site template doesn’t exist in the same location. ([#16344](https://github.com/craftcms/cms/pull/16344))
- When a user with an active two-step verification method logs in from the front end, they’ll be redirected to `/login` (per the `loginPath` config setting) to complete the verification process. ([#16344](https://github.com/craftcms/cms/pull/16344))
- System templates (Login, Set Password, and error message screens) now have more generic styling when rendered on the front end, and can now have custom CSS styling via the `systemTemplateCss` config setting. ([#16344](https://github.com/craftcms/cms/pull/16344))
- Database rows with foreign keys referencing nonexistent rows are now deleted via garbage collection.
- Pages which contain image transform generation URLs now set no-cache headers. ([#16195](https://github.com/craftcms/cms/discussions/16195))
- Reduced the size of GraphQL introspection schemas. ([#16326](https://github.com/craftcms/cms/pull/16326))
Expand Down
19 changes: 9 additions & 10 deletions packages/craftcms-sass/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -312,20 +312,19 @@ $menuBorderRadius: $mediumBorderRadius;
}

@mixin pane {
background: $white;
box-shadow:
0 0 0 1px $grey200,
0 2px 12px color.adjust($grey200, $alpha: -0.5);
background: var(--pane-bg);
box-shadow: var(--pane-shadow);

&:focus {
box-shadow: var(--focus-ring);
}
}

@mixin modal {
border-radius: $largeBorderRadius;
background-color: $white;
box-shadow: 0 25px 100px color.adjust($grey900, $alpha: -0.5) !important;
border: var(--modal-border);
border-radius: var(--modal-border-radius);
background-color: var(--modal-bg);
box-shadow: var(--modal-shadow) !important;
}

@mixin light-on-dark-text() {
Expand Down Expand Up @@ -592,9 +591,9 @@ $menuBorderRadius: $mediumBorderRadius;
}

@mixin input-styles {
border-radius: $smallBorderRadius;
border: 1px solid color.adjust($inputColor, $alpha: -0.75);
background-color: hsl(212, 50%, 99%);
border-radius: var(--input-border-radius);
border: var(--input-border);
background: var(--input-bg);
background-clip: padding-box;
}

Expand Down
59 changes: 43 additions & 16 deletions src/config/GeneralConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -1690,8 +1690,6 @@ class GeneralConfig extends BaseConfig
*
* This can be set to `false` to disable front-end login.
*
* Note that this config setting is ignored when <config5:headlessMode> is enabled.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ::: code
Expand All @@ -1713,8 +1711,6 @@ class GeneralConfig extends BaseConfig
*
* This can be set to `false` to disable front-end logout.
*
* Note that this config setting is ignored when <config5:headlessMode> is enabled.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ::: code
Expand Down Expand Up @@ -2745,8 +2741,6 @@ class GeneralConfig extends BaseConfig
/**
* @var mixed The URI or URL that Craft should use for Set Password forms on the front end.
*
* This setting is ignored when <config5:headlessMode> is enabled, unless it’s set to an absolute URL.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ::: tip
Expand Down Expand Up @@ -2954,6 +2948,24 @@ class GeneralConfig extends BaseConfig
*/
public bool $storeUserIps = false;

/**
* @var string|null The URL to a CSS file that should be included when rendering system templates on the front end,
* such as the Login and Set Password templates.
*
* ::: code
* ```php Static Config
* ->systemTemplateCss('/css/cp-theme.css');
* ```
* ```shell Environment Override
* CRAFT_SYSTEM_TEMPLATE_CSS=/css/cp-theme.css
* ```
* :::
*
* @group System
* @since 5.6.0
*/
public ?string $systemTemplateCss = null;

/**
* @var string|null The handle of the filesystem that should be used for storing temporary asset uploads. A local temp folder will
* be used by default.
Expand Down Expand Up @@ -3293,8 +3305,6 @@ class GeneralConfig extends BaseConfig
/**
* @var mixed The URI or URL that Craft should use for email verification links on the front end.
*
* This setting is ignored when <config5:headlessMode> is enabled, unless it’s set to an absolute URL.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ::: code
Expand Down Expand Up @@ -5149,8 +5159,6 @@ public function localeAliases(array $value): self
*
* This can be set to `false` to disable front-end login.
*
* Note that this config setting is ignored when <config5:headlessMode> is enabled.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ```php
Expand All @@ -5174,8 +5182,6 @@ public function loginPath(mixed $value): self
*
* This can be set to `false` to disable front-end logout.
*
* Note that this config setting is ignored when <config5:headlessMode> is enabled.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ```php
Expand Down Expand Up @@ -6356,8 +6362,6 @@ public function sendPoweredByHeader(bool $value = true): self
/**
* The URI or URL that Craft should use for Set Password forms on the front end.
*
* This setting is ignored when <config5:headlessMode> is enabled, unless it’s set to an absolute URL.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ::: tip
Expand Down Expand Up @@ -6592,6 +6596,31 @@ public function storeUserIps(bool $value = true): self
return $this;
}

/**
* The URL to a CSS file that should be included when rendering system templates on the front end,
* such as the Login and Set Password templates.
*
* ::: code
* ```php Static Config
* ->systemTemplateCss('/css/cp-theme.css');
* ```
* ```shell Environment Override
* CRAFT_SYSTEM_TEMPLATE_CSS=/css/cp-theme.css
* ```
* :::
*
* @group System
* @param string|null $value
* @return self
* @see $systemTemplateCss
* @since 5.6.0
*/
public function systemTemplateCss(?string $value): self
{
$this->systemTemplateCss = $value;
return $this;
}

/**
* The handle of the filesystem that should be used for storing temporary asset uploads. A local temp folder will
* be used by default.
Expand Down Expand Up @@ -6975,8 +7004,6 @@ public function verificationCodeDuration(mixed $value): self
/**
* The URI or URL that Craft should use for email verification links on the front end.
*
* This setting is ignored when <config5:headlessMode> is enabled, unless it’s set to an absolute URL.
*
* See [[ConfigHelper::localizedValue()]] for a list of supported value types.
*
* ```php
Expand Down
43 changes: 20 additions & 23 deletions src/controllers/AuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use craft\helpers\Html;
use craft\i18n\Locale;
use craft\web\Controller;
use craft\web\View;
use yii\base\InvalidConfigException;
use yii\web\Response;

Expand All @@ -35,20 +36,6 @@ class AuthController extends Controller
'verify-totp' => self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE,
];

/**
* @inheritdoc
*/
public function beforeAction($action): bool
{
if (!parent::beforeAction($action)) {
return false;
}

$this->requireCpRequest();
;
return true;
}

/**
* Returns the HTML for an authentication method’s setup slideout.
*
Expand All @@ -64,14 +51,20 @@ public function actionMethodSetupHtml(): ?Response
$containerId = sprintf('auth-method-setup-%s', mt_rand());
$displayName = $method::displayName();
$view = Craft::$app->getView();

$html = Html::tag('h1', Craft::t('app', '{name} Setup', [
'name' => $displayName,
])) .
$view->namespaceInputs(
fn() => $method->getSetupHtml($containerId),
$containerId,
);
$templateMode = $view->getTemplateMode();
$view->setTemplateMode(View::TEMPLATE_MODE_CP);

try {
$html = Html::tag('h1', Craft::t('app', '{name} Setup', [
'name' => $displayName,
])) .
$view->namespaceInputs(
fn() => $method->getSetupHtml($containerId),
$containerId,
);
} finally {
$view->setTemplateMode($templateMode);
}

return $this->asJson([
'containerId' => $containerId,
Expand All @@ -93,7 +86,7 @@ public function actionMethodListingHtml(): ?Response
$this->requireAcceptsJson();

$view = Craft::$app->getView();
$html = $view->renderTemplate('users/_auth-methods.twig');
$html = $view->renderTemplate('users/_auth-methods.twig', templateMode: View::TEMPLATE_MODE_CP);

return $this->asJson([
'html' => $html,
Expand All @@ -111,6 +104,7 @@ public function actionMethodListingHtml(): ?Response
*/
public function actionRemoveMethod(): ?Response
{
$this->requireCpRequest();
$this->requirePostRequest();
$this->requireElevatedSession();

Expand Down Expand Up @@ -176,6 +170,7 @@ public function actionVerifyRecoveryCode(): Response
*/
public function actionPasskeyCreationOptions(): Response
{
$this->requireCpRequest();
$this->requireAcceptsJson();
$this->requirePostRequest();
$this->requireElevatedSession();
Expand Down Expand Up @@ -211,6 +206,7 @@ public function actionPasskeyRequestOptions(): Response
*/
public function actionVerifyPasskeyCreation(): Response
{
$this->requireCpRequest();
$this->requireAcceptsJson();
$this->requirePostRequest();
$this->requireElevatedSession();
Expand All @@ -236,6 +232,7 @@ public function actionVerifyPasskeyCreation(): Response
*/
public function actionDeletePasskey(): Response
{
$this->requireCpRequest();
$this->requireAcceptsJson();
$this->requirePostRequest();

Expand Down
Loading

0 comments on commit ddd41a5

Please sign in to comment.