Skip to content

Commit

Permalink
Merge pull request #19 from fleetbase/dev-v0.1.3
Browse files Browse the repository at this point in the history
v0.1.3
  • Loading branch information
roncodes authored Oct 17, 2024
2 parents 030d25d + 2a81acb commit 898b8d0
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 9 deletions.
18 changes: 18 additions & 0 deletions addon/components/modals/change-user-password.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
<div class="px-4 text-gray-900 dark:text-gray-50">
<div class="mb-1 text-base font-semibold">
You are about to reset the password for
{{this.user.name}}
</div>
<div class="text-sm mb-4">Please enter the new password and confirm it below. You have the option to send the new credentials to the user via email by selecting the checkbox.</div>
<InputGroup>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
<InputGroup @name="New Password" @type="password" @value={{this.password}} @wrapperClass="mb-0i" />
<InputGroup @name="Confirm New Password" @type="password" @value={{this.confirmPassword}} @wrapperClass="mb-0i" />
</div>
</InputGroup>
<InputGroup>
<Checkbox @value={{this.sendCredentials}} @label="Send password credentials to user" @onToggle={{fn (mut this.sendCredentials)}} @alignItems="center" @labelClass="mb-0i" />
</InputGroup>
</div>
</Modal::Default>
49 changes: 49 additions & 0 deletions addon/components/modals/change-user-password.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';

export default class ModalsChangeUserPasswordComponent extends Component {
@service fetch;
@service notifications;
@tracked options = {};
@tracked password;
@tracked confirmPassword;
@tracked sendCredentials = true;
@tracked user;

constructor(owner, { options }) {
super(...arguments);
this.user = options.user;
this.options = options;
this.setupOptions();
}

setupOptions() {
this.options.title = 'Reset User Credentials';
this.options.acceptButtonText = 'Reset Credentials';
this.options.declineButtonHidden = true;
this.options.confirm = async (modal) => {
modal.startLoading();

try {
await this.fetch.post('auth/change-user-password', {
user: this.user.id,
password: this.password,
password_confirmation: this.confirmPassword,
send_credentials: this.sendCredentials,
});

this.notifications.success('User password reset.');

if (typeof this.options.onPasswordResetComplete === 'function') {
this.options.onPasswordResetComplete();
}

modal.done();
} catch (error) {
this.notifications.serverError(error);
modal.stopLoading();
}
};
}
}
30 changes: 29 additions & 1 deletion addon/controllers/roles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export default class RolesIndexController extends Controller {
*/
@action createRole() {
const formPermission = 'iam create role';
const role = this.store.createRecord('role');
const role = this.store.createRecord('role', { is_mutable: true });

this.editRole(role, {
title: this.intl.t('iam.roles.index.new-role'),
Expand All @@ -213,16 +213,30 @@ export default class RolesIndexController extends Controller {
acceptButtonDisabled: this.abilities.cannot(formPermission),
acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
formPermission,
keepOpen: true,
confirm: async (modal) => {
modal.startLoading();

if (!role.name || typeof role.name !== 'string') {
modal.stopLoading();
return this.notifications.warning('Role name is required.');
}

const roleName = role.name.toLowerCase();
if (roleName === 'administrator' || roleName.startsWith('admin')) {
modal.stopLoading();
return this.notifications.error('Creating a role with name "Administrator" or a role name that starts with "Admin" is prohibited, as the name is system reserved.');
}

if (this.abilities.cannot(formPermission)) {
modal.stopLoading();
return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
}

try {
await role.save();
this.notifications.success(this.intl.t('iam.roles.index.new-role-create'));
modal.done();
return this.hostRouter.refresh();
} catch (error) {
this.notifications.serverError(error);
Expand All @@ -249,6 +263,7 @@ export default class RolesIndexController extends Controller {
acceptButtonIcon: 'save',
acceptButtonDisabled: this.abilities.cannot(formPermission),
acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
keepOpen: true,
formPermission,
role,
setPermissions: (permissions) => {
Expand All @@ -257,13 +272,26 @@ export default class RolesIndexController extends Controller {
confirm: async (modal) => {
modal.startLoading();

if (!role.name || typeof role.name !== 'string') {
modal.stopLoading();
return this.notifications.warning('Role name is required.');
}

const roleName = role.name.toLowerCase();
if (roleName === 'administrator' || roleName.startsWith('admin')) {
modal.stopLoading();
return this.notifications.error('Creating a role with name "Administrator" or a role name that starts with "Admin" is prohibited, as the name is system reserved.');
}

if (this.abilities.cannot(formPermission)) {
modal.stopLoading();
return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
}

try {
await role.save();
this.notifications.success(this.intl.t('iam.roles.index.changes-role-saved'));
modal.done();
return this.hostRouter.refresh();
} catch (error) {
this.notifications.serverError(error);
Expand Down
18 changes: 18 additions & 0 deletions addon/controllers/users/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ export default class UsersIndexController extends Controller {
permission: 'iam verify user',
isVisible: (user) => !user.get('email_verified_at'),
},
{
label: this.intl.t('iam.users.index.change-user-password'),
fn: this.changeUserPassword,
className: 'text-danger',
isVisible: (user) => this.abilities.can('iam change-password-for user') || user.role_name === 'Administrator' || user.is_admin === true,
},
{
label: this.intl.t('iam.users.index.delete-user'),
fn: this.deleteUser,
Expand Down Expand Up @@ -454,6 +460,18 @@ export default class UsersIndexController extends Controller {
});
}

/**
* Change password for a user
*
* @void
*/
@action changeUserPassword(user) {
this.modalsManager.show('modals/change-user-password', {
keepOpen: true,
user,
});
}

/**
* Resends invite for a user to join.
*
Expand Down
2 changes: 1 addition & 1 deletion addon/templates/application.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<Layout::Sidebar::Item @route="console.iam.home" @icon="home">{{t "iam.common.dashboard"}}</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.iam.users" @icon="id-card" @permission="iam list user" @visible={{can "iam see user"}}>{{t "iam.common.user"}}</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.iam.groups" @icon="building" @permission="iam list group" @visible={{can "iam see group"}}>{{t "iam.common.group"}}</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.iam.roles" @icon="tag" @permission="iam list role" @visible={{can "iam see role"}}>{{t "iam.common.role"}}</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.iam.roles" @icon="tag" @permission="iam list role" @visible={{can "iam see role"}}>{{t "iam.common.roles"}}</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.iam.policies" @icon="shield" @permission="iam list policy" @visible={{can "iam see policy"}}>{{t "iam.common.policies"}}</Layout::Sidebar::Item>
</Layout::Sidebar::Panel>
</EmberWormhole>
Expand Down
1 change: 1 addition & 0 deletions app/components/modals/change-user-password.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@fleetbase/iam-engine/components/modals/change-user-password';
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/iam-engine",
"version": "0.1.2",
"version": "0.1.3",
"description": "Fleetbase IAM extension provides identity and access management module for managing users, permissions and policies.",
"fleetbase": {
"route": "iam"
Expand Down Expand Up @@ -42,7 +42,7 @@
},
"dependencies": {
"@fleetbase/ember-core": "^0.2.21",
"@fleetbase/ember-ui": "^0.2.34",
"@fleetbase/ember-ui": "^0.2.35",
"@babel/core": "^7.23.2",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions tests/integration/components/modals/change-user-password-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'dummy/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';

module('Integration | Component | modals/change-user-password', function (hooks) {
setupRenderingTest(hooks);

test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`<Modals::ChangeUserPassword />`);

assert.dom().hasText('');

// Template block usage:
await render(hbs`
<Modals::ChangeUserPassword>
template block text
</Modals::ChangeUserPassword>
`);

assert.dom().hasText('template block text');
});
});
1 change: 1 addition & 0 deletions translations/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ iam:
activate-user: Activate user...
delete-user: Delete user...
verify-user: Verify user...
change-user-password: Change user password...
new-user: New User
user-invited-join-your-organization-success: User has been invited to join your organization.
edit-user-title: Edit User
Expand Down

0 comments on commit 898b8d0

Please sign in to comment.