Skip to content

Commit

Permalink
feat(admin): Add OIDC information
Browse files Browse the repository at this point in the history
  • Loading branch information
theotime2005 committed Feb 5, 2025
1 parent 1e30212 commit e558651
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 29 deletions.
16 changes: 16 additions & 0 deletions admin/app/components/users/user-overview.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ export default class UserOverview extends Component {
@service pixToast;
@service references;
@service store;
@service oidcIdentityProviders;

@tracked displayAnonymizeModal = false;
@tracked isEditionMode = false;
@tracked authenticationMethods = [];

languages = this.references.availableLanguages;
locales = this.references.availableLocales;
Expand All @@ -39,6 +41,9 @@ export default class UserOverview extends Component {
constructor() {
super(...arguments);
this.form = this.store.createRecord('user-form');
Promise.resolve(this.args.user.authenticationMethods).then((authenticationMethods) => {
this.authenticationMethods = authenticationMethods;
});
}

get externalURL() {
Expand Down Expand Up @@ -86,6 +91,14 @@ export default class UserOverview extends Component {
return this.args.user.username ? null : 'obligatoire';
}

get useOidcAuthentication() {
const oidcProvidersCodes = this.oidcIdentityProviders.list.map((provider) => provider.code);
const userHasThisOidcAuthenticationMethod = this.authenticationMethods.any((authenticationMethod) =>
oidcProvidersCodes.includes(authenticationMethod.identityProvider),
);
return userHasThisOidcAuthenticationMethod ? 'common.words.yes' : 'common.words.no';
}

_initForm() {
this.form.firstName = this.args.user.firstName;
this.form.lastName = this.args.user.lastName;
Expand Down Expand Up @@ -331,6 +344,9 @@ export default class UserOverview extends Component {
{{/if}}
</span>
</li>
<li class="user-detail-personal-information-section__user-informations flex space-between gap-4x">
<span>{{t "components.users.user-overview.sso"}} : {{t this.useOidcAuthentication}}</span>
</li>
</ul>

<ul class="user-detail-personal-information-section__infogroup">
Expand Down
71 changes: 71 additions & 0 deletions admin/tests/integration/components/users/user-overview-test.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ module('Integration | Component | users | user-overview', function (hooks) {

test('displays the update button', async function (assert) {
// given
const store = this.owner.lookup('service:store');
const user = {
firstName: 'John',
lastName: 'Harry',
email: '[email protected]',
username: 'john.harry0102',
};
user.authenticationMethods = [await store.createRecord('authentication-method', { identityProvider: 'abc' })];

// when
const screen = await render(<template><UserOverview @user={{user}} /></template>);
Expand Down Expand Up @@ -392,13 +394,15 @@ module('Integration | Component | users | user-overview', function (hooks) {
module('When the admin member click to update user details', function () {
test('displays the edit and cancel buttons', async function (assert) {
// given
const store = this.owner.lookup('service:store');
const user = {
firstName: 'John',
lastName: 'Harry',
email: '[email protected]',
username: null,
lang: null,
};
user.authenticationMethods = [await store.createRecord('authentication-method', { identityProvider: 'abc' })];

// when
const screen = await render(<template><UserOverview @user={{user}} /></template>);
Expand All @@ -416,6 +420,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
username: null,
authenticationMethods: [],
});

// when
Expand Down Expand Up @@ -450,6 +455,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
username: null,
authenticationMethods: [],
});

// when
Expand All @@ -469,6 +475,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
username: null,
authenticationMethods: [],
});

// when
Expand All @@ -486,6 +493,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
username: null,
authenticationMethods: [],
});

// when
Expand All @@ -505,6 +513,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: null,
username: 'user.name1212',
authenticationMethods: [],
});

// when
Expand All @@ -522,6 +531,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: null,
username: 'user.name1212',
authenticationMethods: [],
});

// when
Expand All @@ -543,6 +553,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: null,
username: undefined,
authenticationMethods: [],
});

// when
Expand All @@ -563,6 +574,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
username: null,
authenticationMethods: [],
});

const screen = await render(<template><UserOverview @user={{user}} /></template>);
Expand All @@ -588,6 +600,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
username: null,
authenticationMethods: [],
});

const screen = await render(<template><UserOverview @user={{user}} /></template>);
Expand Down Expand Up @@ -660,6 +673,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
firstName: 'John',
email: '[email protected]',
isPixAgent: true,
authenticationMethods: [],
});

// when
Expand All @@ -675,11 +689,67 @@ module('Integration | Component | users | user-overview', function (hooks) {
assert.dom(anonymizationDisabledTooltip).exists();
});
});

module('Displays OIDC information', function (hooks) {
class OidcIdentityProvidersStub extends Service {
get list() {
return [
{
code: 'SUNLIGHT_NAVIGATIONS',
organizationName: 'Sunlight Navigations',
},
];
}
}

hooks.beforeEach(function () {
this.owner.register('service:oidc-identity-providers', OidcIdentityProvidersStub);
});

test('When user has not OIDC authentication method', async function (assert) {
// given
const store = this.owner.lookup('service:store');
const user = {
firstName: 'John',
lastName: 'Harry',
email: '[email protected]',
username: 'john.harry0102',
};
user.authenticationMethods = [await store.createRecord('authentication-method', { identityProvider: 'abc' })];

// when
const screen = await render(<template><UserOverview @user={{user}} /></template>);

// then
assert.dom(screen.getByText('SSO : Non')).exists();
});

test('When user has OIDC authentication method', async function (assert) {
// given
const store = this.owner.lookup('service:store');
const user = {
firstName: 'John',
lastName: 'Harry',
email: '[email protected]',
username: 'john.harry0102',
};
user.authenticationMethods = [
await store.createRecord('authentication-method', { identityProvider: 'SUNLIGHT_NAVIGATIONS' }),
];

// when
const screen = await render(<template><UserOverview @user={{user}} /></template>);

// then
assert.dom(screen.getByText('SSO : Oui')).exists();
});
});
});

module('When the admin member does not have access to users actions scope', function () {
test('does not display the action buttons "Modifier" and "Anonymiser cet utilisateur"', async function (assert) {
// given
const store = this.owner.lookup('service:store');
class AccessControlStub extends Service {
hasAccessToUsersActionsScope = false;
}
Expand All @@ -690,6 +760,7 @@ module('Integration | Component | users | user-overview', function (hooks) {
email: '[email protected]',
username: 'john.harry0102',
};
user.authenticationMethods = [await store.createRecord('authentication-method', { identityProvider: 'abc' })];
this.owner.register('service:access-control', AccessControlStub);

// when
Expand Down
50 changes: 21 additions & 29 deletions admin/tests/unit/components/users/user-overview-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,15 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('#externalURL', function () {
test('it should generate dashboard URL based on environment and object', async function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');

const args = {
const baseUrl = 'https://metabase.pix.fr/dashboard/132?id=';
ENV.APP.USER_DASHBOARD_URL = baseUrl;
const component = createGlimmerComponent('component:users/user-overview', {
user: {
id: 1,
authenticationMethods: [],
},
};
const baseUrl = 'https://metabase.pix.fr/dashboard/132?id=';
const expectedUrl = baseUrl + args.user.id;

ENV.APP.USER_DASHBOARD_URL = baseUrl;
component.args = args;
});
const expectedUrl = baseUrl + '1';

// when
const actualUrl = component.externalURL;
Expand All @@ -38,9 +35,8 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('when user already has an email', function () {
test('it should allow email modification', async function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { email: '[email protected]', firstName: 'Lisa', lastName: 'Dupont' };
component.args.user = user;
const user = { email: '[email protected]', firstName: 'Lisa', lastName: 'Dupont', authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });

// when & then
assert.true(component.canModifyEmail);
Expand All @@ -50,9 +46,8 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('when user has an username', function () {
test('it should also allow email modification', async function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { username: 'lisa.dupont', firstName: 'Lisa', lastName: 'Dupont' };
component.args.user = user;
const user = { username: 'lisa.dupont', firstName: 'Lisa', lastName: 'Dupont', authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });

// when & then
assert.true(component.canModifyEmail);
Expand All @@ -62,9 +57,8 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('when user has neither a username nor an email', function () {
test('it should not allow email modification', async function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { firstName: 'Lisa', lastName: 'Dupont' };
component.args.user = user;
const user = { firstName: 'Lisa', lastName: 'Dupont', authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });

// when & then
assert.false(component.canModifyEmail);
Expand All @@ -76,7 +70,8 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('when user has no login informations yet', function () {
test('should not display temporary blocked date', function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });

// when && then
assert.false(component.shouldDisplayTemporaryBlockedDate);
Expand All @@ -86,9 +81,8 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('when user has login but not temporary blocked', function () {
test('should not display temporary blocked date', function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { firstName: 'Lisa', lastName: 'Dupont' };
component.args.user = user;
const user = { firstName: 'Lisa', lastName: 'Dupont', authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });
const getTemporaryBlockedUntilProperty = () => null;
const userLoginProxy = { get: getTemporaryBlockedUntilProperty };
component.args.user.userLogin = userLoginProxy;
Expand All @@ -101,11 +95,10 @@ module('Unit | Component | users | user-overview', function (hooks) {
module('when user has login and temporary blocked date', function () {
test('should display temporary blocked date when now date is after temporaty blocked date', function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { firstName: 'Lisa', lastName: 'Dupont' };
const user = { firstName: 'Lisa', lastName: 'Dupont', authenticationMethods: [] };
const getTemporaryBlockedUntilProperty = () => new Date(Date.now() + 3600 * 1000);
const component = createGlimmerComponent('component:users/user-overview', { user });
const userLoginProxy = { get: getTemporaryBlockedUntilProperty };
component.args.user = user;
component.args.user.userLogin = userLoginProxy;

// when && then
Expand All @@ -114,9 +107,8 @@ module('Unit | Component | users | user-overview', function (hooks) {

test('should not display temporary blocked date when now date is before temporaty blocked date', function (assert) {
// given
const component = createGlimmerComponent('component:users/user-overview');
const user = { firstName: 'Lisa', lastName: 'Dupont' };
component.args.user = user;
const user = { firstName: 'Lisa', lastName: 'Dupont', authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });
const getTemporaryBlockedUntilProperty = () => new Date(Date.now() - 3600 * 1000);
const userLoginProxy = { get: getTemporaryBlockedUntilProperty };
component.args.user.userLogin = userLoginProxy;
Expand All @@ -131,7 +123,7 @@ module('Unit | Component | users | user-overview', function (hooks) {
test('should empty organization learners', async function (assert) {
// given
const organizationLearners = [{ firstName: 'fanny', lastName: 'epi' }];
const user = { organizationLearners, save: sinon.stub().resolves() };
const user = { organizationLearners, save: sinon.stub().resolves(), authenticationMethods: [] };
const component = createGlimmerComponent('component:users/user-overview', { user });

// when
Expand Down
3 changes: 3 additions & 0 deletions admin/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,9 @@
}
},
"copied": "Copied!"
},
"user-overview": {
"sso": "SSO"
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions admin/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@
}
},
"copied": "Copié !"
},
"user-overview": {
"sso": "SSO"
}
}
},
Expand Down

0 comments on commit e558651

Please sign in to comment.