Files
MikrotikManager/backend/scripts/writer-profile/context.mjs
T

29 lines
3.3 KiB
JavaScript

// Internal fixed SQL/state verification. No signing, provisioning, pool or issuer.
import {canonical} from '../../src/db/application-writer-profile-format.js'
import {readProtectedRegistryStructureData} from '../../src/db/application-writer-profile-registry-structure.js'
export {readCurrentApplicationWriterProfile as readCurrent,HISTORY,CURRENT} from '../../src/db/application-writer-profile-registry-read.js'
const same=(a,b,phase)=>{if(canonical(a)!==canonical(b))throw Error('Protected registry refused: '+phase)}
export async function ownedContext(client,installation,actor,phase){
const rows=(await client.query(`SELECT CURRENT_USER::text AS actor,SESSION_USER::text AS login,r.oid::text AS role_oid,
d.oid::text AS database_oid,d.datname AS database_name,pg_catalog.pg_backend_pid() AS pid,
pg_catalog.pg_current_xact_id_if_assigned()::text AS xid,pg_catalog.current_setting('transaction_read_only') AS read_only,
pg_catalog.current_setting('transaction_isolation') AS isolation,pg_catalog.current_setting('server_version_num')::int AS version,
pg_catalog.pg_is_in_recovery() AS recovery,control.system_identifier::text AS system_identifier,
(EXTRACT(EPOCH FROM pg_catalog.clock_timestamp())*1000)::bigint::text AS server_now,
EXISTS(SELECT 1 FROM pg_catalog.pg_locks l WHERE l.pid=pg_catalog.pg_backend_pid() AND l.locktype='advisory'
AND l.database=d.oid AND l.classid=0 AND l.objid=8723110 AND l.objsubid=1 AND l.granted
AND l.mode=ANY($1::text[])) AS admitted
FROM pg_catalog.pg_roles r CROSS JOIN pg_catalog.pg_database d CROSS JOIN pg_catalog.pg_control_system() control
WHERE r.rolname=CURRENT_USER AND d.datname=pg_catalog.current_database()`,[phase.startsWith('publisher')?['ExclusiveLock']:['ShareLock','ExclusiveLock']])).rows
const c=rows[0],expectedOid=installation.roleBindings.publisher.signedOid
if(actor!==installation.roleBindings.publisher.name||rows.length!==1||!c||c.actor!==actor||c.login!==actor||c.role_oid!==expectedOid||c.recovery!==false||c.version<180000||c.version>=190000||c.admitted!==true||!Number.isSafeInteger(c.pid)||!/^[1-9][0-9]*$/.test(c.database_oid)||!(/^[1-9][0-9]{0,19}$/).test(c.system_identifier))throw Error('Distinct actual actor/source/admission context refused')
if(phase==='publisher-read'&&(c.read_only!=='on'||c.isolation!=='repeatable read')||phase==='publisher-inspect'&&(c.read_only!=='on'||c.isolation!=='read committed')||['publisher-write','operator'].includes(phase)&&(c.read_only!=='off'||c.isolation!=='read committed'||!(/^[1-9][0-9]*$/).test(c.xid??'')))throw Error('Distinct owned transaction context refused')
return c
}
export function sameOwned(a,b){same(Object.fromEntries(['actor','login','role_oid','database_oid','database_name','pid','xid','read_only','isolation','version','recovery','system_identifier','admitted'].map(k=>[k,a[k]])),Object.fromEntries(['actor','login','role_oid','database_oid','database_name','pid','xid','read_only','isolation','version','recovery','system_identifier','admitted'].map(k=>[k,b[k]])),'backend/fullXID/lifetime')}
export const sourceCoordinates=c=>({systemIdentifier:c.system_identifier,databaseOid:c.database_oid,databaseName:c.database_name,serverVersionNum:c.version,inRecovery:false})
export function protectedStructure(client,installation){return readProtectedRegistryStructureData(client,installation.roleBindings)}