mirror of
https://github.com/fleetbase/fleetbase.git
synced 2026-01-08 07:16:49 +00:00
Fixed 2FA Config component
This commit is contained in:
1
console/app/components/configure/2fa.hbs
Normal file
1
console/app/components/configure/2fa.hbs
Normal file
@@ -0,0 +1 @@
|
||||
{{yield}}
|
||||
3
console/app/components/configure/2fa.js
Normal file
3
console/app/components/configure/2fa.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import Component from '@glimmer/component';
|
||||
|
||||
export default class Configure2faComponent extends Component {}
|
||||
@@ -1,21 +1,21 @@
|
||||
<div class="flex items-center space-x-4">
|
||||
<label class="text-lg font-medium">Enable Two-Factor Authentication</label>
|
||||
<Toggle @isToggled={{this.is2FAEnabled}} @onToggle={{this.toggle2FA}} />
|
||||
<Toggle @isToggled={{this.isTwoFaEnabled}} @onToggle={{this.onTwoFaToggled}} />
|
||||
</div>
|
||||
|
||||
{{#if this.is2FAEnabled}}
|
||||
{{#if this.isTwoFaEnabled}}
|
||||
<div class="mt-6">
|
||||
<label class="text-lg font-medium">Choose an authentication method</label>
|
||||
<p class="text-sm text-gray-600 mt-1">In addition to your username and password, you'll have to enter a code (delivered via app or SMS) to sign in to your account</p>
|
||||
{{#each this.TwoFaMethods as |method|}}
|
||||
<div class="border p-4 mt-2 transition duration-300 {{if (eq this.selected2FAMethod method) 'border-blue-500' 'border-gray-200'}}">
|
||||
<input type="radio" name="2fa-method" id="{{method.name}}" checked={{eq this.selected2FAMethod method}} {{on "change" (fn this.select2FAMethod method)}} />
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mt-1">In addition to your username and password, you'll have to enter a code (delivered via app or SMS) to sign in to your account</p>
|
||||
{{#each @twoFaMethods as |method|}}
|
||||
<div class="border rounded-lg px-4 py-3 mt-2 transition duration-300 {{if (eq this.selectedTwoFaMethod method.key) 'border-blue-500' 'border-gray-200 dark:border-gray-700'}}">
|
||||
<input type="radio" name="2fa-method" id="{{method.name}}" checked={{eq this.selectedTwoFaMethod method.key}} {{on "change" (fn this.onTwoFaSelected method.key)}} />
|
||||
<label for="{{method.name}}">
|
||||
{{method.name}}
|
||||
{{#if method.recommended}}
|
||||
<span class="bg-blue-500 text-white px-2 py-1 ml-2 text-xs font-semibold">Recommended</span>
|
||||
<span class="bg-blue-500 rounded-xl text-white px-2 py-1 ml-2 text-xs font-semibold">Recommended</span>
|
||||
{{/if}}
|
||||
<p class="text-sm text-gray-600 mt-1">{{method.description}}</p>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mt-1">{{method.description}}</p>
|
||||
</label>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
@@ -1,44 +1,116 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
import { isArray } from '@ember/array';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
/**
|
||||
* Default Two-Factor Authentication method when not explicitly selected.
|
||||
*
|
||||
* @property {string} DEFAULT_2FA_METHOD
|
||||
* @private
|
||||
*/
|
||||
const DEFAULT_2FA_METHOD = 'authenticator_app';
|
||||
|
||||
/**
|
||||
* Glimmer component for managing Two-Factor Authentication settings.
|
||||
*
|
||||
* @class TwoFaSettingsComponent
|
||||
* @extends Component
|
||||
*/
|
||||
export default class TwoFaSettingsComponent extends Component {
|
||||
/**
|
||||
* The fetch service for making HTTP requests.
|
||||
*
|
||||
* @property {Service} fetch
|
||||
* @public
|
||||
*/
|
||||
@service fetch;
|
||||
|
||||
/**
|
||||
* The notifications service for displaying user notifications.
|
||||
*
|
||||
* @property {Service} notifications
|
||||
* @public
|
||||
*/
|
||||
@service notifications;
|
||||
|
||||
@tracked selected2FAMethod;
|
||||
@tracked is2FAEnabled;
|
||||
@tracked twoFaSettings;
|
||||
@tracked isLoading;
|
||||
/**
|
||||
* The currently selected Two-Factor Authentication method.
|
||||
*
|
||||
* @property {string} selectedTwoFaMethod
|
||||
* @public
|
||||
*/
|
||||
@tracked selectedTwoFaMethod;
|
||||
|
||||
TwoFaMethods = [
|
||||
{ name: 'Authenticator App', description: 'Get codes from an app like Authy, 1Password, Microsoft Authenticator, or Google Authenticator', recommended: true },
|
||||
{ name: 'SMS', description: 'Receive a unique code via SMS' },
|
||||
{ name: 'Email', description: 'Receive a unique code via Email' },
|
||||
];
|
||||
/**
|
||||
* Indicates whether Two-Factor Authentication is currently enabled.
|
||||
*
|
||||
* @property {boolean} isTwoFaEnabled
|
||||
* @public
|
||||
*/
|
||||
@tracked isTwoFaEnabled;
|
||||
|
||||
constructor() {
|
||||
/**
|
||||
* Class constructor to initialize the component.
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} owner - The owner of the component.
|
||||
* @param {Object} options - Options passed during component instantiation.
|
||||
* @param {Object} options.twoFaSettings - The current Two-Factor Authentication settings.
|
||||
* @param {Array} options.twoFaMethods - Available Two-Factor Authentication methods.
|
||||
*/
|
||||
constructor(owner, { twoFaSettings, twoFaMethods }) {
|
||||
super(...arguments);
|
||||
if (this.is2FAEnabled) {
|
||||
this.selected2FAMethod = this.TwoFaMethods.find((method) => method.recommended);
|
||||
}
|
||||
|
||||
const userSelectedMethod = isArray(twoFaMethods) ? twoFaMethods.find(({ key }) => key === twoFaSettings.method) : null;
|
||||
|
||||
this.isTwoFaEnabled = twoFaSettings.enabled === true;
|
||||
this.selectedTwoFaMethod = userSelectedMethod ? userSelectedMethod.key : DEFAULT_2FA_METHOD;
|
||||
}
|
||||
|
||||
@action async toggle2FA() {
|
||||
this.is2FAEnabled = !this.is2FAEnabled;
|
||||
/**
|
||||
* Action handler for toggling Two-Factor Authentication.
|
||||
*
|
||||
* @method onTwoFaToggled
|
||||
* @param {boolean} isTwoFaEnabled - Indicates whether Two-Factor Authentication is enabled.
|
||||
* @return {void}
|
||||
* @public
|
||||
*/
|
||||
@action onTwoFaToggled(isTwoFaEnabled) {
|
||||
this.isTwoFaEnabled = isTwoFaEnabled;
|
||||
|
||||
if (!this.is2FAEnabled) {
|
||||
this.selected2FAMethod = null;
|
||||
if (isTwoFaEnabled) {
|
||||
const recommendedMethod = isArray(this.args.twoFaMethods) ? this.args.twoFaMethods.find((method) => method.recommended) : null;
|
||||
if (recommendedMethod) {
|
||||
this.selectedTwoFaMethod = recommendedMethod.key;
|
||||
}
|
||||
} else {
|
||||
this.selected2FAMethod = this.TwoFaMethods.find((method) => method.recommended);
|
||||
this.selectedTwoFaMethod = null;
|
||||
}
|
||||
|
||||
console.log('selected2FAMethod:', this.selected2FAMethod);
|
||||
if (typeof this.args.onTwoFaToggled === 'function') {
|
||||
this.args.onTwoFaToggled(...arguments);
|
||||
}
|
||||
|
||||
if (typeof this.args.onTwoFaMethodSelected === 'function') {
|
||||
this.args.onTwoFaMethodSelected(this.selectedTwoFaMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@action select2FAMethod(method) {
|
||||
this.selected2FAMethod = method;
|
||||
console.log('selected2FAMethod:', this.selected2FAMethod);
|
||||
/**
|
||||
* Action handler for selecting a Two-Factor Authentication method.
|
||||
*
|
||||
* @method onTwoFaSelected
|
||||
* @param {string} method - The selected Two-Factor Authentication method.
|
||||
* @return {void}
|
||||
* @public
|
||||
*/
|
||||
@action onTwoFaSelected(method) {
|
||||
this.selectedTwoFaMethod = method;
|
||||
|
||||
if (typeof this.args.onTwoFaMethodSelected === 'function') {
|
||||
this.args.onTwoFaMethodSelected(...arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export default class AuthLoginController extends Controller {
|
||||
* @var {Controller}
|
||||
*/
|
||||
@controller('auth.forgot-password') forgotPasswordController;
|
||||
|
||||
|
||||
/**
|
||||
* Inject the `notifications` service
|
||||
*
|
||||
@@ -89,45 +89,50 @@ export default class AuthLoginController extends Controller {
|
||||
*/
|
||||
@tracked failedAttempts = 0;
|
||||
|
||||
@action async login(event) {
|
||||
// firefox patch
|
||||
event.preventDefault();
|
||||
// get user credentials
|
||||
const { identity, password, rememberMe } = this;
|
||||
// start loader
|
||||
this.set('isLoading', true);
|
||||
// set where to redirect on login
|
||||
this.setRedirect();
|
||||
try {
|
||||
await this.session.authenticate('authenticator:fleetbase', { identity, password }, rememberMe);
|
||||
} catch (error) {
|
||||
this.failedAttempts++;
|
||||
return this.failure(error);
|
||||
}
|
||||
if (this.session.isAuthenticated) {
|
||||
this.success();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the user
|
||||
*
|
||||
* @void
|
||||
*/
|
||||
@action async login(event) {
|
||||
// firefox patch
|
||||
event.preventDefault();
|
||||
|
||||
// get user credentials
|
||||
const { email, password, rememberMe } = this;
|
||||
|
||||
// start loader
|
||||
this.set('isLoading', true);
|
||||
|
||||
// set where to redirect on login
|
||||
this.setRedirect();
|
||||
|
||||
try {
|
||||
await this.session.authenticate('authenticator:fleetbase', { email, password }, rememberMe);
|
||||
|
||||
const isTwoFactorEnabled = this.session.user ? this.session.user.isTwoFactorEnabled : false;
|
||||
|
||||
if (isTwoFactorEnabled) {
|
||||
// Redirect to the 2FA page if 2FA is enabled
|
||||
this.transitionToRoute('auth.two-fa');
|
||||
} else {
|
||||
// Continue with the default behavior (e.g., redirect to another route)
|
||||
this.success();
|
||||
}
|
||||
} catch (error) {
|
||||
this.failedAttempts++;
|
||||
return this.failure(error);
|
||||
}
|
||||
|
||||
if (this.session.isAuthenticated) {
|
||||
this.success();
|
||||
}
|
||||
}
|
||||
// @action async login(event) {
|
||||
// // firefox patch
|
||||
// event.preventDefault();
|
||||
// // get user credentials
|
||||
// const { email, password, rememberMe } = this;
|
||||
// // start loader
|
||||
// this.set('isLoading', true);
|
||||
// // set where to redirect on login
|
||||
// this.setRedirect();
|
||||
// try {
|
||||
// await this.session.authenticate('authenticator:fleetbase', { email, password }, rememberMe);
|
||||
// } catch (error) {
|
||||
// this.failedAttempts++;
|
||||
// return this.failure(error);
|
||||
// }
|
||||
// if (this.session.isAuthenticated) {
|
||||
// this.success();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Transition user to onboarding screen
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
export default class AuthTwoFaController extends Controller {
|
||||
@action verifyCode() {
|
||||
// console.log('Verification code submitted!');
|
||||
}
|
||||
|
||||
export default class AuthTwoFaController extends Controller {}
|
||||
@action resendCode() {
|
||||
// console.log('Resending verification code...');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@ import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
/**
|
||||
* Controller responsible for handling Two-Factor Authentication settings in the admin console.
|
||||
*
|
||||
* @class ConsoleAdminTwoFaSettingsController
|
||||
* @extends Controller
|
||||
*/
|
||||
export default class ConsoleAdminTwoFaSettingsController extends Controller {
|
||||
/**
|
||||
* Inject the notifications service.
|
||||
@@ -18,9 +24,30 @@ export default class ConsoleAdminTwoFaSettingsController extends Controller {
|
||||
*/
|
||||
@service fetch;
|
||||
|
||||
@tracked selected2FAMethod = null;
|
||||
/**
|
||||
* Tracked property for the Two-Factor Authentication enabled state.
|
||||
*
|
||||
* @memberof ConsoleAdminTwoFaSettingsController
|
||||
* @type {Boolean}
|
||||
*/
|
||||
@tracked twoFaMethod = 'authenticator_app';
|
||||
|
||||
@tracked is2FAEnabled = true;
|
||||
/**
|
||||
* Array of available Two-Factor Authentication methods.
|
||||
*
|
||||
* @memberof ConsoleAdminTwoFaSettingsController
|
||||
* @type {Array}
|
||||
*/
|
||||
@tracked methods = [
|
||||
{
|
||||
key: 'authenticator_app',
|
||||
name: 'Authenticator App',
|
||||
description: 'Get codes from an app like Authy, 1Password, Microsoft Authenticator, or Google Authenticator',
|
||||
recommended: true,
|
||||
},
|
||||
{ key: 'sms', name: 'SMS', description: 'Receive a unique code via SMS' },
|
||||
{ key: 'email', name: 'Email', description: 'Receive a unique code via Email' },
|
||||
];
|
||||
|
||||
/**
|
||||
* The 2FA settings value JSON.
|
||||
@@ -29,8 +56,8 @@ export default class ConsoleAdminTwoFaSettingsController extends Controller {
|
||||
* @var {Object}
|
||||
*/
|
||||
@tracked twoFaSettings = {
|
||||
Selected: this.selected2FAMethod,
|
||||
Enabled: this.is2FAEnabled,
|
||||
enabled: false,
|
||||
method: 'authenticator_app',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -41,9 +68,54 @@ export default class ConsoleAdminTwoFaSettingsController extends Controller {
|
||||
*/
|
||||
@tracked isLoading = false;
|
||||
|
||||
/**
|
||||
* Constructor method for the controller.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.twoFaSettings;
|
||||
this.loadSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action method triggered when Two-Factor Authentication is toggled.
|
||||
*
|
||||
* @action
|
||||
* @param {Boolean} isEnabled - The new state of Two-Factor Authentication.
|
||||
*/
|
||||
@action onTwoFaToggled(isEnabled) {
|
||||
this.isTwoFaEnabled = isEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action method triggered when a Two-Factor Authentication method is selected.
|
||||
*
|
||||
* @action
|
||||
* @param {String} method - The selected Two-Factor Authentication method.
|
||||
*/
|
||||
@action onTwoFaMethodSelected(method) {
|
||||
this.twoFaMethod = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action method to load Two-Factor Authentication settings from the server.
|
||||
*
|
||||
* @action
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@action loadSettings() {
|
||||
return this.fetch
|
||||
.get('two-fa/settings')
|
||||
.then((twoFaSettings) => {
|
||||
this.twoFaSettings = twoFaSettings;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.notifications.serverError(error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,16 +127,17 @@ export default class ConsoleAdminTwoFaSettingsController extends Controller {
|
||||
* @memberof ConsoleAdminTwoFaSettingsController
|
||||
*/
|
||||
@action saveSettings() {
|
||||
const { twoFaSettings } = this;
|
||||
|
||||
console.log('settings', twoFaSettings);
|
||||
const twoFaSettings = {
|
||||
enabled: this.isTwoFaEnabled,
|
||||
method: this.twoFaMethod,
|
||||
};
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
return this.fetch
|
||||
.post('two-fa-settings/save-settings', { twoFaSettings })
|
||||
.post('two-fa/settings', { twoFaSettings })
|
||||
.then(() => {
|
||||
this.notifications.success('2FA settings successfully saved.');
|
||||
this.notifications.success('2FA Settings saved successfully.');
|
||||
})
|
||||
.catch((error) => {
|
||||
this.notifications.serverError(error);
|
||||
|
||||
@@ -11,7 +11,6 @@ Router.map(function () {
|
||||
this.route('login', { path: '/' });
|
||||
this.route('forgot-password');
|
||||
this.route('reset-password');
|
||||
this.route('two-fa');
|
||||
});
|
||||
this.route('onboard', function () {
|
||||
this.route('verify-email');
|
||||
@@ -53,16 +52,16 @@ Router.map(function () {
|
||||
path: 'developers'
|
||||
});
|
||||
|
||||
this.mount('@fleetbase/fleetops-engine', {
|
||||
as: 'fleet-ops',
|
||||
path: 'fleet-ops'
|
||||
});
|
||||
|
||||
this.mount('@fleetbase/iam-engine', {
|
||||
as: 'iam',
|
||||
path: 'iam'
|
||||
});
|
||||
|
||||
this.mount('@fleetbase/fleetops-engine', {
|
||||
as: 'fleet-ops',
|
||||
path: 'fleet-ops'
|
||||
});
|
||||
|
||||
this.mount('@fleetbase/storefront-engine', {
|
||||
as: 'storefront',
|
||||
path: 'storefront'
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class AuthTwoFaRoute extends Route {}
|
||||
export default class AuthTwoFaRoute extends Route {
|
||||
@service fetch;
|
||||
|
||||
queryParams = {
|
||||
token: {
|
||||
refreshModel: false
|
||||
}
|
||||
}
|
||||
|
||||
beforeModel(transition) {
|
||||
// validate 2fa session with server
|
||||
const { token } = transition.params;
|
||||
|
||||
return this.fetch.post('two-fa/validate-session', { token }).catch((error) => {
|
||||
this.notifications.serverError(error);
|
||||
return this.redirect('auth.login');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
<FaIcon @icon="exclamation-triangle" @size="lg" class="text-yellow-900 mr-4" />
|
||||
</div>
|
||||
<p class="flex-1 text-sm text-yellow-900 dark:yellow-red-900">
|
||||
<strong>Forgot your password?</strong><br> Click the button below to reset your password.
|
||||
<strong>Forgot your password?</strong><br />
|
||||
Click the button below to reset your password.
|
||||
</p>
|
||||
</div>
|
||||
<Button @text="Ok, help me reset!" @type="warning" @onClick={{this.forgotPassword}} />
|
||||
@@ -24,11 +25,44 @@
|
||||
<form class="mt-8" {{on "submit" this.login}}>
|
||||
<input type="hidden" name="remember" value="true" />
|
||||
<div class="rounded-md shadow-sm">
|
||||
{{!-- <div>
|
||||
<Input
|
||||
@value={{this.email}}
|
||||
aria-label="Email address"
|
||||
name="email"
|
||||
@type="email"
|
||||
autocomplete="username"
|
||||
required
|
||||
class="relative block w-full px-3 py-2 text-gray-900 placeholder-gray-500 border border-gray-300 rounded-none appearance-none rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5 dark:text-white dark:bg-gray-700 dark:border-gray-900"
|
||||
placeholder="Email address"
|
||||
disabled={{this.isLoading}}
|
||||
/>
|
||||
</div> --}}
|
||||
<div>
|
||||
<Input @value={{this.email}} aria-label="Email address" name="email" @type="email" autocomplete="username" required class="relative block w-full px-3 py-2 text-gray-900 placeholder-gray-500 border border-gray-300 rounded-none appearance-none rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5 dark:text-white dark:bg-gray-700 dark:border-gray-900" placeholder="Email address" disabled={{this.isLoading}} />
|
||||
<Input
|
||||
@value={{this.identity}}
|
||||
aria-label="Email or Phone Number"
|
||||
name="email"
|
||||
@type="email"
|
||||
autocomplete="username"
|
||||
required
|
||||
class="relative block w-full px-3 py-2 text-gray-900 placeholder-gray-500 border border-gray-300 rounded-none appearance-none rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5 dark:text-white dark:bg-gray-700 dark:border-gray-900"
|
||||
placeholder="Email or Phone Number"
|
||||
disabled={{this.isLoading}}
|
||||
/>
|
||||
</div>
|
||||
<div class="-mt-px">
|
||||
<Input @value={{this.password}} aria-label="Password" name="password" @type="password" autocomplete="current-password" required class="relative block w-full px-3 py-2 text-gray-900 placeholder-gray-500 border border-gray-300 rounded-none appearance-none rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5 dark:text-white dark:bg-gray-700 dark:border-gray-900" placeholder="Password" disabled={{this.isLoading}} />
|
||||
<Input
|
||||
@value={{this.password}}
|
||||
aria-label="Password"
|
||||
name="password"
|
||||
@type="password"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
class="relative block w-full px-3 py-2 text-gray-900 placeholder-gray-500 border border-gray-300 rounded-none appearance-none rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5 dark:text-white dark:bg-gray-700 dark:border-gray-900"
|
||||
placeholder="Password"
|
||||
disabled={{this.isLoading}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +75,12 @@
|
||||
</div>
|
||||
|
||||
<div class="text-sm leading-5">
|
||||
<a href="javascript:;" {{on "click" this.forgotPassword}} disabled={{this.isLoading}} class="font-medium transition duration-150 ease-in-out text-sky-600 hover:text-sky-500 focus:outline-none focus:underline">
|
||||
<a
|
||||
href="javascript:;"
|
||||
{{on "click" this.forgotPassword}}
|
||||
disabled={{this.isLoading}}
|
||||
class="font-medium transition duration-150 ease-in-out text-sky-600 hover:text-sky-500 focus:outline-none focus:underline"
|
||||
>
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -16,19 +16,6 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="mfaMethod" class="block text-sm font-medium text-gray-700 dark:text-gray-50">
|
||||
Choose 2FA Method
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<select id="mfaMethod" name="mfaMethod" class="form-select form-select-lg w-full" {{on "change" this.updateSelectedMethod}}>
|
||||
<option value="sms">SMS</option>
|
||||
<option value="email">Email</option>
|
||||
<option value="authenticator">Authenticator App</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="space-y-6" {{on "submit" this.verifyCode}}>
|
||||
<div>
|
||||
<label for="verificationCode" class="block text-sm font-medium text-gray-700 dark:text-gray-50">
|
||||
@@ -53,13 +40,6 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" id="rememberDevice" name="rememberDevice" class="form-checkbox" checked={{this.rememberDevice}} {{on "change" this.toggleRememberDevice}} />
|
||||
<label for="rememberDevice" class="ml-2 text-sm text-gray-700 dark:text-gray-50">
|
||||
Remember this device
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row space-x-2">
|
||||
<Button @icon="check-circle" @type="primary" @buttonType="submit" @text="Verify Code" @onClick={{this.verifyCode}} @isLoading={{this.isLoading}} />
|
||||
<Button @buttonType="button" @text="Cancel" @onClick={{fn (transition-to "auth.login")}} @disabled={{this.isLoading}} />
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
{{page-title "Two-Factor Authentication"}}
|
||||
<Layout::Section::Header @title="Two-Factor Authentication">
|
||||
{{page-title "2FA Config"}}
|
||||
<Layout::Section::Header @title="2FA Config">
|
||||
<Button @type="primary" @size="sm" @icon="save" @text="Save Changes" @onClick={{this.saveSettings}} @disabled={{this.isLoading}} @isLoading={{this.isLoading}} />
|
||||
</Layout::Section::Header>
|
||||
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
<div class="container mx-auto h-screen" {{increase-height-by 1200}}>
|
||||
<div class="max-w-3xl my-10 mx-auto space-y-4">
|
||||
<ContentPanel @title="Two-Factor Authentication Settings" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
||||
<ContentPanel @title="2FA Config" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
||||
<TwoFaSettings
|
||||
@selected2FAMethod={{this.selected2FAMethod}}
|
||||
@is2FAEnabled={{this.is2FAEnabled}}
|
||||
@twoFaMethods={{this.methods}}
|
||||
@twoFaSettings={{this.twoFaSettings}}
|
||||
@isLoading={{this.isLoading}}
|
||||
@saveSettings={{this.saveSettings}}
|
||||
@onTwoFaToggled={{this.onTwoFaToggled}}
|
||||
@onTwoFaMethodSelected={{this.onTwoFaMethodSelected}}
|
||||
/>
|
||||
</ContentPanel>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user