Skip to content

Commit

Permalink
Add urn generation to aoe-web-backend
Browse files Browse the repository at this point in the history
  • Loading branch information
MikkoKauhanen committed Jan 16, 2025
1 parent 7701295 commit c0fff32
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 35 deletions.
1 change: 0 additions & 1 deletion aoe-infra/bin/infra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,6 @@ if (environmentName === 'dev' || environmentName === 'qa' || environmentName ===
Secrets.secrets.SESSION_SECRET,
Secrets.secrets.CLIENT_SECRET,
Secrets.secrets.JWT_SECRET,
Secrets.secrets.PID_API_KEY,
Secrets.secrets.PROXY_URI,
Secrets.secrets.CLIENT_ID
],
Expand Down
5 changes: 2 additions & 3 deletions aoe-infra/environments/dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@
"image_tag": "ga-267",
"allow_ecs_exec": true,
"env_vars": {
"PID_SERVICE_URL": "http://localhost",
"NODE_ENV": "production",
"LOG_LEVEL": "error",
"PORT_LISTEN": "8080",
Expand Down Expand Up @@ -163,8 +162,8 @@
"KAFKA_ENABLED": "1",
"LOGIN_ENABLED": "1",

"PID_SERVICE_RUN_SCHEDULED": "0",
"PID_SERVICE_ENABLED": "0",
"PID_SERVICE_RUN_SCHEDULED": "1",
"PID_SERVICE_ENABLED": "1",

"STREAM_ENABLED": "1",
"STREAM_FILESIZE_MIN": "100000",
Expand Down
1 change: 0 additions & 1 deletion aoe-infra/environments/qa.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@
"image_tag": "ga-267",
"allow_ecs_exec": true,
"env_vars": {
"PID_SERVICE_URL": "http://localhost",
"NODE_ENV": "production",
"LOG_LEVEL": "error",
"PORT_LISTEN": "8080",
Expand Down
1 change: 0 additions & 1 deletion aoe-infra/lib/secrets-manager-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export class SecretManagerStack extends cdk.Stack {
SESSION_SECRET: { envVarName: 'SESSION_SECRET', path: '/service/web-backend/SESSION_SECRET', secretKey: 'secretkey' },
CLIENT_SECRET: { envVarName: 'CLIENT_SECRET', path: '/service/web-backend/CLIENT_SECRET', secretKey: 'secretkey' },
JWT_SECRET: { envVarName: 'JWT_SECRET', path: '/service/web-backend/JWT_SECRET', secretKey: 'secretkey' },
PID_API_KEY: { envVarName: 'PID_API_KEY', path: '/service/web-backend/PID_API_KEY', secretKey: 'secretkey' },
ANALYTICS_PG_PASS: {envVarName: 'SPRING_DATASOURCE_PRIMARY_PASSWORD', path: '/auroradbs/web-backend/dev/reporter', secretKey: 'password' },
ANALYTICS_DOCDB_PASSWORD: {envVarName: 'MONGODB_PRIMARY_PASSWORD', path: '/service/data-analytics/DOCDB_PASS', secretKey: 'secretkey' },
ANALYTICS_TRUST_STORE_PASSWORD: {envVarName: 'TRUST_STORE_PASS', path: '/service/data-analytics/TRUST_STORE_PASS', secretKey: 'secretkey' },
Expand Down
2 changes: 0 additions & 2 deletions aoe-web-backend/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ CONVERSION_TO_PDF_ENABLED=1
## PID Service
PID_SERVICE_RUN_SCHEDULED=0
PID_SERVICE_ENABLED=0
PID_API_KEY=
PID_SERVICE_URL=

## PosgreSQL Database
POSTGRESQL_HOST=
Expand Down
4 changes: 0 additions & 4 deletions aoe-web-backend/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ process.env.STREAM_REDIRECT_URI || missingEnvs.push('STREAM_REDIRECT_URI');
process.env.STREAM_STATUS_HOST || missingEnvs.push('STREAM_STATUS_HOST');
process.env.STREAM_STATUS_PATH || missingEnvs.push('STREAM_STATUS_PATH');
process.env.STREAM_STATUS_HOST_HTTPS_ENABLED || missingEnvs.push('STREAM_STATUS_HOST_HTTPS_ENABLED');
process.env.PID_API_KEY || missingEnvs.push('PID_API_KEY');
process.env.PID_SERVICE_URL || missingEnvs.push('PID_SERVICE_URL');
process.env.PG_USER || missingEnvs.push('PG_USER');
process.env.PG_PASS || missingEnvs.push('PG_PASS');

Expand Down Expand Up @@ -120,8 +118,6 @@ export default {
// AOE server and service component general purpose configurations.
SERVER_CONFIG_OPTIONS: {
oaipmhAnalyticsURL: process.env.SERVER_CONFIG_OAIPMH_ANALYTICS_URL as string,
pidApiKey: process.env.PID_API_KEY as string,
pidServiceURL: process.env.PID_SERVICE_URL as string,
} as const,

// Session management conventions to handle session initialization and persistence.
Expand Down
26 changes: 26 additions & 0 deletions aoe-web-backend/src/domain/aoeModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@ export const commonSettings: ModelOptions = {
timestamps: false,
};

export const Urn = sequelize.define<UrnModel>(
'urn',
{
id: {
field: 'id',
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
material_url: {
field: 'material_url',
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
},
{
indexes: [
{
unique: true,
fields: ['material_url'],
},
],
} && (commonSettings as ModelOptions),
);

export const AOEUser = <AOEUserType>sequelize.define(
'aoeuser',
{
Expand Down
65 changes: 43 additions & 22 deletions aoe-web-backend/src/services/pidResolutionService.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import axios, { AxiosRequestConfig } from 'axios';
import { updateEduMaterialVersionURN } from '@query/apiQueries';
import { getEdumaterialVersionsWithoutURN } from '@query/pidQueries';
import { getEduMaterialVersionURL } from './urlService';
import winstonLogger from '@util/winstonLogger';
import { IRegisterPID } from '@aoe/services/pidResolutionService';
import config from '@/config';
import { Urn } from '@domain/aoeModels';

/**
* Request for PID registration using URN type.
* @param url string Resource URL for PID registration.
*/
export const registerPID = async (url: string): Promise<any> => {
try {
const pidRegistrationParams: IRegisterPID = {
url: url as string,
type: 'URN',
persist: '0',
};
const requestHeaders: Record<string, string> = {
'Content-Type': 'application/json',
apikey: config.SERVER_CONFIG_OPTIONS.pidApiKey,
};
const response: Record<string, unknown> = await axios.post(
config.SERVER_CONFIG_OPTIONS.pidServiceURL,
pidRegistrationParams as IRegisterPID,
{ headers: requestHeaders } as AxiosRequestConfig,
);
return response.data;
} catch (error) {
winstonLogger.error('PID registration failed in registerPID(): ' + error);
export const registerPID = async (url: string): Promise<string> => {
const record = await Urn.findOne({
where: { material_url: url },
});

if (record) {
winstonLogger.error(`URL ${url} already has urn generated`);
return null;
}

const newId = await Urn.create({ material_url: url });
const internalId = newId.id;
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, '0');

// Previous URN generator generated formattedInternalId with 8 digits. To prevent possible duplicates increase it to 9
const formattedInternalId = internalId.toString().padStart(9, '0');
const formattedString = `${year}${month}${formattedInternalId}`;

const luhnChecksum = calculateLuhn(formattedString);
return `urn:nbn:fi:oerfi-${year}${month}${formattedInternalId}_${luhnChecksum}`;
};

/**
Expand Down Expand Up @@ -82,6 +82,27 @@ export const processEntriesWithoutPID = async (): Promise<void> => {
}
};

const calculateLuhn = (number: string): number => {
let sum = 0;
let alternate = false;

for (let i = number.length - 1; i >= 0; i--) {
let n = parseInt(number[i], 10);

if (alternate) {
n *= 2;
if (n > 9) {
n -= 9;
}
}

sum += n;
alternate = !alternate;
}

return (10 - (sum % 10)) % 10;
};

export default {
processEntriesWithoutPID,
registerPID,
Expand Down
7 changes: 6 additions & 1 deletion aoe-web-backend/types/aoe/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BuildOptions, Model } from 'sequelize';
import { BuildOptions, CreationOptional, InferAttributes, InferCreationAttributes, Model } from 'sequelize';

/**
* Global interface and type declarations for the data persistence with Sequelize.
Expand Down Expand Up @@ -141,4 +141,9 @@ declare global {
type TemporaryRecordType = typeof Model & {
new (values?: Record<string, unknown>, options?: BuildOptions): TemporaryRecord;
};

interface UrnModel extends Model<InferAttributes<UrnModel>, InferCreationAttributes<UrnModel, { omit: 'id' }>> {
id: CreationOptional<number>;
material_url: string;
}
}

0 comments on commit c0fff32

Please sign in to comment.