Skip to content

Commit

Permalink
Added org user API integration (#6817)
Browse files Browse the repository at this point in the history
* Added APi integration

Signed-off-by: Chaitali Mane <cmane@progress.com>

* Added code integration

Signed-off-by: Chaitali Mane <cmane@progress.com>

* Added cypress test case

Signed-off-by: Chaitali Mane <cmane@progress.com>
  • Loading branch information
chaitali-mane authored and vinay033 committed Mar 24, 2022
1 parent acbb0a4 commit 7c40162
Show file tree
Hide file tree
Showing 12 changed files with 366 additions and 14 deletions.
2 changes: 2 additions & 0 deletions components/automate-ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ import { RunlistRequests } from './entities/runlists/runlists.requests';
import { ServerRequests } from './entities/servers/server.requests';
import { NodeCredentialRequests } from './entities/node-credentials/node-credential.requests';
import { OrgRequests } from './entities/orgs/org.requests';
import { OrgUserRequests } from './entities/org-users/org-users.requests';
import { PolicyFileRequests } from './entities/policy-files/policy-file.requests';
import { ServiceGroupsRequests } from './entities/service-groups/service-groups.requests';
import { TeamRequests } from './entities/teams/team.requests';
Expand Down Expand Up @@ -384,6 +385,7 @@ import {
ServerRequests,
NodeCredentialRequests,
OrgRequests,
OrgUserRequests,
PolicyFileRequests,
ServiceGroupsRequests,
SessionStorageService,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Action } from '@ngrx/store';
import { OrgUser } from './org-users.model';

export enum OrgUsersActionTypes {
GET_ALL = 'USERS::GET_ALL',
GET_ALL_SUCCESS = 'USERS::GET_ALL::SUCCESS',
GET_ALL_FAILURE = 'USERS::GET_ALL::FAILURE'
}

export interface UsersSuccessPayload {
orgUsers: OrgUser[];
}

export interface UsersPayload {
org_id: string;
server_id: string;
}

export class GetUsers implements Action {
readonly type = OrgUsersActionTypes.GET_ALL;
constructor(public payload: UsersPayload) { }
}

export class GetUsersSuccess implements Action {
readonly type = OrgUsersActionTypes.GET_ALL_SUCCESS;
constructor(public payload: UsersSuccessPayload) { }
}

export class GetUsersFailure implements Action {
readonly type = OrgUsersActionTypes.GET_ALL_FAILURE;
constructor(public payload: HttpErrorResponse) { }
}

export type OrgUsersActions =
| GetUsers
| GetUsersSuccess
| GetUsersFailure;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of as observableOf } from 'rxjs';
import { catchError, mergeMap, map } from 'rxjs/operators';
import { CreateNotification } from 'app/entities/notifications/notification.actions';
import { Type } from 'app/entities/notifications/notification.model';

import {
GetUsers,
GetUsersSuccess,
GetUsersFailure,
UsersSuccessPayload,
OrgUsersActionTypes
} from './org-users.action';

import { OrgUserRequests } from './org-users.requests';

@Injectable()
export class OrgUserEffects {
constructor(
private actions$: Actions,
private requests: OrgUserRequests
) { }

getUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(OrgUsersActionTypes.GET_ALL),
mergeMap(({ payload: { server_id, org_id } }: GetUsers) =>
this.requests.OrgUserRequests(server_id, org_id).pipe(
map((resp: UsersSuccessPayload) => new GetUsersSuccess(resp)),
catchError((error: HttpErrorResponse) =>
observableOf(new GetUsersFailure(error)))
))));

getUsersFailure$ = createEffect(() =>
this.actions$.pipe(
ofType(OrgUsersActionTypes.GET_ALL_FAILURE),
map(({ payload }: GetUsersFailure) => {
const msg = payload.error.error;
return new CreateNotification({
type: Type.error,
message: `Could not get clients: ${msg || payload.error}`
});
})));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface OrgUser {
user_id: string;
server_id: string;
org_id: string;
infra_server_username: string;
first_name: string;
last_name: string;
email_id: string;
middle_name: string;
display_name: string;
connector: string;
automate_user_id: string;
is_admin: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { set, pipe } from 'lodash/fp';
import { EntityStatus } from 'app/entities/entities';
import { OrgUsersActionTypes, OrgUsersActions } from './org-users.action';
import { OrgUser } from './org-users.model';

export interface OrgUserEntityState extends EntityState<OrgUser> {
getAllStatus: EntityStatus;
orgUserList: {
orgUsers: OrgUser[]
};
}

const GET_ALL_STATUS = 'getAllStatus';

export const orgUserEntityAdapter: EntityAdapter<OrgUser> =
createEntityAdapter<OrgUser>({
selectId: (orgUser: OrgUser) => orgUser.user_id
});

export const OrgUserEntityInitialState: OrgUserEntityState =
orgUserEntityAdapter.getInitialState(<OrgUserEntityState>{
getAllStatus: EntityStatus.notLoaded
});

export function orgUserEntityReducer(
state: OrgUserEntityState = OrgUserEntityInitialState,
action: OrgUsersActions): OrgUserEntityState {

switch (action.type) {
case OrgUsersActionTypes.GET_ALL:
return set(GET_ALL_STATUS, EntityStatus.loading, orgUserEntityAdapter.removeAll(state));

case OrgUsersActionTypes.GET_ALL_SUCCESS:
return pipe(
set(GET_ALL_STATUS, EntityStatus.loadingSuccess),
set('orgUserList.items', action.payload.orgUsers || [])
)(state) as OrgUserEntityState;

case OrgUsersActionTypes.GET_ALL_FAILURE:
return set(GET_ALL_STATUS, EntityStatus.loadingFailure, state);

default:
return state;
}
}

export const getEntityById = (id: string) =>
(state: OrgUserEntityState) => state.entities[id];
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment as env } from 'environments/environment';
import { UsersSuccessPayload } from './org-users.action';

@Injectable()
export class OrgUserRequests {

constructor(private http: HttpClient) { }

public OrgUserRequests(server_id: string, org_id: string)
: Observable<UsersSuccessPayload> {
const url = `${env.infra_proxy_url}/servers/${server_id}/orgs/${org_id}/automateinfraorgusers`;
return this.http.get<UsersSuccessPayload>(url);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { OrgUserEntityState, orgUserEntityAdapter } from './org-users.reducer';

export const orgUserState = createFeatureSelector<OrgUserEntityState>('OrgUsers');
export const {
selectAll: allUsers,
selectEntities: userEntities
} = orgUserEntityAdapter.getSelectors(orgUserState);

export const getAllStatus = createSelector(
orgUserState,
(state) => state.getAllStatus
);

export const orgUserList = createSelector(
orgUserState,
(state) => state.orgUserList
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
<app-paginator [length]="total" [pageSize]="per_page" [pageIndex]="current_page"
(changePage)="onUpdatePage($event)"></app-paginator>
</div>
<chef-table>
<div class="empty-section" cy-data="empty-list" *ngIf="!loading && !users.length && current_page === 1">
<img alt="No preview" src="/assets/img/no_preview.gif" />
</div>
<chef-table data-cy=orgUsers-table-container>
<chef-thead>
<chef-tr class="no_border_tr">
<chef-th class="no_border_th">Chef Server User Name</chef-th>
Expand All @@ -18,13 +21,13 @@
</chef-tr>
</chef-thead>
<chef-tbody>
<chef-tr>
<chef-td>User Name</chef-td>
<chef-td>Automate Name</chef-td>
<chef-td>automatename@email.com</chef-td>
<chef-tr *ngFor="let user of users">
<chef-td>{{user.infra_server_username}}</chef-td>
<chef-td>{{user.automate_user_id}}</chef-td>
<chef-td>{{user.email_id}}</chef-td>
<chef-td class="three-dot-column">
<mat-select panelClass="chef-control-menu">
<mat-option data-cy="resetPEMKey" (onSelectionChange)="resetPEMKey()">Reset PEM Key</mat-option>
<mat-option data-cy="resetPEMKey" (onSelectionChange)="resetPEMKey()">Reset User Key</mat-option>
</mat-select>
</chef-td>
</chef-tr>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { Component, Input, OnInit, OnDestroy, EventEmitter, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { LayoutFacadeService, Sidebar } from 'app/entities/layout/layout.facade';
import { OrgUser } from '../../../entities/org-users/org-users.model';
import { GetUsers } from '../../../entities/org-users/org-users.action';
import { getAllStatus, orgUserList } from '../../../entities/org-users/org-users.selectors';
import { Store } from '@ngrx/store';

import { combineLatest, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { isNil } from 'lodash/fp';
import { NgrxStateAtom } from 'app/ngrx.reducers';
import { EntityStatus } from 'app/entities/entities';

@Component({
selector: 'app-org-users',
Expand All @@ -13,22 +22,41 @@ export class OrgUsersComponent implements OnInit, OnDestroy {
@Input() orgId: string;
@Output() resetKeyRedirection = new EventEmitter<boolean>();

//Will variable add type at time of API integration
public users;
public usersListLoading: boolean = false;
public authFailure: boolean = false;
public loading: boolean = false;
public current_page:number = 1;
public per_page:number = 100;
public usersState: { orgUsers: OrgUser[] };
public users: OrgUser[] = [];
public usersListLoading = false;
public authFailure = false;
public loading = false;
public current_page = 1;
public per_page = 100;
public total: number;
private isDestroyed = new Subject<boolean>();

constructor(
private store: Store<NgrxStateAtom>,
private layoutFacade: LayoutFacadeService
) {}

ngOnInit(): void {
this.layoutFacade.showSidebar(Sidebar.Infrastructure);

this.getOrgUsersData();

combineLatest([
this.store.select(getAllStatus),
this.store.select(orgUserList)
]).pipe(takeUntil(this.isDestroyed))
.subscribe(([getUsersSt, OrgUsersState]) => {
if (getUsersSt === EntityStatus.loadingSuccess && !isNil(OrgUsersState)) {
this.usersState = OrgUsersState;
this.users = this.usersState.orgUsers;
this.usersListLoading = false;
this.loading = false;
} else if (getUsersSt === EntityStatus.loadingFailure) {
this.usersListLoading = false;
this.authFailure = true;
}
});
}

ngOnDestroy(): void {
Expand All @@ -40,6 +68,15 @@ export class OrgUsersComponent implements OnInit, OnDestroy {
this.resetKeyRedirection.emit(resetLink);
}

getOrgUsersData(): void {
const payload = {
server_id: this.serverId,
org_id: this.orgId
};

this.store.dispatch(new GetUsers(payload));
}

onPageChange(event: number): void {
this.current_page = event;
this.loading = true;
Expand Down
2 changes: 2 additions & 0 deletions components/automate-ui/src/app/ngrx.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { NodeCredentialEffects } from './entities/node-credentials/node-credenti
import { NodeRunlistEffects } from './entities/nodeRunlists/nodeRunlists.effects';
import { NotificationRuleEffects } from './entities/notification_rules/notification_rule.effects';
import { OrgEffects } from './entities/orgs/org.effects';
import { OrgUserEffects } from './entities/org-users/org-users.effects';
import { PolicyEffects } from './entities/policies/policy.effects';
import { PolicyFileEffects } from './entities/policy-files/policy-file.effects';
import { ProfileEffects } from './entities/profiles/profile.effects';
Expand Down Expand Up @@ -84,6 +85,7 @@ import { UserPreferencesEffects } from './services/user-preferences/user-prefere
NodeRunlistEffects,
NotificationRuleEffects,
OrgEffects,
OrgUserEffects,
PolicyEffects,
PolicyFileEffects,
ProfileEffects,
Expand Down
4 changes: 4 additions & 0 deletions components/automate-ui/src/app/ngrx.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import * as nodeRunlistEntity from './entities/nodeRunlists/nodeRunlists.reducer
import * as notificationEntity from './entities/notifications/notification.reducer';
import * as NotificationRuleEntity from './entities/notification_rules/notification_rule.reducer';
import * as orgEntity from './entities/orgs/org.reducer';
import * as OrgUserEntity from './entities/org-users/org-users.reducer';
import * as permEntity from './entities/userperms/userperms.reducer';
import * as policyEntity from './entities/policies/policy.reducer';
import * as policyFileEntity from './entities/policy-files/policy-file.reducer';
Expand Down Expand Up @@ -121,6 +122,7 @@ export interface NgrxStateAtom {
notifications: notificationEntity.NotificationEntityState;
notificationRules: NotificationRuleEntity.NotificationRuleEntityState;
orgs: orgEntity.OrgEntityState;
OrgUsers: OrgUserEntity.OrgUserEntityState;
policies: policyEntity.PolicyEntityState;
policyFiles: policyFileEntity.PolicyFileEntityState;
policyFileDetails: policyFileDetailsEntity.PolicyFileDetailsEntityState;
Expand Down Expand Up @@ -274,6 +276,7 @@ export const defaultInitialState = {
nodeCredentialDetails: nodeCredentialDetailsEntity.NodeCredentialEntityInitialState,
servers: serverEntity.ServerEntityInitialState,
orgs: orgEntity.OrgEntityInitialState,
OrgUsers: OrgUserEntity.OrgUserEntityInitialState,
serviceGroups: serviceGroups.ServiceGroupEntityInitialState,
teams: teamEntity.TeamEntityInitialState,
desktops: desktopEntity.desktopEntityInitialState,
Expand Down Expand Up @@ -346,6 +349,7 @@ export const ngrxReducers = {
runlist: runlistEntity.runlistEntityReducer,
servers: serverEntity.serverEntityReducer,
orgs: orgEntity.orgEntityReducer,
OrgUsers: OrgUserEntity.orgUserEntityReducer,
nodeCredential: nodeCredentialEntity.nodeCredentialEntityReducer,
nodeCredentialDetails: nodeCredentialDetailsEntity.nodeCredentialDetailsEntityReducer,
serviceGroups: serviceGroups.serviceGroupsEntityReducer,
Expand Down
Loading

0 comments on commit 7c40162

Please sign in to comment.