Skip to content
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: 1 addition & 1 deletion src/app/modules/user/store/user.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class UserEffects {
loadUserInfo$: Observable<Action> = this.actions$.pipe(
ofType(actions.UserActionTypes.LOAD_USER),
map((action: actions.LoadUser) => action.userId),
mergeMap((userId) =>
mergeMap((userId: string) =>
this.userService.loadUser(userId).pipe(
map((response) => new actions.LoadUserSuccess(response)),
catchError((error) => of(new actions.LoadUserFail(error)))
Expand Down
1 change: 1 addition & 0 deletions src/app/modules/users/models/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface User {
name: string;
email: string;
roles?: string[];
groups?: string[];
id: string;
tenant_id?: string;
deleted?: string;
Expand Down
20 changes: 20 additions & 0 deletions src/app/modules/users/services/users.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,24 @@ describe('UsersService', () => {
const grantRoleRequest = httpMock.expectOne(`${service.baseUrl}/${userId}/roles/${roleId}/revoke`);
expect(grantRoleRequest.request.method).toBe('POST');
});

it('add user to group', () => {
const userId = 'userId';
const group = 'admin';
const addGroupURL = `${service.baseUrl}/${userId}/groups/add`;

service.addUserToGroup(userId, group).subscribe();

expect(httpMock.expectOne(addGroupURL).request.method).toBe('POST');
});

it('remove user from group', () => {
const userId = 'userId';
const group = 'admin';
const removeGroupURL = `${service.baseUrl}/${userId}/groups/remove`;

service.removeUserFromGroup(userId, group).subscribe();

expect(httpMock.expectOne(removeGroupURL).request.method).toBe('POST');
});
});
13 changes: 13 additions & 0 deletions src/app/modules/users/services/users.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { User } from '../models/users';
import { environment } from './../../../../environments/environment';
@Injectable({
providedIn: 'root',
Expand All @@ -23,4 +24,16 @@ export class UsersService {
const url = `${this.baseUrl}/${userId}/roles/${roleId}/revoke`;
return this.http.post(url, null);
}

addUserToGroup(userId: string, group: string): Observable<User> {
return this.http.post<User>(`${this.baseUrl}/${userId}/groups/add`, {
group_name: group,
});
}

removeUserFromGroup(userId: string, group: string): Observable<User> {
return this.http.post<User>(`${this.baseUrl}/${userId}/groups/remove`, {
group_name: group,
});
}
}
42 changes: 42 additions & 0 deletions src/app/modules/users/store/user.actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,46 @@ describe('UserActions', () => {
const action = new actions.RevokeRoleUserFail('error');
expect(action.type).toEqual(actions.UserActionTypes.REVOKE_USER_ROLE_FAIL);
});

it('AddUserToGroup type is UserActionTypes.ADD_USER_TO_GROUP', () => {
const userId = 'userId';
const groupName = 'groupName';
const action = new actions.AddUserToGroup(userId, groupName);

expect(action.type).toEqual(actions.UserActionTypes.ADD_USER_TO_GROUP);
});

it('AddUserToGroupSuccess type is UserActionTypes.ADD_USER_TO_GROUP_SUCCESS', () => {
const payload: User = { id: 'id', email: 'email', name: 'name' };
const action = new actions.AddUserToGroupSuccess(payload);

expect(action.type).toEqual(actions.UserActionTypes.ADD_USER_TO_GROUP_SUCCESS);
});

it('AddUserToGroupFail type is UserActionTypes.ADD_USER_TO_GROUP_FAIL', () => {
const action = new actions.AddUserToGroupFail('error');

expect(action.type).toEqual(actions.UserActionTypes.ADD_USER_TO_GROUP_FAIL);
});

it('RemoveUserFromGroup type is UserActionTypes.REMOVE_USER_FROM_GROUP', () => {
const userId = 'userId';
const groupName = 'groupName';
const action = new actions.RemoveUserFromGroup(userId, groupName);

expect(action.type).toEqual(actions.UserActionTypes.REMOVE_USER_FROM_GROUP);
});

it('RemoveUserFromGroupSuccess type is UserActionTypes.REMOVE_USER_FROM_GROUP_SUCCESS', () => {
const payload: User = { id: 'id', email: 'email', name: 'name' };
const action = new actions.RemoveUserFromGroupSuccess(payload);

expect(action.type).toEqual(actions.UserActionTypes.REMOVE_USER_FROM_GROUP_SUCCESS);
});

it('RemoveUserFromGroupFail type is UserActionTypes.REMOVE_USER_FROM_GROUP_FAIL', () => {
const action = new actions.RemoveUserFromGroupFail('error');

expect(action.type).toEqual(actions.UserActionTypes.REMOVE_USER_FROM_GROUP_FAIL);
});
});
45 changes: 44 additions & 1 deletion src/app/modules/users/store/user.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export enum UserActionTypes {
REVOKE_USER_ROLE = '[User] REVOKE_USER_ROLE',
REVOKE_USER_ROLE_SUCCESS = '[User] REVOKE_USER_ROLE_SUCCESS',
REVOKE_USER_ROLE_FAIL = '[User] REVOKE_USER_ROLE_FAIL',
ADD_USER_TO_GROUP = '[User] ADD_USER_TO_GROUP',
ADD_USER_TO_GROUP_SUCCESS = '[User] ADD_USER_TO_GROUP_SUCCESS',
ADD_USER_TO_GROUP_FAIL = '[User] ADD_USER_TO_GROUP_FAIL',
REMOVE_USER_FROM_GROUP = '[User] REMOVE_USER_FROM_GROUP',
REMOVE_USER_FROM_GROUP_SUCCESS = '[User] REMOVE_USER_FROM_GROUP_SUCCESS',
REMOVE_USER_FROM_GROUP_FAIL = '[User] REMOVE_USER_FROM_GROUP_FAIL',
DEFAULT_USER = '[USER] DEFAULT_USER',
}

Expand Down Expand Up @@ -57,6 +63,37 @@ export class RevokeRoleUserFail implements Action {
public readonly type = UserActionTypes.REVOKE_USER_ROLE_FAIL;
constructor(public error: string) {}
}

export class AddUserToGroup implements Action {
public readonly type = UserActionTypes.ADD_USER_TO_GROUP;
constructor(public userId: string, public groupName: string) {}
}

export class AddUserToGroupSuccess implements Action {
public readonly type = UserActionTypes.ADD_USER_TO_GROUP_SUCCESS;
constructor(readonly payload: User) {}
}

export class AddUserToGroupFail implements Action {
public readonly type = UserActionTypes.ADD_USER_TO_GROUP_FAIL;
constructor(public error: string) {}
}

export class RemoveUserFromGroup implements Action {
public readonly type = UserActionTypes.REMOVE_USER_FROM_GROUP;
constructor(public userId: string, public groupName: string) {}
}

export class RemoveUserFromGroupSuccess implements Action {
public readonly type = UserActionTypes.REMOVE_USER_FROM_GROUP_SUCCESS;
constructor(readonly payload: User) {}
}

export class RemoveUserFromGroupFail implements Action {
public readonly type = UserActionTypes.REMOVE_USER_FROM_GROUP_FAIL;
constructor(public error: string) {}
}

export class DefaultUser implements Action {
public readonly type = UserActionTypes.DEFAULT_USER;
}
Expand All @@ -71,4 +108,10 @@ export type UserActions =
| GrantRoleUserFail
| RevokeRoleUser
| RevokeRoleUserSuccess
| RevokeRoleUserFail;
| RevokeRoleUserFail
| AddUserToGroup
| AddUserToGroupSuccess
| AddUserToGroupFail
| RemoveUserFromGroup
| RemoveUserFromGroupSuccess
| RemoveUserFromGroupFail;
72 changes: 72 additions & 0 deletions src/app/modules/users/store/user.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,76 @@ describe('UserEffects', () => {
expect(action.type).toEqual(UserActionTypes.REVOKE_USER_ROLE_FAIL);
});
});

it('action type is ADD_USER_TO_GROUP_SUCCESS when service is executed sucessfully', async () => {
const userId = 'userId';
const groupName = 'groupName';
actions$ = of({
type: UserActionTypes.ADD_USER_TO_GROUP,
userId,
groupName,
});

spyOn(toastrService, 'success');
spyOn(service, 'addUserToGroup').and.returnValue(of(user));

effects.addUserToGroup$.subscribe((action) => {
expect(toastrService.success).toHaveBeenCalledWith('Add user to group success');
expect(action.type).toEqual(UserActionTypes.ADD_USER_TO_GROUP_SUCCESS);
});
});

it('action type is ADD_USER_TO_GROUP_FAIL when service is executed and fail', async () => {
const userId = 'userId';
const groupName = 'groupName';
actions$ = of({
type: UserActionTypes.ADD_USER_TO_GROUP,
userId,
groupName,
});

spyOn(toastrService, 'error');
spyOn(service, 'addUserToGroup').and.returnValue(throwError({ error: { message: 'error' } }));

effects.addUserToGroup$.subscribe((action) => {
expect(toastrService.error).toHaveBeenCalled();
expect(action.type).toEqual(UserActionTypes.ADD_USER_TO_GROUP_FAIL);
});
});

it('action type is REMOVE_USER_FROM_GROUP_SUCCESS when service is executed succesfully', async () => {
const userId = 'userId';
const groupName = 'groupName';
actions$ = of({
type: UserActionTypes.REMOVE_USER_FROM_GROUP,
userId,
groupName,
});

spyOn(toastrService, 'success');
spyOn(service, 'removeUserFromGroup').and.returnValue(of(user));

effects.removeUserFromGroup$.subscribe((action) => {
expect(toastrService.success).toHaveBeenCalledWith('Remove user from group success');
expect(action.type).toEqual(UserActionTypes.REMOVE_USER_FROM_GROUP_SUCCESS);
});
});

it('action type is REMOVE_USER_FROM_GROUP_FAIL when service is executed succesfully', async () => {
const userId = 'userId';
const groupName = 'groupName';
actions$ = of({
type: UserActionTypes.REMOVE_USER_FROM_GROUP,
userId,
groupName,
});

spyOn(toastrService, 'error');
spyOn(service, 'removeUserFromGroup').and.returnValue(throwError({ error: { message: 'error' } }));

effects.removeUserFromGroup$.subscribe((action) => {
expect(toastrService.error).toHaveBeenCalled();
expect(action.type).toEqual(UserActionTypes.REMOVE_USER_FROM_GROUP_FAIL);
});
});
});
36 changes: 36 additions & 0 deletions src/app/modules/users/store/user.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,40 @@ export class UserEffects {
)
)
);

@Effect()
addUserToGroup$: Observable<Action> = this.actions$.pipe(
ofType(actions.UserActionTypes.ADD_USER_TO_GROUP),
map((action: actions.AddUserToGroup) => action),
mergeMap((action) =>
this.userService.addUserToGroup(action.userId, action.groupName).pipe(
map((response) => {
this.toastrService.success('Add user to group success');
return new actions.AddUserToGroupSuccess(response);
}),
catchError((error) => {
this.toastrService.error(error.error.message);
return of(new actions.AddUserToGroupFail(error));
})
)
)
);

@Effect()
removeUserFromGroup$: Observable<Action> = this.actions$.pipe(
ofType(actions.UserActionTypes.REMOVE_USER_FROM_GROUP),
map((action: actions.RemoveUserFromGroup) => action),
mergeMap((action) =>
this.userService.removeUserFromGroup(action.userId, action.groupName).pipe(
map((response) => {
this.toastrService.success('Remove user from group success');
return new actions.RemoveUserFromGroupSuccess(response);
}),
catchError((error) => {
this.toastrService.error(error.error.message);
return of(new actions.RemoveUserFromGroupFail(error));
})
)
)
);
}
64 changes: 64 additions & 0 deletions src/app/modules/users/store/user.reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,70 @@ describe('userReducer', () => {
expect(state.isLoading).toEqual(false);
});

it('on AddUserToGroup, isLoading is true', () => {
const userId = 'userId';
const groupName = 'groupName';
const action = new actions.AddUserToGroup(userId, groupName);
const state = userReducer(initialState, action);

expect(state.isLoading).toEqual(true);
});

it('on AddUserToGroupSuccess, user groups should change', () => {
const currentState: UserState = {
data: [{ id: 'id', name: 'name', email: 'email', groups: null }],
isLoading: false,
message: '',
};
const userWithGroupAdded: User = { id: 'id', name: 'name', email: 'email', groups: ['group'] };
const action = new actions.AddUserToGroupSuccess(userWithGroupAdded);
const state = userReducer(currentState, action);

expect(state.data).toEqual([userWithGroupAdded]);
expect(state.isLoading).toEqual(false);
expect(state.message).toEqual('Add user to group success');
});

it('on AddUserToGroupFail, should show a message with an error message', () => {
const action = new actions.AddUserToGroupFail('error');
const state = userReducer(initialState, action);

expect(state.message).toEqual('Something went wrong adding user to group');
expect(state.isLoading).toEqual(false);
});

it('on RemoveUserFromGroup, isLoading is true', () => {
const userId = 'userId';
const groupName = 'groupName';
const action = new actions.RemoveUserFromGroup(userId, groupName);
const state = userReducer(initialState, action);

expect(state.isLoading).toEqual(true);
});

it('on RemoveUserFromGroupSuccess, user groups should change', () => {
const currentState: UserState = {
data: [{ id: 'id', name: 'name', email: 'email', groups: ['group'] }],
isLoading: false,
message: '',
};
const userWithGroupRemoved: User = { id: 'id', name: 'name', email: 'email', groups: null };
const action = new actions.RemoveUserFromGroupSuccess(userWithGroupRemoved);
const state = userReducer(currentState, action);

expect(state.data).toEqual([userWithGroupRemoved]);
expect(state.isLoading).toEqual(false);
expect(state.message).toEqual('Remove user from group success');
});

it('on RemoveUserFromGroupFail, should show a message with an error message', () => {
const action = new actions.RemoveUserFromGroupFail('error');
const state = userReducer(initialState, action);

expect(state.message).toEqual('Something went wrong removing user from group');
expect(state.isLoading).toEqual(false);
});

it('on Default, ', () => {
const action = new actions.DefaultUser();
const state = userReducer(initialState, action);
Expand Down
Loading