Skip to content

Commit

Permalink
feat: SKFP-354 review fixs
Browse files Browse the repository at this point in the history
  • Loading branch information
celinepelletier committed Jul 8, 2024
1 parent 4ba171b commit 078588f
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 43 deletions.
8 changes: 4 additions & 4 deletions src/db/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ UserModel.init(
type: DataTypes.STRING,
allowNull: true,
validate: {
validate: (value: string) => value === '' || NAME_REGEX.test(value),
validate: (value: string) => value === '' || NAME_REGEX.test(value.trim()),
},
},
email: {
Expand Down Expand Up @@ -153,7 +153,7 @@ UserModel.init(
type: DataTypes.CITEXT,
allowNull: true,
validate: {
validate: (value: string) => value === '' || NAME_REGEX.test(value),
validate: (value: string) => value === '' || NAME_REGEX.test(value.trim()),
},
},
public_email: {
Expand Down Expand Up @@ -253,14 +253,14 @@ UserModel.init(
type: DataTypes.CITEXT,
allowNull: true,
validate: {
validate: (value: string) => value === '' || NAME_REGEX.test(value),
validate: (value: string) => value === '' || NAME_REGEX.test(value.trim()),
},
},
location_state: {
type: DataTypes.CITEXT,
allowNull: true,
validate: {
validate: (value: string) => value === '' || NAME_REGEX.test(value),
validate: (value: string) => value === '' || NAME_REGEX.test(value.trim()),
},
},
website: {
Expand Down
197 changes: 197 additions & 0 deletions src/external/persona.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { convertToPersona, Persona, validateUniqPersonas } from './persona';

describe('validateUniqPersonas', () => {
const p: Persona = { egoId: '1' } as Persona;
it('should return true if no duplicate', () => {
const personas = [p, { ...p, egoId: '2' }, { ...p, egoId: '3' }];

expect(validateUniqPersonas(personas)).toBeTruthy();
});

it('should return false if at least 1 duplicate', () => {
const personas = [p, { ...p, egoId: '2' }, { ...p, egoId: '2' }];

expect(validateUniqPersonas(personas)).toBeFalsy();
});
});

describe('convertToPersona', () => {
const emptyInput = {
id: '',
isPublic: '',
isActive: '',
title: '',
firstName: '',
lastName: '',
role: '',
loginEmail: '',
institution: '',
department: '',
jobTitle: '',
addressLine1: '',
addressLine2: '',
city: '',
state: '',
country: '',
phone: '',
institutionalEmail: '',
eraCommonsID: '',
website: '',
twitter: '',
orchid: '',
linkedin: '',
googleScholarId: '',
github: '',
facebook: '',
acceptedTerms: '',
acceptedNihOptIn: '',
acceptedKfOptIn: '',
acceptedDatasetSub: '',
interests: '',
egoId: '',
story: '',
bio: '',
};

it('should transform boolean', () => {
const input = {
...emptyInput,
isPublic: 'true',
isActive: 'true',
acceptedTerms: 'false',
acceptedNihOptIn: '0',
acceptedKfOptIn: '1',
acceptedDatasetSub: '',
};

const persona = convertToPersona(input);

expect(persona.isPublic).toBeTruthy();
expect(persona.isActive).toBeTruthy();
expect(persona.acceptedTerms).toBeFalsy();
expect(persona.acceptedNihOptIn).toBeFalsy();
expect(persona.acceptedKfOptIn).toBeFalsy();
expect(persona.acceptedDatasetSub).toBeFalsy();
});

it('should replace empty string by null', () => {
const persona = convertToPersona(emptyInput);

expect(persona.firstName).toBeNull();
expect(persona.lastName).toBeNull();
expect(persona.loginEmail).toBeNull();
expect(persona.institution).toBeNull();
expect(persona.state).toBeNull();
expect(persona.country).toBeNull();
expect(persona.institutionalEmail).toBeNull();
expect(persona.eraCommonsID).toBeNull();
expect(persona.website).toBeNull();
expect(persona.linkedin).toBeNull();
expect(persona.egoId).toBeNull();
});

it('should split arrays of string', () => {
const input = {
...emptyInput,
role: 'a,b',
interests: 'c,d',
};

const personaEmpty = convertToPersona(emptyInput);
const persona = convertToPersona(input);

expect(personaEmpty.role).toEqual([]);
expect(personaEmpty.interests).toEqual([]);
expect(persona.role).toEqual(['a', 'b']);
expect(persona.interests).toEqual(['c', 'd']);
});

it('should trim', () => {
const input = {
...emptyInput,
firstName: ' firstName ',
lastName: ' lastName ',
loginEmail: ' [email protected] ',
institution: ' institution ',
state: ' state ',
country: ' country ',
institutionalEmail: ' [email protected] ',
eraCommonsID: ' eraCommonsID ',
website: ' http://www.website.org ',
linkedin: ' http://www.linkedin.com/in/test ',
egoId: ' egoId ',
};

const persona = convertToPersona(input);

expect(persona.firstName).toBe('firstName');
expect(persona.lastName).toBe('lastName');
expect(persona.loginEmail).toBe('[email protected]');
expect(persona.institution).toBe('institution');
expect(persona.state).toBe('state');
expect(persona.country).toBe('country');
expect(persona.institutionalEmail).toBe('[email protected]');
expect(persona.eraCommonsID).toBe('eraCommonsID');
expect(persona.website).toBe('http://www.website.org');
expect(persona.linkedin).toBe('http://www.linkedin.com/in/test');
expect(persona.egoId).toBe('egoId');
});

it('should validate URL', () => {
const inputValid = {
...emptyInput,
website: 'http://www.website.org',
};

const inputInvalid = {
...emptyInput,
website: 'invalid_url',
};

const personaValidUrl = convertToPersona(inputValid);
const personaInvalidUrl = convertToPersona(inputInvalid);

expect(personaValidUrl.website).toBe('http://www.website.org');
expect(personaInvalidUrl.website).toBeNull();
});

it('should validate emails', () => {
const inputValid = {
...emptyInput,
loginEmail: '[email protected]',
institutionalEmail: '[email protected]',
};

const inputInvalid = {
...emptyInput,
loginEmail: 'invalid_login_email',
institutionalEmail: 'invalid_institutional_email',
};

const personaValidEmails = convertToPersona(inputValid);
const personaInvalidEmails = convertToPersona(inputInvalid);

expect(personaValidEmails.loginEmail).toBe('[email protected]');
expect(personaValidEmails.institutionalEmail).toBe('[email protected]');
expect(personaInvalidEmails.loginEmail).toBeNull();
expect(personaInvalidEmails.institutionalEmail).toBeNull();
});

it('should validate linkedin link', () => {
const inputValid = {
...emptyInput,
linkedin: 'http://www.linkedin.com/in/test',
};

const inputInvalid = {
...emptyInput,
linkedin: 'invalid_linkedin',
};

const personaValidLinkedin = convertToPersona(inputValid);
const personaInvalidLinkedin = convertToPersona(inputInvalid);

expect(personaValidLinkedin.linkedin).toBe('http://www.linkedin.com/in/test');
expect(personaInvalidLinkedin.linkedin).toBeNull();
});
});
59 changes: 23 additions & 36 deletions src/external/persona.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable complexity */
/* eslint-disable no-console */
import { parseString } from '@fast-csv/parse';
import validator from 'validator';
Expand Down Expand Up @@ -46,21 +45,9 @@ export type Persona = {
};

export const validateUniqPersonas = (personas: Persona[]): boolean => {
const result = new Map();
personas.reduce((map, obj) => {
if (map.has(obj.egoId)) {
map.set(obj.egoId, map.get(obj.egoId).push(obj));
} else {
map.set(obj.egoId, [obj]);
}
return map;
}, result);
const values = Array.from(result.values()).filter((l) => l.length !== 1);
if (values.length > 0) {
console.warn('OOPS duplicate persona');
return false;
}
return true;
const ids = personas.map((p) => p.egoId);
const uniqIds = new Set(ids);
return ids.length === uniqIds.size;
};

export const readCsv = (csvContent: string): Promise<Persona[]> =>
Expand Down Expand Up @@ -106,12 +93,11 @@ export const convertToPersona = (p: any): Persona => ({
firstName: p.firstName === '' ? null : (p.firstName as string).trim(),
lastName: p.lastName === '' ? null : (p.lastName as string).trim(),
role: p.role === '' ? [] : p.role.split(','),
loginEmail:
p.loginEmail === ''
? null
: validator.isURL((p.loginEmail as string).trim())
? (p.loginEmail as string).trim()
: null,
loginEmail: ((email) => {
if (email === '') return null;
const trimEmail = email.trim();
return validator.isEmail(trimEmail) ? trimEmail : null;
})(p.loginEmail),
institution: p.institution === '' ? null : (p.institution as string).trim(),
department: p.department,
jobTitle: p.jobTitle,
Expand All @@ -121,23 +107,24 @@ export const convertToPersona = (p: any): Persona => ({
state: p.state === '' ? null : (p.state as string).trim(),
country: p.country === '' ? null : (p.country as string).trim(),
phone: p.phone,
institutionalEmail:
p.institutionalEmail === ''
? null
: validator.isURL((p.institutionalEmail as string).trim())
? (p.institutionalEmail as string).trim()
: null,
institutionalEmail: ((email) => {
if (email === '') return null;
const trimEmail = email.trim();
return validator.isEmail(trimEmail) ? trimEmail : null;
})(p.institutionalEmail),
eraCommonsID: p.eraCommonsID === '' ? null : (p.eraCommonsID as string).trim(),
website:
p.website === '' ? null : validator.isURL((p.website as string).trim()) ? (p.website as string).trim() : null,
website: ((website) => {
if (website === '') return null;
const trimWebsite = website.trim();
return validator.isURL(trimWebsite) ? trimWebsite : null;
})(p.website),
twitter: p.twitter,
orchid: p.orchid,
linkedin:
p.linkedin === ''
? null
: LINKEDIN_REGEX.test((p.linkedin as string).trim())
? (p.linkedin as string).trim()
: null,
linkedin: ((linkedin) => {
if (linkedin === '') return null;
const trimLinkedin = linkedin.trim();
return LINKEDIN_REGEX.test(trimLinkedin) ? trimLinkedin : null;
})(p.linkedin),
googleScholarId: p.googleScholarId,
github: p.github,
facebook: p.facebook,
Expand Down
5 changes: 2 additions & 3 deletions src/routes/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ adminRouter.post('/doMigrationFromPersona', async (req, res, next) => {
const personas = await readCsv(csvContent);
if (validateUniqPersonas(personas)) {
const result = await Promise.all(personas.map((p) => createOrUpdate(p)));
res.status(StatusCodes.OK).send({
return res.status(StatusCodes.OK).send({
created: result.filter((s) => s === 'created').length,
updated: result.filter((s) => s === 'updated').length,
ignored: result.filter((s) => s === 'ignored').length,
});
} else {
res.status(StatusCodes.BAD_REQUEST).send('Duplicate persona, migration aborted');
}
return res.status(StatusCodes.BAD_REQUEST).send('Duplicate persona, migration aborted');
}
} catch (e) {
next(e);
Expand Down

0 comments on commit 078588f

Please sign in to comment.