Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added org user API integration #6817

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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