Coder Social home page Coder Social logo

mayflower / postgraphile-audit-plugin Goto Github PK

View Code? Open in Web Editor NEW
11.0 13.0 2.0 1.33 MB

This plugin adds functionality to access pgMemento's audit data on an entity level from a postgraphile graphql api.

Home Page: https://www.npmjs.com/package/postgraphile-audit-plugin

License: MIT License

JavaScript 8.62% PLpgSQL 4.38% TypeScript 83.33% Shell 3.67%
postgraphile pgmemento graphql audit

postgraphile-audit-plugin's Introduction

Motivation

This plugin adds functionality to access pgMemento's audit data on an entity level from a postgraphile graphql api.

Each Entity for an audited table can be extended automatically with the following properties:

interface Audited {
  firstAuditEvent: AuditEvent!
  lastAuditEvent: AuditEvent!
  createdAt: String!
  lastModifiedAt: String!
  createdBy: String!
  lastModifiedBy: String!
  auditEvents(
    first: Int
    last: Int
    offset: Int
    before: Cursor
    after: Cursor
  ): AuditEventsConnection!
}

interface AuditEvent {
  id: BigInt
  auditId: BigInt
  eventId: Int
  transactionId: Int
  userName: String
  stmtDate: Datetime
  sessionInfo: JSON
  valuesBefore: JSON
  valuesAfter: JSON
}

Properties can be renamed using inflection and their presence can be configured.

Installation

npm install postgraphile-audit-plugin
# this will ask you for a target schema and then create the `AuditEvent` type and `get_audit_information` function.
psql -h host -p 5432 -U user -d database -f Setup.sql

Usage

The plugin comes preconfigured out of the box. It can be configured using a .postgraphilerc.js:

/**
 * @type {import("./src").AuditPluginOptions}
 */
const auditPlugin = {
  /**
   * name of the schema that contains the `get_audit_information` function
   */
  auditFunctionSchema: "public",

  /**
   * include "auditEvents" connection on audited types
   */
  auditEventConnection: true,

  /**
   * include "firstAuditEvent" and "lastAuditEvent" field on audited types
   */
  firstLastAuditEvent: true,

  /**
   * include "createdAt" and "lastModifiedAt" field on audited types
   */
  dateProps: true,

  /**
   * include "createdBy" and "lastModifiedBy" on audited types
   */
  nameProps: true,

  /**
   * define how "name" properties should be filled - either with the transaction's "user_name", or with a value from the "session_info" JSON
   * can be "user_name" or "session_info";
   */
  nameSource: "session_info",

  /**
   * if `nameSource` is "session_info", this describes the path to the username within the JSON
   * e.g. "{name}" or "{nested,user,name}" (see the #>> notation described in https://www.postgresql.org/docs/9.3/functions-json.html)
   */
  nameSessionInfoJsonPath: "{nested,name}",

  /**
   * if name cannot be filled (because it is null or undefined), fall back to this value
   */
  nameFallback: "unknown user",
};

module.exports = {
  options: {
    graphileBuildOptions: {
      auditPlugin,
    },
  },
};

Extracting the user name from a JWT and writing it to session_info

You can return an object contining the key pgmemento.session_info from a callback provided to the pgSettings option. At this point, postgraphile will already have validated the JWT against the jwtSecret option, so you can trust the claims without additional validation. A basic usage could look like this (e.g. in your .postgraphilerc.js):

module.exports = {
  options: {
    async pgSettings(req) {
      const claims = getClaimsFromRequest(req);
      return {
        "pgmemento.session_info": JSON.stringify({
          userId: claims.name,
        }),
      };
    },
    jwtSecret: "my-jwt-secret",
  },
};

function getClaimsFromRequest(req) {
  try {
    const { authorization } = req.headers;
    const [, token] = /^\s*bearer\s+(.*?)\s*$/i.exec(authorization);
    const [, claims] = token.split(".");
    return JSON.parse(Buffer.from(claims, "base64").toString());
  } catch {
    return {};
  }
}

License

MIT. See LICENSE

postgraphile-audit-plugin's People

Contributors

dependabot[bot] avatar khartir avatar marco-arnold avatar mariahaubner avatar xedon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

postgraphile-audit-plugin's Issues

Error: Cannot find module 'tslib'

Hi,
I'm getting error Cannot find module 'tslib'

Error: Cannot find module 'tslib'
Require stack:
- /usr/local/lib/node_modules/postgraphile-audit-plugin/node_modules/graphile-utils/node8plus/index.js
- /usr/local/lib/node_modules/postgraphile-audit-plugin/dist/index.js
- /usr/local/lib/node_modules/postgraphile/build/postgraphile/cli.js
- /usr/local/lib/node_modules/postgraphile/cli.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1020:15)
    at Function.Module._load (internal/modules/cjs/loader.js:890:27)
    at Module.require (internal/modules/cjs/loader.js:1080:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/postgraphile-audit-plugin/node_modules/graphile-utils/node8plus/index.js:3:17)
    at Module._compile (internal/modules/cjs/loader.js:1176:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1196:10)
    at Module.load (internal/modules/cjs/loader.js:1040:32)
    at Function.Module._load (internal/modules/cjs/loader.js:929:14)
    at Module.require (internal/modules/cjs/loader.js:1080:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/usr/local/lib/node_modules/postgraphile-audit-plugin/node_modules/graphile-utils/node8plus/index.js',
    '/usr/local/lib/node_modules/postgraphile-audit-plugin/dist/index.js',
    '/usr/local/lib/node_modules/postgraphile/build/postgraphile/cli.js',
    '/usr/local/lib/node_modules/postgraphile/cli.js'
  ]
}
internal/modules/cjs/loader.js:1023
  throw err;
  ^

My dockerfile:

FROM node:14-alpine

RUN npm install -g graphql
RUN npm install -g postgraphile
RUN npm install -g graphile-build

RUN npm install -g postgraphile-plugin-connection-filter

RUN npm install -g @graphile-contrib/pg-simplify-inflector
RUN npm install -g @graphile-contrib/pg-order-by-related
RUN npm install -g @graphile-contrib/pg-many-to-many
RUN npm install -g @graphile-contrib/pg-order-by-multi-column-index
RUN npm install -g @graphile/pg-pubsub

RUN npm install -g postgraphile-plugin-nested-mutations
RUN npm install -g postgraphile-audit-plugin

COPY .postgraphilerc.js .postgraphilerc.js

RUN npm cache clean --force

.postgraphilerc.js

const auditPlugin = {
  /**
   * name of the schema that contains the `get_audit_information` function
   */
  auditFunctionSchema: "study",

  /**
   * include "auditEvents" connection on audited types
   */
  auditEventConnection: true,

  /**
   * include "firstAuditEvent" and "lastAuditEvent" field on audited types
   */
  firstLastAuditEvent: true,

  /**
   * include "createdAt" and "lastModifiedAt" field on audited types
   */
  dateProps: true,

  /**
   * include "createdBy" and "lastModifiedBy" on audited types
   */
  nameProps: true,

  /**
   * define how "name" properties should be filled - either with the transaction's "user_name", or with a value from the "session_info" JSON
   * can be "user_name" or "session_info";
   */
  nameSource: "session_info",

  /**
   * if `nameSource` is "session_info", this describes the path to the username within the JSON
   * e.g. "{name}" or "{nested,user,name}" (see the #>> notation described in https://www.postgresql.org/docs/9.3/functions-json.html)
   */
  nameSessionInfoJsonPath: "{nested,name}",

  /**
   * if name cannot be filled (because it is null or undefined), fall back to this value
   */
  nameFallback: "unknown_user",
};

module.exports = {
  options: {
    graphileBuildOptions: {
      auditPlugin,
    },
  },
};

docker-compose.yaml

    command: [
        "postgraphile",
        "--plugins",
        "@graphile/pg-pubsub",
        "--append-plugins",
        "postgraphile-plugin-connection-filter,@graphile-contrib/pg-simplify-inflector,@graphile-contrib/pg-order-by-related,@graphile-contrib/pg-many-to-many,postgraphile-plugin-nested-mutations,postgraphile-audit-plugin",
        "--connection",
        "postgres://my_user:my_password@postgresql-master:5432/study_tracker",
        "--owner-connection",
        "postgres://postgres:postgres_password@postgresql-master:5432/study_tracker",
        "--host",
        "0.0.0.0",
        "--port",
        "5433",
        "--cors",
        "--schema",
        "study",
        "--watch",
        "--simple-collections",
        "both",
        "--enable-query-batching",
        "--no-ignore-rbac",
        "--dynamic-json",
        "--no-setof-functions-contain-nulls",
        "--subscriptions",
        "--simple-subscriptions",
        "--graphql",
        "/graphql",
        "--graphiql",
        "/graphiql",
        "--extended-errors",
        "errcode",
        "--enhance-graphiql",
      ]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.