@digigov-oss/auditrecord-postgresql-engine
Version:
PostgreSQL storage database for use with audit mechanism of GSIS
157 lines (140 loc) • 6.03 kB
text/typescript
//To check this engine you have to have a PostgreSQL database installed and running.
//The database must be configured to allow connections from the host that the application is running on.
//The database must also have the following table:
//table audit_records
// auditUnit: varchar(255);
// auditTransactionId: varchar(255);
// auditProtocol: varchar(255);
// auditTransactionDate: varchar(20);
// auditUserIp: varchar(16);
// auditUserId: varchar(255);
// if you do not provide the table name, the engine will create it for you.
//You can use Docker to run PostgreSQL for your tests.
//`docker run -d --name audit-postgres -e POSTGRES_PASSWORD=audit --network host postgres`
//`docker exec -it audit-postgres psql -U postgres -h localhost -c "CREATE DATABASE audit;"`
//`docker exec -it audit-postgres psql -U postgres -h localhost -c "CREATE TABLE audit_log (auditUnit varchar(255), auditTransactionId varchar(255), auditProtocol varchar(255), auditTransactionDate varchar(20), auditUserIp varchar(16), auditUserId varchar(255));"`
//You can also map the fields of already existent table to the fields in the audit log.
import Client from 'pg-native';
import { AuditRecord, AuditEngine, DatabaseSettings, PNRESETTYPES } from '@digigov-oss/gsis-audit-record-db';
/**
* @description AuditEngine implementation
* @note This class is used to implement the methods that must be implemented by the AuditEngine
* @class PostgreSqlEngine
* @implements AuditEngine
* @param {string} connectionString - connect to db via connection string
* @param {DatabaseSettings} dbSettings - database settings
*/
export class PostgreSqlEngine implements AuditEngine {
#table: string;
#columnNames:AuditRecord;
#client: any;
/**
* @description constructor
* @param {string} connectionString - connect to db via connection string
* @param {DatabaseSettings} settings - settings for the database
* @param {AuditRecord} columnNames - column names
* @memberof PostgreSqlEngine
*/
constructor(connectionString:string = "", dbSettings: DatabaseSettings={}) {
const connection = connectionString!=""?{connectionString}:{};
this.#table = dbSettings.tableName || "audit_records";
this.#columnNames = dbSettings.columns || {
auditUnit: "auditUnit",
auditTransactionId: "auditTransactionId",
auditProtocol: "auditProtocol",
auditTransactionDate: "auditTransactionDate",
auditUserIp: "auditUserIp",
auditUserId: "auditUserId"
}
this.#client = new Client(connection);
this.#client.connectSync();
if (!dbSettings.tableName) {
this.#client.querySync("CREATE TABLE IF NOT EXISTS "+this.#table+" ("+this.#columnNames.auditUnit+" varchar(255), "+this.#columnNames.auditTransactionId+" varchar(255), "+this.#columnNames.auditProtocol+" varchar(255), "+this.#columnNames.auditTransactionDate+" varchar(20), "+this.#columnNames.auditUserIp+" varchar(16), "+this.#columnNames.auditUserId+" varchar(255));");
}
}
/**
* @description Store a record in the database
* @param {AuditRecord} record - record to be stored
* @returns {AuditRecord} - the record stored
* @memberof FileEngine
* @method put
*/
put(record: AuditRecord): AuditRecord {
const data = JSON.stringify(record, null, 2);
try {
this.#client.querySync("INSERT INTO "+this.#table+" ("+this.#columnNames.auditUnit+","+this.#columnNames.auditTransactionId+","+this.#columnNames.auditProtocol+","+this.#columnNames.auditTransactionDate+","+this.#columnNames.auditUserIp+","+this.#columnNames.auditUserId+") \
VALUES ('"+record.auditUnit+"','"+record.auditTransactionId+"','"+record.auditProtocol+"','"+record.auditTransactionDate+"','"+record.auditUserIp+"','"+record.auditUserId+"');");
return record;
} catch (error) {
throw error;
}
}
/**
* @description Get a record from the database
* @param auditTransactionId: string - transaction id
* @returns {AuditRecord}
* @memberof FileEngine
* @method get
*/
get(auditTransactionId: string): AuditRecord {
try {
let data = {}
const res = this.#client.querySync("SELECT * FROM "+this.#table+" WHERE "+this.#columnNames.auditTransactionId+"='"+auditTransactionId+"';");
data = res[0];
return data;
} catch (error) {
throw error;
}
}
/**
* @description Generate a new sequence number
* @param path
* @returns number
* @memberof FileEngine
* @method seq
*/
seq():number {
try {
this.#client.querySync("CREATE SEQUENCE IF NOT EXISTS "+this.#table+"_seq START 1");
const res = this.#client.querySync("SELECT nextval('"+this.#table+"_seq');");
return res[0].nextval;
} catch (error) {
throw error;
}
}
/**
* @description Generate a new protocol number
* @param path
* @returns string
* @memberof FileEngine
* @method protocol
*/
pn(pnreset?:PNRESETTYPES): string {
try {
let protocol_split = "aion";
let protocol_date = new Date().toISOString().split('T')[0];
switch(pnreset){
case "daily":
protocol_split = protocol_date;
break;
case "monthly":
protocol_split = protocol_date.split('-')[0]+"-"+protocol_date.split('-')[1];
break;
case "yearly":
protocol_split = protocol_date.split('-')[0];
break;
case "innumerable":
protocol_split = "aion";
break;
}
const seqName = "prot"+protocol_split.replace(/-/g, '');
//create sequence for protocol_split if not exists
this.#client.querySync("CREATE SEQUENCE IF NOT EXISTS "+seqName+"_seq START 1");
const res = this.#client.querySync("SELECT nextval('"+seqName+"_seq');");
return res[0].nextval+"/"+protocol_date;
} catch (error) {
throw error;
}
}
}
export default PostgreSqlEngine;