Skip to content

Commit

Permalink
feat: route to export all users in json or csv
Browse files Browse the repository at this point in the history
  • Loading branch information
celinepelletier committed Jul 17, 2024
1 parent e8a86b3 commit 4c4b599
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 5 deletions.
41 changes: 37 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.312.0",
"@fast-csv/format": "^5.0.0",
"@fast-csv/parse": "^5.0.0",
"@types/pg-format": "^1.0.2",
"@types/validator": "^13.7.1",
Expand Down
2 changes: 2 additions & 0 deletions src/db/dal/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,5 @@ export const retrieveUserCreatedSince = async (date: string): Promise<number> =>
});
return result;
};

export const exportAllUsers = async (): Promise<UserModel[]> => await UserModel.findAll();
14 changes: 14 additions & 0 deletions src/db/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,26 @@ export interface IUserOutput extends IUserAttributes {}
class UserModel extends Model<IUserAttributes, IUserInput> implements IUserAttributes {
public id: number;
public keycloak_id: string;
public first_name?: string;
public last_name?: string;
public era_commons_id?: string;
public email?: string;
public external_individual_fullname?: string;
public profile_image_key?: string;
public affiliation?: string;
public research_domains?: string[];
public research_area_description?: string;
public locale?: string;
public newsletter_email?: string;
public newsletter_subscription_status?: SubscriptionStatus;
public newsletter_dataset_subscription_status?: SubscriptionStatus;
public commercial_use_reason: string;
public accepted_terms: boolean;
public understand_disclaimer: boolean;
public completed_registration: boolean;
public creation_date: Date;
public updated_date: Date;
public consent_date?: Date;
public deleted: boolean;
public roles: string[];
public portal_usages: string[];
Expand Down
21 changes: 20 additions & 1 deletion src/routes/statistics.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Router } from 'express';
import { StatusCodes } from 'http-status-codes';

import { retrieveUserCreatedSince } from '../db/dal/user';
import { exportAllUsers, retrieveUserCreatedSince } from '../db/dal/user';
import { writeUserListInCsv } from '../utils/csvWriter';

// Handles requests made to /statistics
const statisticsRouter = Router();
Expand All @@ -18,4 +19,22 @@ statisticsRouter.get('/createdSince/:year/:month/:day', async (req, res, next) =
}
});

statisticsRouter.get('/exportAll/:format', async (req, res, next) => {
try {
if (req.params.format === 'json') {
const users = await exportAllUsers();
return res.status(StatusCodes.OK).send(users);
}

if (req.params.format === 'csv') {
const users = await exportAllUsers();
return writeUserListInCsv(users, res);
}

return res.status(StatusCodes.BAD_REQUEST).send('Unsupported format');
} catch (e) {
next(e);
}
});

export default statisticsRouter;
50 changes: 50 additions & 0 deletions src/utils/csvWriter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { format } from '@fast-csv/format';

import UserModel from '../db/models/User';

export const writeUserListInCsv = (users: UserModel[], res) => {
const csvStream = format({ headers: true });

res.setHeader('Content-disposition', 'attachment; filename="members.csv"');
res.setHeader('Content-Type', 'text/csv');

csvStream.pipe(res);
users.forEach((u) => {
csvStream.write({
id: u.id,
keycloak_id: u.keycloak_id,
first_name: u.first_name,
last_name: u.last_name,
era_commons_id: u.era_commons_id,
email: u.email,
linkedin: u.linkedin,
public_email: u.public_email,
external_individual_fullname: u.external_individual_fullname,
external_individual_email: u.external_individual_email,
profile_image_key: u.profile_image_key,
roles: u.roles,
affiliation: u.affiliation,
portal_usages: u.portal_usages,
research_domains: u.research_domains,
research_area_description: u.research_area_description,
creation_date: u.creation_date,
updated_date: u.updated_date,
consent_date: u.consent_date,
accepted_terms: u.accepted_terms,
understand_disclaimer: u.understand_disclaimer,
commercial_use_reason: u.commercial_use_reason,
completed_registration: u.completed_registration,
deleted: u.deleted,
locale: u.locale,
newsletter_email: u.newsletter_email,
newsletter_subscription_status: u.newsletter_subscription_status,
newsletter_dataset_subscription_status: u.newsletter_dataset_subscription_status,
location_country: u.location_country,
location_state: u.location_state,
website: u.website,
areas_of_interest: u.areas_of_interest,
is_public: u.is_public,
});
});
csvStream.end();
};

0 comments on commit 4c4b599

Please sign in to comment.