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

Feat.update user endpoint #1948

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
72 changes: 35 additions & 37 deletions features/API-admin-user/Create_new_user.feature
Original file line number Diff line number Diff line change
@@ -1,42 +1,40 @@
@api-admin-user
Feature: Create new user

Background:
Given a logged-in user on the Swagger UI page
Given the user has access to 'email', 'first name' and 'last name' of the user to create

Scenario: Successfully create new 'disaster-manager' user
Given the user is using the `api/user` endpoint
Given the user has filled in 'email', 'first name' and 'last name'
Given the user also uses the 'email' as 'username'
Given the 'middleName' property is removed (as it's optional)
Given the user has generated a random password using https://passwordsgenerator.net/ and filled it in
Given the user has trimmed the country-list to only the relevant countries (on production: always just 1 country)
Given the user leaves the role on 'disaster-manager' and the status on 'active'
When the user presses 'Execute'
Then a status 201 is returned and an object with 'email' and 'token' properties

Scenario: Successfully create new 'guest' user
Given the user is using the `api/user` endpoint
Given everything is filled in as in previous scenario, except role = 'guest'
When the user presses 'Execute'
Then a status 201 is returned and an object with 'email' and 'token' properties

--------------------------------
NOTE: Below scenario is not in the exact right location at the moment, but closely related to above scenarios.

Scenario: Successfully create new user in Mailchimp 1-by-1
Given the user is logged in to mailchimp 'IbfSystem' using credentials from Bitwarden
Given the user has navigated via 'Audience' and 'All contacts' and 'Add contacts' to 'Add subscriber'
Given the user has filled in 'email', 'first name' and 'last name'
Given the user has added the right country-tag (e.g. 'Zambia' for 'Zambia')
Given the user has checked the permission checkbox
When clicking 'subscribe'
Then the user appears in the audience with the right tag and the status 'Subscribed'

Scenario: Successfully create new user in Mailchimp through import
Given the user is logged in to mailchimp 'IbfSystem' using credentials from Bitwarden
When the user has navigated via 'Audience' and 'All contacts' and 'Add contacts' to 'Import contacts'
Then this can be used to achieve the same result as above in bulk
Background:
Given a logged-in user on the Swagger UI page
Given the user has access to 'email', 'first name' and 'last name' of the user to create

Scenario: Successfully create new 'disaster-manager' user
Given the user is using the `api/user` endpoint
Given the user has filled in 'email', 'first name' and 'last name'
Given the 'middleName' property is removed (as it's optional)
Given the user has generated a random password using https://passwordsgenerator.net/ and filled it in
Given the user has trimmed the country-list to only the relevant countries (on production: always just 1 country)
When the user presses 'Execute'
Then a status 201 is returned and an object with 'email' and 'token' properties

Scenario: Successfully create new 'guest' user
Given the user is using the `api/user` endpoint
Given everything is filled in as in previous scenario, except role = 'guest'
When the user presses 'Execute'
Then a status 201 is returned and an object with 'email' and 'token' properties

--------------------------------
NOTE: Below scenario is not in the exact right location at the moment, but closely related to above scenarios.

Scenario: Successfully create new user in Mailchimp 1-by-1
Given the user is logged in to mailchimp 'IbfSystem' using credentials from Bitwarden
Given the user has navigated via 'Audience' and 'All contacts' and 'Add contacts' to 'Add subscriber'
Given the user has filled in 'email', 'first name' and 'last name'
Given the user has added the right country-tag (e.g. 'Zambia' for 'Zambia')
Given the user has checked the permission checkbox
When clicking 'subscribe'
Then the user appears in the audience with the right tag and the status 'Subscribed'

Scenario: Successfully create new user in Mailchimp through import
Given the user is logged in to mailchimp 'IbfSystem' using credentials from Bitwarden
When the user has navigated via 'Audience' and 'All contacts' and 'Add contacts' to 'Import contacts'
Then this can be used to achieve the same result as above in bulk


64 changes: 32 additions & 32 deletions features/IBF-portal-user/dashboard-page/Use_header_section.feature
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
@ibf-portal-user
Feature: View and use header section

Background:
Given a logged-in user on the dashboard page
Given logged in for a specific "country"

Scenario: View header of dashboard page
When the user enters the dashboard page
Then the user sees the Header section at the top of the page
And it shows 'IBF PORTAL' followed by the "country" name, followed by the selected "disaster-type" name
And it contains a Logout button
And it shows "Logged in as" with the user's username
And the username is underlined and clickable
And it contains the logos of the "country"

Scenario: View header in Triggered mode
When the user is viewing the Header section
Then 'Log-out' button displays in purple color

Scenario: View header in Non-triggered mode
When the user is viewing the Header section
Then 'Log-out' button displays in navy-blue color

Scenario: Logout
When the user clicks the "Log Out" button in the header
Then the user get logged out from IBF-portal
And returns to the "login" page

Scenario: Open the "Change Pasword" form
When the user clicks on the username
Then a popup opens with "Change Password" as title
And the user sees two fields: "New Password" and "Confirm Password"
And the "Change Password" button is disabled
And further scenarios on how to use the popup are in 'Change_password.feature'
Background:
Given a logged-in user on the dashboard page
Given logged in for a specific "country"

Scenario: View header of dashboard page
When the user enters the dashboard page
Then the user sees the Header section at the top of the page
And it shows 'IBF PORTAL' followed by the "country" name, followed by the selected "disaster-type" name
And it contains a Logout button
And it shows "Logged in as" with the user's email address
And the email address is underlined and clickable
And it contains the logos of the "country"

Scenario: View header in Triggered mode
When the user is viewing the Header section
Then 'Log-out' button displays in purple color

Scenario: View header in Non-triggered mode
When the user is viewing the Header section
Then 'Log-out' button displays in navy-blue color

Scenario: Logout
When the user clicks the "Log Out" button in the header
Then the user get logged out from IBF-portal
And returns to the "login" page

Scenario: Open the "Change Password" form
When the user clicks on the email address
Then a popup opens with "Change Password" as title
And the user sees two fields: "New Password" and "Confirm Password"
And the "Change Password" button is disabled
And further scenarios on how to use the popup are in 'Change_password.feature'



Expand Down
12 changes: 5 additions & 7 deletions interfaces/IBF-dashboard/src/app/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,10 @@ export class AuthService implements OnDestroy {
const user: User = {
token: rawToken,
email: decodedToken.email,
username: decodedToken.username,
firstName: decodedToken.firstName,
middleName: decodedToken.middleName,
lastName: decodedToken.lastName,
userRole: decodedToken.userRole,
userStatus: decodedToken.userStatus,
countries: decodedToken.countries,
disasterTypes: decodedToken.disasterTypes,
};
Expand All @@ -93,13 +91,13 @@ export class AuthService implements OnDestroy {
return user;
}

public login(email, password) {
public login(email: string, password: string) {
return this.apiService
.login(email, password)
.subscribe(this.onLoginResponse, this.onLoginError);
}

private onLoginResponse = (response) => {
private onLoginResponse = (response: { user: User }) => {
if (!response.user?.token) {
return;
}
Expand Down Expand Up @@ -129,7 +127,7 @@ export class AuthService implements OnDestroy {
message: `Authentication Failed: ${message}`,
duration: 5000,
});
toast.present();
void toast.present();
console.error('AuthService error: ', error);
};

Expand Down Expand Up @@ -161,7 +159,7 @@ export class AuthService implements OnDestroy {
message: `Password changed successfully`,
duration: 5000,
});
toast.present();
void toast.present();
};

private onChangePasswordError = async (error) => {
Expand All @@ -171,7 +169,7 @@ export class AuthService implements OnDestroy {
message: `Authentication Failed: ${message}`,
duration: 5000,
});
toast.present();
void toast.present();
console.error('AuthService error: ', error);
};
}

This file was deleted.

3 changes: 0 additions & 3 deletions interfaces/IBF-dashboard/src/app/models/user/user.model.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { UserRole } from 'src/app/models/user/user-role.enum';
import { UserStatus } from 'src/app/models/user/user-status.enum';

export class User {
token: string;
email: string;
username: string;
firstName: string;
middleName?: string;
lastName: string;
userRole: UserRole;
countries: string[];
disasterTypes: string[];
userStatus: UserStatus;
}
2 changes: 1 addition & 1 deletion interfaces/IBF-dashboard/src/app/services/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export class ApiService {
// API-endpoints:
/////////////////////////////////////////////////////////////////////////////

login(email: string, password: string): Observable<User> {
login(email: string, password: string): Observable<{ user: User }> {
this.log('ApiService : login()');

return this.post(
Expand Down
4 changes: 2 additions & 2 deletions interfaces/IBF-dashboard/src/app/services/jwt.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { JwtHelperService } from '@auth0/angular-jwt';
import { User } from 'src/app/models/user/user.model';

@Injectable({
providedIn: 'root',
Expand All @@ -20,8 +21,7 @@ export class JwtService {
window.localStorage.removeItem(this.tokenKey);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public decodeToken(rawToken: string): any {
public decodeToken(rawToken: string): User {
return this.jwtHelper.decodeToken(rawToken);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class RemoveUserProperties1738064090018 implements MigrationInterface {
name = 'RemoveUserProperties1738064090018';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "IBF-app"."user" DROP CONSTRAINT "UQ_09cdc2f534910e14de7705815a8"`,
);
await queryRunner.query(
`ALTER TABLE "IBF-app"."user" DROP COLUMN "username"`,
);
await queryRunner.query(
`ALTER TABLE "IBF-app"."user" DROP COLUMN "userStatus"`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "IBF-app"."user" ADD "userStatus" character varying NOT NULL DEFAULT 'active'`,
);
await queryRunner.query(
`ALTER TABLE "IBF-app"."user" ADD "username" character varying NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "IBF-app"."user" ADD CONSTRAINT "UQ_09cdc2f534910e14de7705815a8" UNIQUE ("username")`,
);
}
}
19 changes: 3 additions & 16 deletions services/API-service/src/api/user/dto/create-user.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
ArrayNotEmpty,
IsArray,
IsEmail,
IsEnum,
IsIn,
IsNotEmpty,
IsOptional,
Expand All @@ -15,21 +14,17 @@ import {
import countries from '../../../scripts/json/countries.json';
import disasterTypes from '../../../scripts/json/disasters.json';
import { UserRole } from '../user-role.enum';
import { UserStatus } from '../user-status.enum';

const userRoleArray = Object.values(UserRole).map((item) => String(item));
export const userRoleArray = Object.values(UserRole).map((item) =>
String(item),
);

export class CreateUserDto {
@ApiProperty({ example: 'dunant@redcross.nl' })
@IsEmail()
@IsNotEmpty()
public email: string;

@ApiProperty({ example: 'dunant' })
@IsString()
@IsNotEmpty()
public username: string;

@ApiProperty({ example: 'Henry' })
@IsString()
@IsNotEmpty()
Expand Down Expand Up @@ -69,14 +64,6 @@ export class CreateUserDto {
@ArrayNotEmpty()
public disasterTypes: string[];

@ApiProperty({
example: UserStatus.Active,
default: UserStatus.Inactive,
})
@IsEnum(UserStatus)
@IsNotEmpty()
public status: UserStatus;

@ApiProperty({ example: 'password' })
@IsNotEmpty()
@MinLength(4)
Expand Down
36 changes: 36 additions & 0 deletions services/API-service/src/api/user/dto/update-user.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ApiProperty } from '@nestjs/swagger';

import { IsIn, IsOptional, IsString } from 'class-validator';

import { UserRole } from '../user-role.enum';
import { userRoleArray } from './create-user.dto';

export class UpdateUserDto {
@ApiProperty({ example: 'Henry' })
@IsOptional()
@IsString()
public firstName?: string;

@ApiProperty({ example: 'Middle name' })
@IsOptional()
@IsString()
public middleName?: string;

@ApiProperty({ example: 'Dunant' })
@IsString()
@IsOptional()
public lastName?: string;

@ApiProperty({
enum: userRoleArray,
example: userRoleArray.join(' | '),
})
@IsIn(userRoleArray)
@IsOptional()
public role?: UserRole;

@ApiProperty({ example: '+31600000000' })
@IsString()
@IsOptional()
public whatsappNumber?: string;
}
4 changes: 0 additions & 4 deletions services/API-service/src/api/user/user-status.enum.ts

This file was deleted.

Loading
Loading