Skip to content

Commit

Permalink
Enedis: Better catch error when user consent is no longer found (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Gilles committed Mar 29, 2024
1 parent 16f285a commit 74945ed
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 12 deletions.
41 changes: 29 additions & 12 deletions core/enedis/enedis.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ const {

const ENEDIS_GRANT_ACCESS_TOKEN_REDIS_PREFIX = 'enedis-grant-access-token:';

const getDevicesWithEnedisActivated = `
SELECT DISTINCT t_user.id, t_user.account_id,
t_device.id as device_id, t_device.provider_refresh_token
FROM t_user
INNER JOIN t_device ON t_user.id = t_device.user_id
WHERE t_user.account_id = $1
AND t_device.revoked = false
AND t_device.is_deleted = false
AND t_device.client_id = $2;
`;

module.exports = function EnedisModel(logger, db, redisClient) {
const { ENEDIS_GRANT_CLIENT_ID, ENEDIS_GRANT_CLIENT_SECRET, ENEDIS_BACKEND_URL, ENEDIS_GLADYS_PLUS_REDIRECT_URI } =
process.env;
Expand Down Expand Up @@ -69,16 +80,7 @@ module.exports = function EnedisModel(logger, db, redisClient) {
if (accessTokenInRedis) {
return accessTokenInRedis;
}
const getDevicesWithEnedisActivated = `
SELECT DISTINCT t_user.id, t_user.account_id,
t_device.id as device_id, t_device.provider_refresh_token
FROM t_user
INNER JOIN t_device ON t_user.id = t_device.user_id
WHERE t_user.account_id = $1
AND t_device.revoked = false
AND t_device.is_deleted = false
AND t_device.client_id = $2;
`;

const devices = await db.query(getDevicesWithEnedisActivated, [accountId, ENEDIS_GRANT_CLIENT_ID]);
if (devices.length === 0) {
logger.warn(`Forbidden: Enedis Oauth process was not done`);
Expand Down Expand Up @@ -226,14 +228,25 @@ module.exports = function EnedisModel(logger, db, redisClient) {
async function getContract(accountId, usagePointId) {
logger.info(`Enedis - get contract for usagePoint = ${usagePointId}`);
const accessToken = await getAccessToken(accountId);
const devices = await db.query(getDevicesWithEnedisActivated, [accountId, ENEDIS_GRANT_CLIENT_ID]);
if (devices.length === 0) {
logger.warn(`Forbidden: Enedis Oauth process was not done`);
throw new ForbiddenError();
}
const data = {
usage_point_id: usagePointId,
};
let response;
try {
response = await makeRequest('/customers_upc/v5/usage_points/contracts', data, accessToken);
} catch (e) {
logger.error(e);
// if status is 403, error is "No consent can be found for this customer and this usage point"
// Revoke device to avoid re-hitting this error
if (get(e, 'response.status') === 403) {
await db.t_device.update(devices[0].device_id, {
revoked: true,
});
}
throw e;
}
const lastActivationDate = get(response, 'customer.usage_points.0.contracts.last_activation_date');
Expand Down Expand Up @@ -328,7 +341,11 @@ module.exports = function EnedisModel(logger, db, redisClient) {
const oneWeekAgo = dayjs().subtract(6, 'day');
logger.info(`Enedis: Daily refresh of all users. Refreshing ${usersToRefresh.length} users`);
await Promise.each(usersToRefresh, async (userToRefresh) => {
await refreshAllData({ userId: userToRefresh.id, start: oneWeekAgo });
try {
await refreshAllData({ userId: userToRefresh.id, start: oneWeekAgo });
} catch (e) {
logger.error(`Failed to refresh user = ${userToRefresh.id}`);
}
});
}
async function enedisSyncData(job) {
Expand Down
42 changes: 42 additions & 0 deletions test/core/enedis/enedis.dailyRefreshAllUsers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,39 @@ describe('EnedisWorker.dailyRefreshAllUsers', function Describe() {
await shutdown();
});
it('should publish 2 jobs', async () => {
// Insert broken enedis user data
await TEST_DATABASE_INSTANCE.t_account.insert({
id: 'ab9c205a-d090-4c97-84b5-d2a9eb932201',
name: 'user_with_broken_enedis_sync@test.fr',
current_period_end: new Date('2050-11-19T16:00:00.000Z'),
status: 'active',
});
await TEST_DATABASE_INSTANCE.t_user.insert({
id: '1258b0b1-4f5a-4ea6-926b-755ab725eeb3',
email_confirmation_token_hash: 'dlkflmdskflmdskfmldskfkdsfldsfldksmfkdslfksdf',
email: 'user_with_broken_enedis_sync@test.fr',
email_confirmed: true,
srp_salt: 'ddd',
srp_verifier: 'sdfsdf',
two_factor_enabled: false,
role: 'admin',
account_id: 'ab9c205a-d090-4c97-84b5-d2a9eb932201',
language: 'fr',
name: 'Broken Enedis',
});
await TEST_DATABASE_INSTANCE.t_device.insert({
id: '002a93b7-e21b-48bb-a414-29bcc31615ba',
user_id: '1258b0b1-4f5a-4ea6-926b-755ab725eeb3',
client_id: process.env.ENEDIS_GRANT_CLIENT_ID,
name: 'Enedis',
refresh_token_hash: 'a43fc595dfbf78cf52e644cd30e4cb45ad1f4ef2472c6819cf4546afdece8888',
created_at: '2024-10-16T02:21:25.901Z',
last_seen: '2024-10-16T02:21:25.901Z',
});
await TEST_DATABASE_INSTANCE.t_enedis_usage_point.insert({
account_id: 'ab9c205a-d090-4c97-84b5-d2a9eb932201',
usage_point_id: 'broken-usage-point',
});
// First, finalize Enedis Oauth process
nock(`https://${process.env.ENEDIS_BACKEND_URL}`)
.post('/oauth2/v3/token', (body) => {
Expand All @@ -63,10 +96,18 @@ describe('EnedisWorker.dailyRefreshAllUsers', function Describe() {
usage_points_id: '16401220101758,16401220101710,16401220101720',
apigo_client_id: '73cd2d7f-e361-b7f6-48359493ed2c',
});

nock(`https://${process.env.ENEDIS_BACKEND_URL}`)
.get('/customers_upc/v5/usage_points/contracts')
.query(contractQueryParams)
.reply(200, contractData);
nock(`https://${process.env.ENEDIS_BACKEND_URL}`)
.get('/customers_upc/v5/usage_points/contracts')
.query({ usage_point_id: 'broken-usage-point' })
.reply(403, {
error: 'ERRE001150',
error_description: 'No consent can be found for this customer and this usage point.',
});
await request(TEST_BACKEND_APP)
.post('/enedis/finalize')
.send({
Expand All @@ -78,6 +119,7 @@ describe('EnedisWorker.dailyRefreshAllUsers', function Describe() {
.expect('Content-Type', /json/)
.expect(200);
mockAccessTokenRefresh();
mockAccessTokenRefresh();
await enedisModel.dailyRefreshOfAllUsers();
const counts = await enedisModel.queue.getJobCounts('wait', 'completed', 'failed');
expect(counts).to.deep.equal({ wait: 2, completed: 0, failed: 0 });
Expand Down

0 comments on commit 74945ed

Please sign in to comment.