@citrineos/data
Version:
The OCPP data module which includes all persistence layer implementation.
192 lines • 10.3 kB
JavaScript
import { CrudRepository, OCPP2_0_1 } from '@citrineos/base';
import { Sequelize } from 'sequelize-typescript';
import { Logger } from 'tslog';
import { AuthorizationMapper } from '../mapper/2.0.1/index.js';
import { Authorization, LocalListAuthorization, LocalListVersion, LocalListVersionAuthorization, SendLocalList, SendLocalListAuthorization, } from '../model/index.js';
import { SequelizeAuthorizationRepository } from './Authorization.js';
import { SequelizeRepository } from './Base.js';
export class SequelizeLocalAuthListRepository extends SequelizeRepository {
authorization;
localListAuthorization;
sendLocalList;
constructor(config, logger, sequelizeInstance, authorization, localListAuthorization, sendLocalList) {
super(config, Authorization.MODEL_NAME, logger, sequelizeInstance);
this.authorization = authorization
? authorization
: new SequelizeAuthorizationRepository(config, logger);
this.localListAuthorization = localListAuthorization
? localListAuthorization
: new SequelizeRepository(config, LocalListAuthorization.MODEL_NAME, logger, sequelizeInstance);
this.sendLocalList = sendLocalList
? sendLocalList
: new SequelizeRepository(config, SendLocalList.MODEL_NAME, logger, sequelizeInstance);
}
async createSendLocalListFromRequestData(tenantId, stationId, correlationId, updateType, versionNumber, localAuthorizationList) {
const sendLocalList = await this.sendLocalList.create(tenantId, SendLocalList.build({
tenantId,
stationId,
correlationId,
versionNumber,
updateType,
}));
for (const authData of localAuthorizationList ?? []) {
const auth = await Authorization.findOne({
where: {
idToken: authData.idToken.idToken,
idTokenType: AuthorizationMapper.fromIdTokenEnumType(authData.idToken.type),
},
});
if (!auth) {
throw new Error(`Authorization not found for ${JSON.stringify(authData)}, invalid SendLocalListRequest (create necessary Authorizations first)`);
}
// If groupAuthorizationId is present, compare its id to groupAuthorizationId
if (authData.idTokenInfo?.groupIdToken) {
const groupAuth = await Authorization.findOne({
where: {
idToken: authData.idTokenInfo.groupIdToken.idToken,
idTokenType: AuthorizationMapper.fromIdTokenEnumType(authData.idTokenInfo.groupIdToken.type),
},
});
const groupAuthorizationAuthId = groupAuth?.id;
if (!auth.groupAuthorizationId || groupAuthorizationAuthId !== auth.groupAuthorizationId) {
throw new Error(`Authorization groupIdToken in SendLocalListRequest ${JSON.stringify(authData.idTokenInfo.groupIdToken)} does not match groupAuthorizationId in database ${JSON.stringify(auth.groupAuthorizationId)} (update the groupAuthorization first)`);
}
if (!auth.groupAuthorizationId || groupAuthorizationAuthId !== auth.groupAuthorizationId) {
throw new Error(`Authorization groupIdToken in SendLocalListRequest ${JSON.stringify(authData.idTokenInfo.groupIdToken)} does not match groupAuthorizationId in database ${JSON.stringify(auth.groupAuthorizationId)} (update the groupAuthorization first)`);
}
}
// No longer create IdTokenInfo, just use Authorization fields
const { id, ...authorizationFields } = auth;
const localListAuthorization = await this.localListAuthorization.create(tenantId, LocalListAuthorization.build({
...authorizationFields,
authorizationId: id,
}));
await SendLocalListAuthorization.create({
tenantId,
sendLocalListId: sendLocalList.id,
authorizationId: localListAuthorization.id,
});
}
await sendLocalList.reload({ include: [LocalListAuthorization] });
this.sendLocalList.emit('created', [sendLocalList]);
return sendLocalList;
}
async validateOrReplaceLocalListVersionForStation(tenantId, versionNumber, stationId) {
await this.s.transaction(async (transaction) => {
const localListVersion = await LocalListVersion.findOne({
where: { stationId },
transaction,
});
if (localListVersion && localListVersion.versionNumber === versionNumber) {
return;
}
if (localListVersion && localListVersion.versionNumber !== versionNumber) {
// Remove associations
await LocalListVersionAuthorization.destroy({
where: { localListVersionId: localListVersion.id },
transaction,
});
}
if (!localListVersion) {
const newLocalListVersion = await LocalListVersion.create({ tenantId, stationId, versionNumber }, { transaction });
this.emit('created', [newLocalListVersion]);
}
else {
await localListVersion.update({ versionNumber }, { transaction });
this.emit('updated', [localListVersion]);
}
});
}
async getSendLocalListRequestByStationIdAndCorrelationId(tenantId, stationId, correlationId) {
return this.sendLocalList.readOnlyOneByQuery(tenantId, { where: { stationId, correlationId } });
}
async createOrUpdateLocalListVersionFromStationIdAndSendLocalList(tenantId, stationId, sendLocalList) {
switch (sendLocalList.updateType) {
case OCPP2_0_1.UpdateEnumType.Full:
return this.replaceLocalListVersionFromStationIdAndSendLocalList(tenantId, stationId, sendLocalList);
case OCPP2_0_1.UpdateEnumType.Differential:
return this.updateLocalListVersionFromStationIdAndSendLocalListRequest(tenantId, stationId, sendLocalList);
}
}
async replaceLocalListVersionFromStationIdAndSendLocalList(tenantId, stationId, sendLocalList) {
const localListVersion = await this.s.transaction(async (transaction) => {
const oldLocalListVersion = await LocalListVersion.findOne({
where: { stationId },
include: [LocalListAuthorization],
transaction,
});
if (oldLocalListVersion) {
// Remove associations
await LocalListVersionAuthorization.destroy({
where: { localListVersionId: oldLocalListVersion.id },
transaction,
});
// Destroy old version
await LocalListVersion.destroy({ where: { stationId }, transaction });
}
const localListVersion = await LocalListVersion.create({
tenantId,
stationId,
versionNumber: sendLocalList.versionNumber,
}, { transaction });
if (!sendLocalList.localAuthorizationList) {
return localListVersion;
}
for (const auth of sendLocalList.localAuthorizationList) {
await LocalListVersionAuthorization.create({
tenantId,
localListVersionId: localListVersion.id,
authorizationId: auth.id,
}, { transaction });
}
return localListVersion.reload({ include: [LocalListAuthorization], transaction });
});
this.emit('created', [localListVersion]);
return localListVersion;
}
async updateLocalListVersionFromStationIdAndSendLocalListRequest(tenantId, stationId, sendLocalList) {
const localListVersion = await this.s.transaction(async (transaction) => {
if (!sendLocalList.localAuthorizationList) {
// See D01.FR.05
const localListVersion = await this._updateAllByQuery(tenantId, { versionNumber: sendLocalList.versionNumber }, { where: { stationId }, transaction });
if (localListVersion.length !== 1) {
throw new Error(`LocalListVersion not found for ${stationId} during differential version update: ${JSON.stringify(localListVersion)}`);
}
else {
return localListVersion[0];
}
}
const localListVersion = await LocalListVersion.findOne({
where: { stationId },
include: [LocalListAuthorization],
transaction,
});
if (!localListVersion) {
throw new Error(`LocalListVersion not found for ${stationId} during differential update`);
}
for (const sendAuth of sendLocalList.localAuthorizationList) {
// If there is already an association with the same authorizationId, remove it
const oldAuth = localListVersion.localAuthorizationList?.find((localAuth) => localAuth.authorizationId === sendAuth.authorizationId);
if (oldAuth) {
await LocalListVersionAuthorization.destroy({
where: {
localListVersionId: localListVersion.id,
authorizationId: oldAuth.authorizationId,
},
transaction,
});
}
await LocalListVersionAuthorization.create({
tenantId,
localListVersionId: localListVersion.id,
authorizationId: sendAuth.id,
}, { transaction });
}
await localListVersion.update({ versionNumber: sendLocalList.versionNumber }, { transaction });
return localListVersion.reload({ include: [LocalListAuthorization], transaction });
});
this.emit('updated', [localListVersion]);
return localListVersion;
}
}
//# sourceMappingURL=LocalAuthList.js.map