Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
P-Jeremy committed Dec 9, 2024
1 parent 634fad3 commit bc12292
Show file tree
Hide file tree
Showing 15 changed files with 362 additions and 0 deletions.
15 changes: 15 additions & 0 deletions api/db/database-builder/factory/build-legal-document-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { databaseBuffer } from '../database-buffer.js';

const buildLegalDocumentVersion = function ({
id = databaseBuffer.getNextId(),
type,
service,
versionAt = new Date(),
} = {}) {
return databaseBuffer.pushInsertable({
tableName: 'legal-document-versions',
values: { id, type, service, versionAt },
});
};

export { buildLegalDocumentVersion };
16 changes: 16 additions & 0 deletions api/src/legal-documents/application/api/legal-documents-api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { usecases } from '../../domain/usecases/index.js';

/**
* Accept legal document by user id.
*
* @param{string} params.service
* @param{string} params.type
* @param{string} params.userId
*
* @returns {Promise<void>}
*/
const acceptLegalDocumentByUserId = async ({ type, service, userId }) => {
return usecases.acceptLegalDocumentByUserId({ type, service, userId });
};

export { acceptLegalDocumentByUserId };
18 changes: 18 additions & 0 deletions api/src/legal-documents/domain/models/LegalDocument.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export class LegalDocument {
static TYPES = {
TOS: 'TOS',
};

static SERVICES = {
PIX_APP: 'pix-app',
PIX_ORGA: 'pix-orga',
PIX_CERTIF: 'pix-certif',
};

constructor({ id, type, service, versionAt }) {
this.id = id;
this.type = type;
this.service = service;
this.versionAt = versionAt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { LegalDocument } from '../models/LegalDocument.js';

const { TOS } = LegalDocument.TYPES;
const { PIX_ORGA } = LegalDocument.SERVICES;

const acceptLegalDocumentByUserId = async ({
type,
service,
userId,
userRepository,
legalDocumentRepository,
userAcceptanceRepository,
logger,
}) => {
// legacy document acceptance
if (type === TOS && service === PIX_ORGA) {
await userRepository.setPixOrgaCguByUserId(userId);
}

// new document acceptance
const document = await legalDocumentRepository.getLastVersionByTypeAndService({ type, service });
if (!document) {
logger.warn(`No legal document found for type: ${type} and service: ${service}`);
} else {
await userAcceptanceRepository.create({ userId, legalDocumentVersionId: document.id });
}
};

export { acceptLegalDocumentByUserId };
28 changes: 28 additions & 0 deletions api/src/legal-documents/domain/usecases/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { config } from '../../../shared/config.js';
import { injectDependencies } from '../../../shared/infrastructure/utils/dependency-injection.js';
import { importNamedExportsFromDirectory } from '../../../shared/infrastructure/utils/import-named-exports-from-directory.js';
import { logger } from '../../../shared/infrastructure/utils/logger.js';
import * as legalDocumentRepository from '../../infrastructure/repositories/legal-document.repository.js';
import * as userRepository from '../../infrastructure/repositories/user.repository.js';
import * as userAcceptanceRepository from '../../infrastructure/repositories/user-acceptance.repository.js';

const path = dirname(fileURLToPath(import.meta.url));

const repositories = {
legalDocumentRepository,
userAcceptanceRepository,
userRepository,
};

const dependencies = Object.assign({ config, logger }, repositories);

const usecasesWithoutInjectedDependencies = {
...(await importNamedExportsFromDirectory({ path: join(path, './'), ignoredFileNames: ['index.js'] })),
};

const usecases = injectDependencies(usecasesWithoutInjectedDependencies, dependencies);

export { usecases };
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { DomainTransaction } from '../../../shared/domain/DomainTransaction.js';
import { LegalDocument } from '../../domain/models/LegalDocument.js';

const getLastVersionByTypeAndService = async ({ type, service }) => {
const knexConnection = DomainTransaction.getConnection();
const document = await knexConnection('legal-document-versions')
.where({ type, service })
.orderBy('versionAt', 'desc')
.first();

if (!document) {
return null;
}

return new LegalDocument(document);
};

export { getLastVersionByTypeAndService };
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DomainTransaction } from '../../../shared/domain/DomainTransaction.js';

const create = async ({ userId, legalDocumentVersionId }) => {
const knexConnection = DomainTransaction.getConnection();
await knexConnection('legal-document-version-user-acceptances').insert({ userId, legalDocumentVersionId });
};

export { create };
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DomainTransaction } from '../../../shared/domain/DomainTransaction.js';

const setPixOrgaCguByUserId = async (userId) => {
const knexConnection = DomainTransaction.getConnection();
await knexConnection('users').where('id', userId).update({
pixOrgaTermsOfServiceAccepted: true,
lastPixOrgaTermsOfServiceValidatedAt: new Date(),
});
};

export { setPixOrgaCguByUserId };
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as legalDocumentsApi from '../../../../../src/legal-documents/application/api/legal-documents-api.js';
import { LegalDocument } from '../../../../../src/legal-documents/domain/models/LegalDocument.js';
import { databaseBuilder, expect, knex } from '../../../../test-helper.js';

const { TOS } = LegalDocument.TYPES;
const { PIX_ORGA } = LegalDocument.SERVICES;

describe('Integration | Privacy | Application | Api | legal documents', function () {
describe('#acceptLegalDocumentByUserId', function () {
it('accepts the latest legal document version by user id ', async function () {
// given
const userId = databaseBuilder.factory.buildUser().id;
databaseBuilder.factory.buildLegalDocumentVersion({
type: TOS,
service: PIX_ORGA,
versionAt: new Date('2021-01-01'),
});

const latestDocument = databaseBuilder.factory.buildLegalDocumentVersion({
type: TOS,
service: PIX_ORGA,
versionAt: new Date(),
});

await databaseBuilder.commit();

const formerAcceptances = await knex('legal-document-version-user-acceptances').where({ userId });

expect(formerAcceptances.length).to.equal(0);

// when
await legalDocumentsApi.acceptLegalDocumentByUserId({ userId, type: TOS, service: PIX_ORGA });

// then
const userAcceptance = await knex('legal-document-version-user-acceptances')
.where({ userId })
.where('legalDocumentVersionId', latestDocument.id)
.first();

expect(userAcceptance).to.exist;
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { LegalDocument } from '../../../../../src/legal-documents/domain/models/LegalDocument.js';
import { usecases } from '../../../../../src/legal-documents/domain/usecases/index.js';
import { databaseBuilder, expect, knex, sinon } from '../../../../test-helper.js';

const { TOS } = LegalDocument.TYPES;
const { PIX_ORGA } = LegalDocument.SERVICES;

describe('Integration | Legal documents | Domain | Use case | accept-legal-document-by-user-id', function () {
it('accepts a legal document for a user', async function () {
// given
const user = databaseBuilder.factory.buildUser();
const document = databaseBuilder.factory.buildLegalDocumentVersion({ type: TOS, service: PIX_ORGA });
await databaseBuilder.commit();

// when
await usecases.acceptLegalDocumentByUserId({ userId: user.id, type: TOS, service: PIX_ORGA });

// then
const userAcceptance = await knex('legal-document-version-user-acceptances')
.where('userId', user.id)
.where('legalDocumentVersionId', document.id)
.first();
expect(userAcceptance).to.exist;
});

context('when the legal document is the Terms of Service for Pix Orga', function () {
it('accepts the Pix Orga CGUs in the legacy and legal document model', async function () {
// given
const user = databaseBuilder.factory.buildUser({ pixOrgaTermsOfServiceAccepted: false });
databaseBuilder.factory.buildLegalDocumentVersion({ type: TOS, service: PIX_ORGA });

await databaseBuilder.commit();

// when
await usecases.acceptLegalDocumentByUserId({ userId: user.id, type: TOS, service: PIX_ORGA });

// then
const updatedUser = await knex('users').where('id', user.id).first();
expect(updatedUser.pixOrgaTermsOfServiceAccepted).to.equal(true);
});

it('logs an error, when no legal document is found', async function () {
// given
const user = databaseBuilder.factory.buildUser({ pixOrgaTermsOfServiceAccepted: false });
const loggerStub = { warn: sinon.stub() };
await databaseBuilder.commit();

// when
await usecases.acceptLegalDocumentByUserId({ userId: user.id, type: TOS, service: PIX_ORGA, logger: loggerStub });

// then
expect(loggerStub.warn).to.have.been.calledWith(
`No legal document found for type: ${TOS} and service: ${PIX_ORGA}`,
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { LegalDocument } from '../../../../../src/legal-documents/domain/models/LegalDocument.js';
import * as legalDocumentRepository from '../../../../../src/legal-documents/infrastructure/repositories/legal-document.repository.js';
import { databaseBuilder, domainBuilder, expect } from '../../../../test-helper.js';

const { TOS } = LegalDocument.TYPES;
const { PIX_ORGA, PIX_APP } = LegalDocument.SERVICES;

describe('Integration | Legal document | Infrastructure | Repository | legal-documents', function () {
describe('#getLastVersionByTypeAndService', function () {
it('returns the last legal document version by type and service', async function () {
// given
const type = TOS;
const service = PIX_ORGA;
databaseBuilder.factory.buildLegalDocumentVersion({
type,
service,
versionAt: new Date('2020-12-01'),
});
const expectedDocument = databaseBuilder.factory.buildLegalDocumentVersion({
type,
service,
versionAt: new Date('2024-12-01'),
});

databaseBuilder.factory.buildLegalDocumentVersion({
type,
service: PIX_APP,
versionAt: new Date('2024-12-01'),
});
await databaseBuilder.commit();

// when
const lastDocument = await legalDocumentRepository.getLastVersionByTypeAndService({ type, service });

// then
expect(lastDocument).to.deepEqualInstance(domainBuilder.buildLegalDocument(expectedDocument));
});

it('returns null when no document found', async function () {
// when
const lastDocument = await legalDocumentRepository.getLastVersionByTypeAndService({
type: 'toto',
service: 'tutu',
});

// then
expect(lastDocument).to.be.null;
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { LegalDocument } from '../../../../../src/legal-documents/domain/models/LegalDocument.js';
import * as userAcceptanceRepository from '../../../../../src/legal-documents/infrastructure/repositories/user-acceptance.repository.js';
import { databaseBuilder, expect, knex } from '../../../../test-helper.js';

const { TOS } = LegalDocument.TYPES;
const { PIX_ORGA } = LegalDocument.SERVICES;

describe('Integration | Legal document | Infrastructure | Repository | user-acceptance', function () {
describe('#create', function () {
it('creates an acceptance record for a user and legal document', async function () {
// given
const user = databaseBuilder.factory.buildUser();
const document = databaseBuilder.factory.buildLegalDocumentVersion({ type: TOS, service: PIX_ORGA });
await databaseBuilder.commit();

// when
await userAcceptanceRepository.create({ userId: user.id, legalDocumentVersionId: document.id });

// then
const userAcceptance = await knex('legal-document-version-user-acceptances')
.where('userId', user.id)
.where('legalDocumentVersionId', document.id)
.first();
expect(userAcceptance.acceptedAt).to.be.a('date');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as userRepository from '../../../../../src/legal-documents/infrastructure/repositories/user.repository.js';
import { databaseBuilder, expect, knex } from '../../../../test-helper.js';

describe('Integration | Legal document | Infrastructure | Repository | user', function () {
describe('#setPixOrgaCguByUserId', function () {
it('sets the Pix Orga CGU for a user id', async function () {
// given
const user = databaseBuilder.factory.buildUser({
pixOrgaTermsOfServiceAccepted: false,
lastPixOrgaTermsOfServiceValidatedAt: null,
});
await databaseBuilder.commit();

// when
await userRepository.setPixOrgaCguByUserId(user.id);

// then
const updatedUser = await knex('users').where('id', user.id).first();
expect(updatedUser.pixOrgaTermsOfServiceAccepted).to.equal(true);
expect(updatedUser.lastPixOrgaTermsOfServiceValidatedAt).to.be.a('date');
});
});
});
17 changes: 17 additions & 0 deletions api/tests/tooling/domain-builder/factory/build-legal-document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { LegalDocument } from '../../../../src/legal-documents/domain/models/LegalDocument.js';

const buildLegalDocument = function ({
id = 123,
type = LegalDocument.TYPES.TOS,
service = LegalDocument.SERVICES.PIX_APP,
versionAt = new Date(),
} = {}) {
return new LegalDocument({
id,
type,
service,
versionAt,
});
};

export { buildLegalDocument };
2 changes: 2 additions & 0 deletions api/tests/tooling/domain-builder/factory/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import { buildJuryCertificationSummary } from './build-jury-certification-summar
import { buildJurySession } from './build-jury-session.js';
import { buildKnowledgeElement } from './build-knowledge-element.js';
import { buildLearningContent } from './build-learning-content.js';
import { buildLegalDocument } from './build-legal-document.js';
import { buildMembership } from './build-membership.js';
import { buildMission } from './build-mission.js';
import { buildOrganization } from './build-organization.js';
Expand Down Expand Up @@ -365,6 +366,7 @@ export {
buildJurySession,
buildKnowledgeElement,
buildLearningContent,
buildLegalDocument,
buildMembership,
buildMission,
buildOrganization,
Expand Down

0 comments on commit bc12292

Please sign in to comment.