Merge pull request #1797 from RafaelTaranto/chore/nodejs-version-bump
LAM-1368 chore: nodejs version bump
This commit is contained in:
commit
ff3fd34cf5
58 changed files with 16443 additions and 11282 deletions
47
.github/workflows/build.yml
vendored
47
.github/workflows/build.yml
vendored
|
|
@ -1,47 +0,0 @@
|
||||||
name: build
|
|
||||||
|
|
||||||
on: [ workflow_dispatch ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
everything:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Cache Docker layers
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache
|
|
||||||
key: ${{ runner.os }}-buildx-updatetar
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-updatetar
|
|
||||||
|
|
||||||
- name: Build Docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: build/ci.Dockerfile
|
|
||||||
load: true
|
|
||||||
tags: ci_image:latest
|
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new
|
|
||||||
|
|
||||||
- name: Extract artifact from Docker image
|
|
||||||
run: |
|
|
||||||
docker create --name extract_artifact ci_image:latest
|
|
||||||
docker cp extract_artifact:/lamassu-server.tar.gz ./lamassu-server.tar.gz
|
|
||||||
docker rm extract_artifact
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: lamassu-server.tar.gz
|
|
||||||
path: lamassu-server.tar.gz
|
|
||||||
|
|
||||||
- name: Move cache
|
|
||||||
run: |
|
|
||||||
rm -rf /tmp/.buildx-cache
|
|
||||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
nodejs 14
|
nodejs 22
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
require('../lib/environment-helper')
|
require('../lib/environment-helper')
|
||||||
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
|
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
|
||||||
const userManagement = require('../lib/new-admin/graphql/modules/userManagement')
|
const userManagement = require('../lib/new-admin/graphql/modules/userManagement')
|
||||||
const authErrors = require('../lib/new-admin/graphql/errors/authentication')
|
const authErrors = require('../lib/new-admin/graphql/errors')
|
||||||
|
|
||||||
const name = process.argv[2]
|
const name = process.argv[2]
|
||||||
const role = process.argv[3]
|
const role = process.argv[3]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
const adminServer = require('../lib/new-admin/graphql-dev-insecure')
|
|
||||||
|
|
||||||
adminServer.run()
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
FROM ubuntu:20.04 as base
|
|
||||||
|
|
||||||
ARG VERSION
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
|
||||||
ENV TZ=Europe/Lisbon
|
|
||||||
|
|
||||||
RUN apt-get update
|
|
||||||
|
|
||||||
RUN apt-get install -y -q curl \
|
|
||||||
sudo \
|
|
||||||
git \
|
|
||||||
python2-minimal \
|
|
||||||
build-essential \
|
|
||||||
libpq-dev \
|
|
||||||
net-tools \
|
|
||||||
tar
|
|
||||||
|
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
|
|
||||||
RUN apt-get install nodejs -y -q
|
|
||||||
|
|
||||||
WORKDIR lamassu-server
|
|
||||||
|
|
||||||
COPY ["package.json", "package-lock.json", "./"]
|
|
||||||
RUN npm version --allow-same-version --git-tag-version false --commit-hooks false 1.0.0
|
|
||||||
RUN npm install --production
|
|
||||||
|
|
||||||
COPY . ./
|
|
||||||
|
|
||||||
RUN cd new-lamassu-admin && npm install && npm run build
|
|
||||||
RUN mv new-lamassu-admin/build public/
|
|
||||||
RUN rm -rf new-lamassu-admin/node_modules
|
|
||||||
|
|
||||||
RUN cd .. && tar -zcvf lamassu-server.tar.gz ./lamassu-server
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
FROM alpine:3.14 AS build
|
FROM node:22-alpine AS build
|
||||||
RUN apk add --no-cache nodejs npm git curl build-base net-tools python3 postgresql-dev
|
RUN apk add --no-cache npm git curl build-base net-tools python3 postgresql-dev
|
||||||
|
|
||||||
WORKDIR lamassu-server
|
WORKDIR lamassu-server
|
||||||
|
|
||||||
|
|
@ -10,8 +10,8 @@ RUN npm install --production
|
||||||
COPY . ./
|
COPY . ./
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.14 AS l-s-base
|
FROM node:22-alpine AS l-s-base
|
||||||
RUN apk add --no-cache nodejs npm git curl bash libpq openssl ca-certificates
|
RUN apk add --no-cache npm git curl bash libpq openssl ca-certificates
|
||||||
|
|
||||||
COPY --from=build /lamassu-server /lamassu-server
|
COPY --from=build /lamassu-server /lamassu-server
|
||||||
|
|
||||||
|
|
|
||||||
45
lib/app.js
45
lib/app.js
|
|
@ -1,11 +1,10 @@
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const http = require('http')
|
|
||||||
const https = require('https')
|
const https = require('https')
|
||||||
const argv = require('minimist')(process.argv.slice(2))
|
const argv = require('minimist')(process.argv.slice(2))
|
||||||
|
|
||||||
require('./environment-helper')
|
require('./environment-helper')
|
||||||
const { asyncLocalStorage, defaultStore } = require('./async-storage')
|
const { asyncLocalStorage, defaultStore } = require('./async-storage')
|
||||||
const routes = require('./routes')
|
const { loadRoutes } = require('./routes')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
const poller = require('./poller')
|
const poller = require('./poller')
|
||||||
const settingsLoader = require('./new-settings-loader')
|
const settingsLoader = require('./new-settings-loader')
|
||||||
|
|
@ -16,8 +15,7 @@ const ofacUpdate = require('./ofac/update')
|
||||||
|
|
||||||
const KEY_PATH = process.env.KEY_PATH
|
const KEY_PATH = process.env.KEY_PATH
|
||||||
const CERT_PATH = process.env.CERT_PATH
|
const CERT_PATH = process.env.CERT_PATH
|
||||||
|
const CA_PATH = process.env.CA_PATH
|
||||||
const devMode = argv.dev
|
|
||||||
|
|
||||||
const version = require('../package.json').version
|
const version = require('../package.json').version
|
||||||
logger.info('Version: %s', version)
|
logger.info('Version: %s', version)
|
||||||
|
|
@ -40,7 +38,7 @@ function run () {
|
||||||
.then(settings => {
|
.then(settings => {
|
||||||
clearInterval(handler)
|
clearInterval(handler)
|
||||||
return loadSanctions(settings)
|
return loadSanctions(settings)
|
||||||
.then(() => startServer(settings))
|
.then(startServer)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
})
|
})
|
||||||
.catch(errorHandler)
|
.catch(errorHandler)
|
||||||
|
|
@ -68,30 +66,27 @@ function loadSanctions (settings) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function startServer (settings) {
|
async function startServer () {
|
||||||
return Promise.resolve()
|
const app = await loadRoutes()
|
||||||
.then(() => {
|
|
||||||
poller.setup(['public'])
|
|
||||||
const httpsServerOptions = {
|
|
||||||
key: fs.readFileSync(KEY_PATH),
|
|
||||||
cert: fs.readFileSync(CERT_PATH),
|
|
||||||
requestCert: true,
|
|
||||||
rejectUnauthorized: false
|
|
||||||
}
|
|
||||||
|
|
||||||
const server = devMode
|
poller.setup(['public'])
|
||||||
? http.createServer(routes.app)
|
|
||||||
: https.createServer(httpsServerOptions, routes.app)
|
|
||||||
|
|
||||||
const port = argv.port || 3000
|
const httpsServerOptions = {
|
||||||
|
key: fs.readFileSync(KEY_PATH),
|
||||||
|
cert: fs.readFileSync(CERT_PATH),
|
||||||
|
ca: fs.readFileSync(CA_PATH),
|
||||||
|
requestCert: true,
|
||||||
|
rejectUnauthorized: false
|
||||||
|
}
|
||||||
|
|
||||||
if (devMode) logger.info('In dev mode')
|
const server = https.createServer(httpsServerOptions, app)
|
||||||
|
|
||||||
server.listen(port, () => {
|
const port = argv.port || 3000
|
||||||
logger.info('lamassu-server listening on port ' +
|
|
||||||
port + ' ' + (devMode ? '(http)' : '(https)'))
|
await new Promise((resolve) =>
|
||||||
})
|
server.listen({ port }, resolve),
|
||||||
})
|
)
|
||||||
|
logger.info(`lamassu-server listening on port ${port}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { run }
|
module.exports = { run }
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
const logger = require('../logger')
|
const logger = require('../logger')
|
||||||
|
|
||||||
const https = require('https')
|
const { ApolloServer } = require('@apollo/server')
|
||||||
const { ApolloServer } = require('apollo-server-express')
|
|
||||||
|
|
||||||
const devMode = !!require('minimist')(process.argv.slice(2)).dev
|
const devMode = !!require('minimist')(process.argv.slice(2)).dev
|
||||||
|
|
||||||
module.exports = new ApolloServer({
|
const context = ({ req, res }) => ({
|
||||||
|
deviceId: req.deviceId, /* lib/middlewares/populateDeviceId.js */
|
||||||
|
deviceName: req.deviceName, /* lib/middlewares/authorize.js */
|
||||||
|
operatorId: res.locals.operatorId, /* lib/middlewares/operatorId.js */
|
||||||
|
pid: req.query.pid,
|
||||||
|
settings: req.settings, /* lib/middlewares/populateSettings.js */
|
||||||
|
})
|
||||||
|
|
||||||
|
const graphQLServer = new ApolloServer({
|
||||||
typeDefs: require('./types'),
|
typeDefs: require('./types'),
|
||||||
resolvers: require('./resolvers'),
|
resolvers: require('./resolvers'),
|
||||||
context: ({ req, res }) => ({
|
|
||||||
deviceId: req.deviceId, /* lib/middlewares/populateDeviceId.js */
|
|
||||||
deviceName: req.deviceName, /* lib/middlewares/authorize.js */
|
|
||||||
operatorId: res.locals.operatorId, /* lib/middlewares/operatorId.js */
|
|
||||||
pid: req.query.pid,
|
|
||||||
settings: req.settings, /* lib/middlewares/populateSettings.js */
|
|
||||||
}),
|
|
||||||
uploads: false,
|
|
||||||
playground: false,
|
|
||||||
introspection: false,
|
introspection: false,
|
||||||
formatError: error => {
|
formatError: error => {
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
return error
|
return error
|
||||||
},
|
},
|
||||||
debug: devMode,
|
includeStacktraceInErrorResponses: devMode,
|
||||||
logger
|
logger
|
||||||
})
|
})
|
||||||
|
|
||||||
|
module.exports = { graphQLServer, context }
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
module.exports = gql`
|
module.exports = gql`
|
||||||
type Coin {
|
type Coin {
|
||||||
cryptoCode: String!
|
cryptoCode: String!
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const dbm = require('./postgresql_interface')
|
||||||
const configManager = require('./new-config-manager')
|
const configManager = require('./new-config-manager')
|
||||||
const notifierUtils = require('./notifier/utils')
|
const notifierUtils = require('./notifier/utils')
|
||||||
const notifierQueries = require('./notifier/queries')
|
const notifierQueries = require('./notifier/queries')
|
||||||
const { ApolloError } = require('apollo-server-errors');
|
const { GraphQLError } = require('graphql');
|
||||||
const { loadLatestConfig } = require('./new-settings-loader')
|
const { loadLatestConfig } = require('./new-settings-loader')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@ function getMachine (machineId, config) {
|
||||||
const sql = `${MACHINE_WITH_CALCULATED_FIELD_SQL} WHERE d.device_id = $1`
|
const sql = `${MACHINE_WITH_CALCULATED_FIELD_SQL} WHERE d.device_id = $1`
|
||||||
|
|
||||||
const queryMachine = db.oneOrNone(sql, [machineId]).then(r => {
|
const queryMachine = db.oneOrNone(sql, [machineId]).then(r => {
|
||||||
if (r === null) throw new ApolloError('Resource doesn\'t exist', 'NOT_FOUND')
|
if (r === null) throw new GraphQLError('Resource doesn\'t exist', { extensions: { code: 'NOT_FOUND' } })
|
||||||
else return toMachineObject(r)
|
else return toMachineObject(r)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
const _ = require('lodash/fp')
|
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
|
|
||||||
const logger = require('../logger')
|
|
||||||
|
|
||||||
function sha256 (buf) {
|
function sha256 (buf) {
|
||||||
if (!buf) return null
|
if (!buf) return null
|
||||||
const hash = crypto.createHash('sha256')
|
const hash = crypto.createHash('sha256')
|
||||||
|
|
@ -12,10 +9,9 @@ function sha256 (buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const populateDeviceId = function (req, res, next) {
|
const populateDeviceId = function (req, res, next) {
|
||||||
const deviceId = _.isFunction(req.connection.getPeerCertificate)
|
const peerCert = req.socket.getPeerCertificate ? req.socket.getPeerCertificate() : null
|
||||||
? sha256(req.connection.getPeerCertificate()?.raw)
|
const deviceId = peerCert?.raw ? sha256(peerCert.raw) : null
|
||||||
: null
|
|
||||||
|
|
||||||
if (!deviceId) return res.status(500).json({ error: 'Unable to find certificate' })
|
if (!deviceId) return res.status(500).json({ error: 'Unable to find certificate' })
|
||||||
req.deviceId = deviceId
|
req.deviceId = deviceId
|
||||||
req.deviceTime = req.get('date')
|
req.deviceTime = req.get('date')
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,23 @@ const path = require('path')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const https = require('https')
|
const https = require('https')
|
||||||
const serveStatic = require('serve-static')
|
const serveStatic = require('serve-static')
|
||||||
const cors = require('cors')
|
|
||||||
const helmet = require('helmet')
|
const helmet = require('helmet')
|
||||||
const nocache = require('nocache')
|
const nocache = require('nocache')
|
||||||
const cookieParser = require('cookie-parser')
|
const cookieParser = require('cookie-parser')
|
||||||
const { graphqlUploadExpress } = require('graphql-upload')
|
const { ApolloServer } = require('@apollo/server')
|
||||||
const { ApolloServer } = require('apollo-server-express')
|
const { expressMiddleware } = require('@apollo/server/express4')
|
||||||
|
const { ApolloServerPluginLandingPageDisabled } = require('@apollo/server/plugin/disabled')
|
||||||
|
const { ApolloServerPluginLandingPageLocalDefault } = require('@apollo/server/plugin/landingPage/default')
|
||||||
|
|
||||||
|
const { mergeResolvers } = require('@graphql-tools/merge')
|
||||||
|
const { makeExecutableSchema } = require('@graphql-tools/schema')
|
||||||
|
|
||||||
require('../environment-helper')
|
require('../environment-helper')
|
||||||
const { asyncLocalStorage, defaultStore } = require('../async-storage')
|
const { asyncLocalStorage, defaultStore } = require('../async-storage')
|
||||||
const logger = require('../logger')
|
const logger = require('../logger')
|
||||||
const exchange = require('../exchange')
|
const exchange = require('../exchange')
|
||||||
|
|
||||||
const { AuthDirective } = require('./graphql/directives')
|
const { authDirectiveTransformer } = require('./graphql/directives')
|
||||||
const { typeDefs, resolvers } = require('./graphql/schema')
|
const { typeDefs, resolvers } = require('./graphql/schema')
|
||||||
const findOperatorId = require('../middlewares/operatorId')
|
const findOperatorId = require('../middlewares/operatorId')
|
||||||
const computeSchema = require('../compute-schema')
|
const computeSchema = require('../compute-schema')
|
||||||
|
|
@ -28,6 +32,7 @@ const devMode = require('minimist')(process.argv.slice(2)).dev
|
||||||
const HOSTNAME = process.env.HOSTNAME
|
const HOSTNAME = process.env.HOSTNAME
|
||||||
const KEY_PATH = process.env.KEY_PATH
|
const KEY_PATH = process.env.KEY_PATH
|
||||||
const CERT_PATH = process.env.CERT_PATH
|
const CERT_PATH = process.env.CERT_PATH
|
||||||
|
const CA_PATH = process.env.CA_PATH
|
||||||
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
|
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
|
||||||
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
|
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
|
||||||
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
|
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
|
||||||
|
|
@ -37,64 +42,79 @@ if (!HOSTNAME) {
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = express()
|
const loadRoutes = async () => {
|
||||||
|
const app = express()
|
||||||
|
|
||||||
app.use(helmet())
|
app.use(helmet())
|
||||||
app.use(compression())
|
app.use(compression())
|
||||||
app.use(nocache())
|
app.use(nocache())
|
||||||
app.use(cookieParser())
|
app.use(cookieParser())
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
app.use(express.urlencoded({ extended: true })) // support encoded bodies
|
app.use(express.urlencoded({ extended: true })) // support encoded bodies
|
||||||
app.use(express.static(path.resolve(__dirname, '..', '..', 'public')))
|
app.use(express.static(path.resolve(__dirname, '..', '..', 'public')))
|
||||||
app.use(cleanUserSessions(USER_SESSIONS_CLEAR_INTERVAL))
|
app.use(cleanUserSessions(USER_SESSIONS_CLEAR_INTERVAL))
|
||||||
app.use(computeSchema)
|
app.use(computeSchema)
|
||||||
app.use(findOperatorId)
|
app.use(findOperatorId)
|
||||||
app.use(session)
|
app.use(session)
|
||||||
app.use(graphqlUploadExpress())
|
|
||||||
|
|
||||||
const apolloServer = new ApolloServer({
|
// Dynamic import for graphql-upload since it's not a CommonJS module
|
||||||
typeDefs,
|
const { default: graphqlUploadExpress } = await import('graphql-upload/graphqlUploadExpress.mjs')
|
||||||
resolvers,
|
const { default: GraphQLUpload } = await import('graphql-upload/GraphQLUpload.mjs')
|
||||||
uploads: false,
|
|
||||||
schemaDirectives: {
|
|
||||||
auth: AuthDirective
|
|
||||||
},
|
|
||||||
playground: false,
|
|
||||||
introspection: false,
|
|
||||||
formatError: error => {
|
|
||||||
const exception = error?.extensions?.exception
|
|
||||||
logger.error(error, JSON.stringify(exception || {}))
|
|
||||||
return error
|
|
||||||
},
|
|
||||||
context: async (obj) => buildApolloContext(obj)
|
|
||||||
})
|
|
||||||
|
|
||||||
apolloServer.applyMiddleware({
|
app.use(graphqlUploadExpress())
|
||||||
app,
|
|
||||||
cors: {
|
|
||||||
credentials: true,
|
|
||||||
origin: devMode && 'https://localhost:3001'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// cors on app for /api/register endpoint.
|
const schema = makeExecutableSchema({
|
||||||
app.use(cors({ credentials: true, origin: devMode && 'https://localhost:3001' }))
|
typeDefs,
|
||||||
|
resolvers: mergeResolvers(resolvers, { Upload: GraphQLUpload }),
|
||||||
|
})
|
||||||
|
const schemaWithDirectives = authDirectiveTransformer(schema)
|
||||||
|
|
||||||
app.use('/id-card-photo', serveStatic(ID_PHOTO_CARD_DIR, { index: false }))
|
const apolloServer = new ApolloServer({
|
||||||
app.use('/front-camera-photo', serveStatic(FRONT_CAMERA_DIR, { index: false }))
|
schema: schemaWithDirectives,
|
||||||
app.use('/operator-data', serveStatic(OPERATOR_DATA_DIR, { index: false }))
|
csrfPrevention: false,
|
||||||
|
introspection: false,
|
||||||
|
formatError: (formattedError, error) => {
|
||||||
|
logger.error(error, JSON.stringify(error?.extensions || {}))
|
||||||
|
return formattedError
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
devMode
|
||||||
|
? ApolloServerPluginLandingPageLocalDefault()
|
||||||
|
: ApolloServerPluginLandingPageDisabled()
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
// Everything not on graphql or api/register is redirected to the front-end
|
await apolloServer.start();
|
||||||
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, '..', '..', 'public', 'index.html')))
|
|
||||||
|
app.use(
|
||||||
|
'/graphql',
|
||||||
|
express.json(),
|
||||||
|
expressMiddleware(apolloServer, {
|
||||||
|
context: async ({ req, res }) => buildApolloContext({ req, res })
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
app.use('/id-card-photo', serveStatic(ID_PHOTO_CARD_DIR, { index: false }))
|
||||||
|
app.use('/front-camera-photo', serveStatic(FRONT_CAMERA_DIR, { index: false }))
|
||||||
|
app.use('/operator-data', serveStatic(OPERATOR_DATA_DIR, { index: false }))
|
||||||
|
|
||||||
|
// Everything not on graphql or api/register is redirected to the front-end
|
||||||
|
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, '..', '..', 'public', 'index.html')))
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
const certOptions = {
|
const certOptions = {
|
||||||
key: fs.readFileSync(KEY_PATH),
|
key: fs.readFileSync(KEY_PATH),
|
||||||
cert: fs.readFileSync(CERT_PATH)
|
cert: fs.readFileSync(CERT_PATH),
|
||||||
|
ca: fs.readFileSync(CA_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
function run () {
|
function run () {
|
||||||
const store = defaultStore()
|
const store = defaultStore()
|
||||||
asyncLocalStorage.run(store, () => {
|
asyncLocalStorage.run(store, async () => {
|
||||||
|
const app = await loadRoutes()
|
||||||
const serverPort = devMode ? 8070 : 443
|
const serverPort = devMode ? 8070 : 443
|
||||||
|
|
||||||
const serverLog = `lamassu-admin-server listening on port ${serverPort}`
|
const serverLog = `lamassu-admin-server listening on port ${serverPort}`
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
const express = require('express')
|
|
||||||
const { ApolloServer } = require('apollo-server-express')
|
|
||||||
|
|
||||||
require('../environment-helper')
|
|
||||||
const { typeDefs, resolvers } = require('./graphql/schema')
|
|
||||||
const logger = require('../logger')
|
|
||||||
|
|
||||||
const app = express()
|
|
||||||
const server = new ApolloServer({
|
|
||||||
typeDefs,
|
|
||||||
resolvers
|
|
||||||
})
|
|
||||||
|
|
||||||
server.applyMiddleware({ app })
|
|
||||||
|
|
||||||
app.use(express.json())
|
|
||||||
|
|
||||||
function run () {
|
|
||||||
const serverLog = `lamassu-admin-server listening on port ${9010}${server.graphqlPath}`
|
|
||||||
|
|
||||||
app.listen(9010, () => logger.info(serverLog))
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { run }
|
|
||||||
|
|
@ -1,40 +1,49 @@
|
||||||
const _ = require('lodash/fp')
|
const _ = require('lodash/fp')
|
||||||
|
const { mapSchema, getDirective, MapperKind } = require('@graphql-tools/utils')
|
||||||
const { SchemaDirectiveVisitor, AuthenticationError } = require('apollo-server-express')
|
|
||||||
const { defaultFieldResolver } = require('graphql')
|
const { defaultFieldResolver } = require('graphql')
|
||||||
|
|
||||||
class AuthDirective extends SchemaDirectiveVisitor {
|
const { AuthenticationError } = require('../errors')
|
||||||
visitObject (type) {
|
|
||||||
this.ensureFieldsWrapped(type)
|
|
||||||
type._requiredAuthRole = this.args.requires
|
|
||||||
}
|
|
||||||
|
|
||||||
visitFieldDefinition (field, details) {
|
function authDirectiveTransformer(schema, directiveName = 'auth') {
|
||||||
this.ensureFieldsWrapped(details.objectType)
|
return mapSchema(schema, {
|
||||||
field._requiredAuthRole = this.args.requires
|
// For object types
|
||||||
}
|
[MapperKind.OBJECT_TYPE]: (objectType) => {
|
||||||
|
const directive = getDirective(schema, objectType, directiveName)?.[0]
|
||||||
ensureFieldsWrapped (objectType) {
|
if (directive) {
|
||||||
if (objectType._authFieldsWrapped) return
|
const requiredAuthRole = directive.requires
|
||||||
objectType._authFieldsWrapped = true
|
objectType._requiredAuthRole = requiredAuthRole
|
||||||
|
}
|
||||||
const fields = objectType.getFields()
|
return objectType
|
||||||
|
},
|
||||||
_.forEach(fieldName => {
|
|
||||||
const field = fields[fieldName]
|
// For field definitions
|
||||||
const { resolve = defaultFieldResolver } = field
|
[MapperKind.OBJECT_FIELD]: (fieldConfig, _fieldName, typeName) => {
|
||||||
|
const directive = getDirective(schema, fieldConfig, directiveName)?.[0]
|
||||||
field.resolve = function (root, args, context, info) {
|
if (directive) {
|
||||||
const requiredRoles = field._requiredAuthRole ? field._requiredAuthRole : objectType._requiredAuthRole
|
const requiredAuthRole = directive.requires
|
||||||
|
fieldConfig._requiredAuthRole = requiredAuthRole
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the parent object type
|
||||||
|
const objectType = schema.getType(typeName)
|
||||||
|
|
||||||
|
// Apply auth check to the field's resolver
|
||||||
|
const { resolve = defaultFieldResolver } = fieldConfig
|
||||||
|
fieldConfig.resolve = function (root, args, context, info) {
|
||||||
|
const requiredRoles = fieldConfig._requiredAuthRole || objectType._requiredAuthRole
|
||||||
if (!requiredRoles) return resolve.apply(this, [root, args, context, info])
|
if (!requiredRoles) return resolve.apply(this, [root, args, context, info])
|
||||||
|
|
||||||
const user = context.req.session.user
|
const user = context.req.session.user
|
||||||
if (!user || !_.includes(_.upperCase(user.role), requiredRoles)) throw new AuthenticationError('You do not have permission to access this resource!')
|
if (!user || !_.includes(_.upperCase(user.role), requiredRoles)) {
|
||||||
|
throw new AuthenticationError('You do not have permission to access this resource!')
|
||||||
|
}
|
||||||
|
|
||||||
return resolve.apply(this, [root, args, context, info])
|
return resolve.apply(this, [root, args, context, info])
|
||||||
}
|
}
|
||||||
}, _.keys(fields))
|
|
||||||
}
|
return fieldConfig
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AuthDirective
|
module.exports = authDirectiveTransformer
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
const AuthDirective = require('./auth')
|
const authDirectiveTransformer = require('./auth')
|
||||||
|
|
||||||
module.exports = { AuthDirective }
|
module.exports = { authDirectiveTransformer }
|
||||||
|
|
|
||||||
71
lib/new-admin/graphql/errors.js
Normal file
71
lib/new-admin/graphql/errors.js
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
const { GraphQLError } = require('graphql')
|
||||||
|
const { ApolloServerErrorCode } = require('@apollo/server/errors')
|
||||||
|
|
||||||
|
class AuthenticationError extends GraphQLError {
|
||||||
|
constructor() {
|
||||||
|
super('Authentication failed', {
|
||||||
|
extensions: {
|
||||||
|
code: 'UNAUTHENTICATED'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidCredentialsError extends GraphQLError {
|
||||||
|
constructor() {
|
||||||
|
super('Invalid credentials', {
|
||||||
|
extensions: {
|
||||||
|
code: 'INVALID_CREDENTIALS'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserAlreadyExistsError extends GraphQLError {
|
||||||
|
constructor() {
|
||||||
|
super('User already exists', {
|
||||||
|
extensions: {
|
||||||
|
code: 'USER_ALREADY_EXISTS'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidTwoFactorError extends GraphQLError {
|
||||||
|
constructor() {
|
||||||
|
super('Invalid two-factor code', {
|
||||||
|
extensions: {
|
||||||
|
code: 'INVALID_TWO_FACTOR_CODE'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidUrlError extends GraphQLError {
|
||||||
|
constructor() {
|
||||||
|
super('Invalid URL token', {
|
||||||
|
extensions: {
|
||||||
|
code: 'INVALID_URL_TOKEN'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserInputError extends GraphQLError {
|
||||||
|
constructor() {
|
||||||
|
super('User input error', {
|
||||||
|
extensions: {
|
||||||
|
code: ApolloServerErrorCode.BAD_USER_INPUT
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
AuthenticationError,
|
||||||
|
InvalidCredentialsError,
|
||||||
|
UserAlreadyExistsError,
|
||||||
|
InvalidTwoFactorError,
|
||||||
|
InvalidUrlError,
|
||||||
|
UserInputError
|
||||||
|
}
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
const { ApolloError, AuthenticationError } = require('apollo-server-express')
|
|
||||||
|
|
||||||
class InvalidCredentialsError extends ApolloError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message, 'INVALID_CREDENTIALS')
|
|
||||||
Object.defineProperty(this, 'name', { value: 'InvalidCredentialsError' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UserAlreadyExistsError extends ApolloError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message, 'USER_ALREADY_EXISTS')
|
|
||||||
Object.defineProperty(this, 'name', { value: 'UserAlreadyExistsError' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InvalidTwoFactorError extends ApolloError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message, 'INVALID_TWO_FACTOR_CODE')
|
|
||||||
Object.defineProperty(this, 'name', { value: 'InvalidTwoFactorError' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InvalidUrlError extends ApolloError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message, 'INVALID_URL_TOKEN')
|
|
||||||
Object.defineProperty(this, 'name', { value: 'InvalidUrlError' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
AuthenticationError,
|
|
||||||
InvalidCredentialsError,
|
|
||||||
UserAlreadyExistsError,
|
|
||||||
InvalidTwoFactorError,
|
|
||||||
InvalidUrlError
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,7 @@ const loginHelper = require('../../services/login')
|
||||||
const T = require('../../../time')
|
const T = require('../../../time')
|
||||||
const users = require('../../../users')
|
const users = require('../../../users')
|
||||||
const sessionManager = require('../../../session-manager')
|
const sessionManager = require('../../../session-manager')
|
||||||
const authErrors = require('../errors/authentication')
|
const authErrors = require('../errors')
|
||||||
const credentials = require('../../../hardware-credentials')
|
const credentials = require('../../../hardware-credentials')
|
||||||
|
|
||||||
const REMEMBER_ME_AGE = 90 * T.day
|
const REMEMBER_ME_AGE = 90 * T.day
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
const { GraphQLDateTime } = require('graphql-iso-date')
|
const { DateTimeISOResolver, JSONResolver, JSONObjectResolver } = require('graphql-scalars')
|
||||||
const { GraphQLJSON, GraphQLJSONObject } = require('graphql-type-json')
|
|
||||||
const { GraphQLUpload } = require('graphql-upload')
|
|
||||||
GraphQLDateTime.name = 'Date'
|
|
||||||
|
|
||||||
const resolvers = {
|
const resolvers = {
|
||||||
JSON: GraphQLJSON,
|
JSON: JSONResolver,
|
||||||
JSONObject: GraphQLJSONObject,
|
JSONObject: JSONObjectResolver,
|
||||||
Date: GraphQLDateTime,
|
DateTimeISO: DateTimeISOResolver
|
||||||
UploadGQL: GraphQLUpload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = resolvers
|
module.exports = resolvers
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Bill {
|
type Bill {
|
||||||
|
|
@ -6,7 +6,7 @@ const typeDef = gql`
|
||||||
fiat: Int
|
fiat: Int
|
||||||
fiatCode: String
|
fiatCode: String
|
||||||
deviceId: ID
|
deviceId: ID
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
cashUnitOperationId: ID
|
cashUnitOperationId: ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Blacklist {
|
type Blacklist {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type CashboxBatch {
|
type CashboxBatch {
|
||||||
id: ID
|
id: ID
|
||||||
deviceId: ID
|
deviceId: ID
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
operationType: String
|
operationType: String
|
||||||
customBillCount: Int
|
customBillCount: Int
|
||||||
performedBy: String
|
performedBy: String
|
||||||
|
|
@ -14,7 +14,7 @@ const typeDef = gql`
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
cashboxBatches: [CashboxBatch] @auth
|
cashboxBatches: [CashboxBatch] @auth
|
||||||
cashboxBatchesCsv(from: Date, until: Date, timezone: String): String @auth
|
cashboxBatchesCsv(from: DateTimeISO, until: DateTimeISO, timezone: String): String @auth
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Country {
|
type Country {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Currency {
|
type Currency {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
|
|
||||||
|
|
@ -33,7 +33,7 @@ const typeDef = gql`
|
||||||
customerId: ID
|
customerId: ID
|
||||||
infoRequestId: ID
|
infoRequestId: ID
|
||||||
override: String
|
override: String
|
||||||
overrideAt: Date
|
overrideAt: DateTimeISO
|
||||||
overrideBy: ID
|
overrideBy: ID
|
||||||
customerData: JSON
|
customerData: JSON
|
||||||
customInfoRequest: CustomInfoRequest
|
customInfoRequest: CustomInfoRequest
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Customer {
|
type Customer {
|
||||||
|
|
@ -6,10 +6,10 @@ const typeDef = gql`
|
||||||
authorizedOverride: String
|
authorizedOverride: String
|
||||||
daysSuspended: Int
|
daysSuspended: Int
|
||||||
isSuspended: Boolean
|
isSuspended: Boolean
|
||||||
newPhoto: UploadGQL
|
newPhoto: Upload
|
||||||
photoType: String
|
photoType: String
|
||||||
frontCameraPath: String
|
frontCameraPath: String
|
||||||
frontCameraAt: Date
|
frontCameraAt: DateTimeISO
|
||||||
frontCameraOverride: String
|
frontCameraOverride: String
|
||||||
phone: String
|
phone: String
|
||||||
email: String
|
email: String
|
||||||
|
|
@ -17,19 +17,19 @@ const typeDef = gql`
|
||||||
smsOverride: String
|
smsOverride: String
|
||||||
idCardData: JSONObject
|
idCardData: JSONObject
|
||||||
idCardDataOverride: String
|
idCardDataOverride: String
|
||||||
idCardDataExpiration: Date
|
idCardDataExpiration: DateTimeISO
|
||||||
idCardPhoto: UploadGQL
|
idCardPhoto: Upload
|
||||||
idCardPhotoPath: String
|
idCardPhotoPath: String
|
||||||
idCardPhotoOverride: String
|
idCardPhotoOverride: String
|
||||||
idCardPhotoAt: Date
|
idCardPhotoAt: DateTimeISO
|
||||||
usSsn: String
|
usSsn: String
|
||||||
usSsnOverride: String
|
usSsnOverride: String
|
||||||
sanctions: Boolean
|
sanctions: Boolean
|
||||||
sanctionsAt: Date
|
sanctionsAt: DateTimeISO
|
||||||
sanctionsOverride: String
|
sanctionsOverride: String
|
||||||
totalTxs: Int
|
totalTxs: Int
|
||||||
totalSpent: String
|
totalSpent: String
|
||||||
lastActive: Date
|
lastActive: DateTimeISO
|
||||||
lastTxFiat: String
|
lastTxFiat: String
|
||||||
lastTxFiatCode: String
|
lastTxFiatCode: String
|
||||||
lastTxClass: String
|
lastTxClass: String
|
||||||
|
|
@ -53,28 +53,28 @@ const typeDef = gql`
|
||||||
smsOverride: String
|
smsOverride: String
|
||||||
idCardData: JSONObject
|
idCardData: JSONObject
|
||||||
idCardDataOverride: String
|
idCardDataOverride: String
|
||||||
idCardDataExpiration: Date
|
idCardDataExpiration: DateTimeISO
|
||||||
idCardPhotoPath: String
|
idCardPhotoPath: String
|
||||||
idCardPhotoOverride: String
|
idCardPhotoOverride: String
|
||||||
usSsn: String
|
usSsn: String
|
||||||
usSsnOverride: String
|
usSsnOverride: String
|
||||||
sanctions: Boolean
|
sanctions: Boolean
|
||||||
sanctionsAt: Date
|
sanctionsAt: DateTimeISO
|
||||||
sanctionsOverride: String
|
sanctionsOverride: String
|
||||||
totalTxs: Int
|
totalTxs: Int
|
||||||
totalSpent: String
|
totalSpent: String
|
||||||
lastActive: Date
|
lastActive: DateTimeISO
|
||||||
lastTxFiat: String
|
lastTxFiat: String
|
||||||
lastTxFiatCode: String
|
lastTxFiatCode: String
|
||||||
lastTxClass: String
|
lastTxClass: String
|
||||||
suspendedUntil: Date
|
suspendedUntil: DateTimeISO
|
||||||
subscriberInfo: Boolean
|
subscriberInfo: Boolean
|
||||||
phoneOverride: String
|
phoneOverride: String
|
||||||
}
|
}
|
||||||
|
|
||||||
input CustomerEdit {
|
input CustomerEdit {
|
||||||
idCardData: JSONObject
|
idCardData: JSONObject
|
||||||
idCardPhoto: UploadGQL
|
idCardPhoto: Upload
|
||||||
usSsn: String
|
usSsn: String
|
||||||
subscriberInfo: JSONObject
|
subscriberInfo: JSONObject
|
||||||
}
|
}
|
||||||
|
|
@ -82,8 +82,8 @@ const typeDef = gql`
|
||||||
type CustomerNote {
|
type CustomerNote {
|
||||||
id: ID
|
id: ID
|
||||||
customerId: ID
|
customerId: ID
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
lastEditedAt: Date
|
lastEditedAt: DateTimeISO
|
||||||
lastEditedBy: ID
|
lastEditedBy: ID
|
||||||
title: String
|
title: String
|
||||||
content: String
|
content: String
|
||||||
|
|
@ -108,7 +108,7 @@ const typeDef = gql`
|
||||||
removeCustomField(customerId: ID!, fieldId: ID!): Boolean @auth
|
removeCustomField(customerId: ID!, fieldId: ID!): Boolean @auth
|
||||||
editCustomer(customerId: ID!, customerEdit: CustomerEdit): Customer @auth
|
editCustomer(customerId: ID!, customerEdit: CustomerEdit): Customer @auth
|
||||||
deleteEditedData(customerId: ID!, customerEdit: CustomerEdit): Customer @auth
|
deleteEditedData(customerId: ID!, customerEdit: CustomerEdit): Customer @auth
|
||||||
replacePhoto(customerId: ID!, photoType: String, newPhoto: UploadGQL): Customer @auth
|
replacePhoto(customerId: ID!, photoType: String, newPhoto: Upload): Customer @auth
|
||||||
createCustomerNote(customerId: ID!, title: String!, content: String!): Boolean @auth
|
createCustomerNote(customerId: ID!, title: String!, content: String!): Boolean @auth
|
||||||
editCustomerNote(noteId: ID!, newContent: String!): Boolean @auth
|
editCustomerNote(noteId: ID!, newContent: String!): Boolean @auth
|
||||||
deleteCustomerNote(noteId: ID!): Boolean @auth
|
deleteCustomerNote(noteId: ID!): Boolean @auth
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type CoinFunds {
|
type CoinFunds {
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type MachineLog {
|
type MachineLog {
|
||||||
id: ID!
|
id: ID!
|
||||||
logLevel: String!
|
logLevel: String!
|
||||||
timestamp: Date!
|
timestamp: DateTimeISO!
|
||||||
message: String!
|
message: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerLog {
|
type ServerLog {
|
||||||
id: ID!
|
id: ID!
|
||||||
logLevel: String!
|
logLevel: String!
|
||||||
timestamp: Date!
|
timestamp: DateTimeISO!
|
||||||
message: String
|
message: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
machineLogs(deviceId: ID!, from: Date, until: Date, limit: Int, offset: Int): [MachineLog] @auth
|
machineLogs(deviceId: ID!, from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int): [MachineLog] @auth
|
||||||
machineLogsCsv(deviceId: ID!, from: Date, until: Date, limit: Int, offset: Int, timezone: String): String @auth
|
machineLogsCsv(deviceId: ID!, from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int, timezone: String): String @auth
|
||||||
serverLogs(from: Date, until: Date, limit: Int, offset: Int): [ServerLog] @auth
|
serverLogs(from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int): [ServerLog] @auth
|
||||||
serverLogsCsv(from: Date, until: Date, limit: Int, offset: Int, timezone: String): String @auth
|
serverLogsCsv(from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int, timezone: String): String @auth
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type IndividualDiscount {
|
type IndividualDiscount {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type MachineStatus {
|
type MachineStatus {
|
||||||
|
|
@ -10,8 +10,8 @@ const typeDef = gql`
|
||||||
name: String!
|
name: String!
|
||||||
deviceId: ID!
|
deviceId: ID!
|
||||||
paired: Boolean!
|
paired: Boolean!
|
||||||
lastPing: Date
|
lastPing: DateTimeISO
|
||||||
pairedAt: Date
|
pairedAt: DateTimeISO
|
||||||
diagnostics: Diagnostics
|
diagnostics: Diagnostics
|
||||||
version: String
|
version: String
|
||||||
model: String
|
model: String
|
||||||
|
|
@ -26,9 +26,9 @@ const typeDef = gql`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Diagnostics {
|
type Diagnostics {
|
||||||
timestamp: Date
|
timestamp: DateTimeISO
|
||||||
frontTimestamp: Date
|
frontTimestamp: DateTimeISO
|
||||||
scanTimestamp: Date
|
scanTimestamp: DateTimeISO
|
||||||
}
|
}
|
||||||
|
|
||||||
type CashUnits {
|
type CashUnits {
|
||||||
|
|
@ -64,8 +64,8 @@ const typeDef = gql`
|
||||||
deviceId: ID!
|
deviceId: ID!
|
||||||
name: String
|
name: String
|
||||||
model: String
|
model: String
|
||||||
paired: Date!
|
paired: DateTimeISO!
|
||||||
unpaired: Date!
|
unpaired: DateTimeISO!
|
||||||
}
|
}
|
||||||
|
|
||||||
type MachineEvent {
|
type MachineEvent {
|
||||||
|
|
@ -73,9 +73,9 @@ const typeDef = gql`
|
||||||
deviceId: String
|
deviceId: String
|
||||||
eventType: String
|
eventType: String
|
||||||
note: String
|
note: String
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
age: Float
|
age: Float
|
||||||
deviceTime: Date
|
deviceTime: DateTimeISO
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MachineAction {
|
enum MachineAction {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Query {
|
type Query {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Notification {
|
type Notification {
|
||||||
|
|
@ -6,7 +6,7 @@ const typeDef = gql`
|
||||||
type: String
|
type: String
|
||||||
detail: JSON
|
detail: JSON
|
||||||
message: String
|
message: String
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
read: Boolean
|
read: Boolean
|
||||||
valid: Boolean
|
valid: Boolean
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Rate {
|
type Rate {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type SanctionMatches {
|
type SanctionMatches {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
scalar JSON
|
scalar JSON
|
||||||
scalar JSONObject
|
scalar JSONObject
|
||||||
scalar Date
|
scalar DateTimeISO
|
||||||
scalar UploadGQL
|
scalar Upload
|
||||||
`
|
`
|
||||||
|
|
||||||
module.exports = typeDef
|
module.exports = typeDef
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Query {
|
type Query {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type SMSNotice {
|
type SMSNotice {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type ProcessStatus {
|
type ProcessStatus {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Transaction {
|
type Transaction {
|
||||||
|
|
@ -14,12 +14,12 @@ const typeDef = gql`
|
||||||
txHash: String
|
txHash: String
|
||||||
phone: String
|
phone: String
|
||||||
error: String
|
error: String
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
send: Boolean
|
send: Boolean
|
||||||
sendConfirmed: Boolean
|
sendConfirmed: Boolean
|
||||||
dispense: Boolean
|
dispense: Boolean
|
||||||
timedout: Boolean
|
timedout: Boolean
|
||||||
sendTime: Date
|
sendTime: DateTimeISO
|
||||||
errorCode: String
|
errorCode: String
|
||||||
operatorCompleted: Boolean
|
operatorCompleted: Boolean
|
||||||
sendPending: Boolean
|
sendPending: Boolean
|
||||||
|
|
@ -35,7 +35,7 @@ const typeDef = gql`
|
||||||
customerPhone: String
|
customerPhone: String
|
||||||
customerEmail: String
|
customerEmail: String
|
||||||
customerIdCardDataNumber: String
|
customerIdCardDataNumber: String
|
||||||
customerIdCardDataExpiration: Date
|
customerIdCardDataExpiration: DateTimeISO
|
||||||
customerIdCardData: JSONObject
|
customerIdCardData: JSONObject
|
||||||
customerName: String
|
customerName: String
|
||||||
customerFrontCameraPath: String
|
customerFrontCameraPath: String
|
||||||
|
|
@ -44,9 +44,9 @@ const typeDef = gql`
|
||||||
machineName: String
|
machineName: String
|
||||||
discount: Int
|
discount: Int
|
||||||
txCustomerPhotoPath: String
|
txCustomerPhotoPath: String
|
||||||
txCustomerPhotoAt: Date
|
txCustomerPhotoAt: DateTimeISO
|
||||||
batched: Boolean
|
batched: Boolean
|
||||||
batchTime: Date
|
batchTime: DateTimeISO
|
||||||
batchError: String
|
batchError: String
|
||||||
walletScore: Int
|
walletScore: Int
|
||||||
profit: String
|
profit: String
|
||||||
|
|
@ -60,8 +60,8 @@ const typeDef = gql`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
transactions(from: Date, until: Date, limit: Int, offset: Int, txClass: String, deviceId: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, swept: Boolean, excludeTestingCustomers: Boolean): [Transaction] @auth
|
transactions(from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int, txClass: String, deviceId: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, swept: Boolean, excludeTestingCustomers: Boolean): [Transaction] @auth
|
||||||
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int, txClass: String, deviceId: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, swept: Boolean, timezone: String, excludeTestingCustomers: Boolean, simplified: Boolean): String @auth
|
transactionsCsv(from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int, txClass: String, deviceId: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, swept: Boolean, timezone: String, excludeTestingCustomers: Boolean, simplified: Boolean): String @auth
|
||||||
transactionCsv(id: ID, txClass: String, timezone: String): String @auth
|
transactionCsv(id: ID, txClass: String, timezone: String): String @auth
|
||||||
txAssociatedDataCsv(id: ID, txClass: String, timezone: String): String @auth
|
txAssociatedDataCsv(id: ID, txClass: String, timezone: String): String @auth
|
||||||
transactionFilters: [Filter] @auth
|
transactionFilters: [Filter] @auth
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ const typeDef = `
|
||||||
type UserSession {
|
type UserSession {
|
||||||
sid: String!
|
sid: String!
|
||||||
sess: JSONObject!
|
sess: JSONObject!
|
||||||
expire: Date!
|
expire: DateTimeISO!
|
||||||
}
|
}
|
||||||
|
|
||||||
type User {
|
type User {
|
||||||
|
|
@ -53,8 +53,8 @@ const typeDef = `
|
||||||
username: String
|
username: String
|
||||||
role: String
|
role: String
|
||||||
enabled: Boolean
|
enabled: Boolean
|
||||||
created: Date
|
created: DateTimeISO
|
||||||
last_accessed: Date
|
last_accessed: DateTimeISO
|
||||||
last_accessed_from: String
|
last_accessed_from: String
|
||||||
last_accessed_address: String
|
last_accessed_address: String
|
||||||
}
|
}
|
||||||
|
|
@ -68,14 +68,14 @@ const typeDef = `
|
||||||
type ResetToken {
|
type ResetToken {
|
||||||
token: String
|
token: String
|
||||||
user_id: ID
|
user_id: ID
|
||||||
expire: Date
|
expire: DateTimeISO
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegistrationToken {
|
type RegistrationToken {
|
||||||
token: String
|
token: String
|
||||||
username: String
|
username: String
|
||||||
role: String
|
role: String
|
||||||
expire: Date
|
expire: DateTimeISO
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const { gql } = require('apollo-server-express')
|
const gql = require('graphql-tag')
|
||||||
|
|
||||||
const typeDef = gql`
|
const typeDef = gql`
|
||||||
type Query {
|
type Query {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
const { AuthenticationError } = require('apollo-server-express')
|
|
||||||
const users = require('../../users')
|
const users = require('../../users')
|
||||||
|
|
||||||
|
const { AuthenticationError } = require('../graphql/errors')
|
||||||
|
|
||||||
const buildApolloContext = async ({ req, res }) => {
|
const buildApolloContext = async ({ req, res }) => {
|
||||||
if (!req.session.user) return { req, res }
|
if (!req.session.user) return { req, res }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
const machineLoader = require('../../machine-loader')
|
const machineLoader = require('../../machine-loader')
|
||||||
const { UserInputError } = require('apollo-server-express')
|
const { UserInputError } = require('../graphql/errors')
|
||||||
|
|
||||||
function getMachine (machineId) {
|
function getMachine (machineId) {
|
||||||
return machineLoader.getMachines()
|
return machineLoader.getMachines()
|
||||||
|
|
|
||||||
138
lib/routes.js
138
lib/routes.js
|
|
@ -1,5 +1,4 @@
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const argv = require('minimist')(process.argv.slice(2))
|
|
||||||
const compression = require('compression')
|
const compression = require('compression')
|
||||||
const helmet = require('helmet')
|
const helmet = require('helmet')
|
||||||
const morgan = require('morgan')
|
const morgan = require('morgan')
|
||||||
|
|
@ -35,84 +34,97 @@ const verifyPromoCodeRoutes = require('./routes/verifyPromoCodeRoutes')
|
||||||
const probeRoutes = require('./routes/probeLnRoutes')
|
const probeRoutes = require('./routes/probeLnRoutes')
|
||||||
const failedQRScansRoutes = require('./routes/failedQRScans')
|
const failedQRScansRoutes = require('./routes/failedQRScans')
|
||||||
|
|
||||||
const graphQLServer = require('./graphql/server')
|
const { graphQLServer, context } = require('./graphql/server')
|
||||||
|
|
||||||
const app = express()
|
const { expressMiddleware } = require('@apollo/server/express4')
|
||||||
|
|
||||||
const configRequiredRoutes = [
|
const loadRoutes = async () => {
|
||||||
'/poll',
|
const app = express()
|
||||||
'/terms_conditions',
|
|
||||||
'/event',
|
|
||||||
'/phone_code',
|
|
||||||
'/customer',
|
|
||||||
'/tx',
|
|
||||||
'/verify_promo_code',
|
|
||||||
'/graphql'
|
|
||||||
]
|
|
||||||
|
|
||||||
// middleware setup
|
const configRequiredRoutes = [
|
||||||
app.use(addRWBytes())
|
'/poll',
|
||||||
app.use(compression({ threshold: 500 }))
|
'/terms_conditions',
|
||||||
app.use(helmet())
|
'/event',
|
||||||
app.use(nocache())
|
'/phone_code',
|
||||||
app.use(express.json({ limit: '2mb' }))
|
'/customer',
|
||||||
|
'/tx',
|
||||||
|
'/verify_promo_code',
|
||||||
|
'/graphql'
|
||||||
|
]
|
||||||
|
|
||||||
morgan.token('bytesRead', (_req, res) => res.bytesRead)
|
// middleware setup
|
||||||
morgan.token('bytesWritten', (_req, res) => res.bytesWritten)
|
app.use(addRWBytes())
|
||||||
app.use(morgan(':method :url :status :response-time ms -- :bytesRead/:bytesWritten B', { stream: logger.stream }))
|
app.use(compression({ threshold: 500 }))
|
||||||
|
app.use(helmet())
|
||||||
|
app.use(nocache())
|
||||||
|
app.use(express.json({ limit: '2mb' }))
|
||||||
|
|
||||||
app.use('/robots.txt', (req, res) => {
|
morgan.token('bytesRead', (_req, res) => res.bytesRead)
|
||||||
res.type('text/plain')
|
morgan.token('bytesWritten', (_req, res) => res.bytesWritten)
|
||||||
res.send("User-agent: *\nDisallow: /")
|
app.use(morgan(':method :url :status :response-time ms -- :bytesRead/:bytesWritten B', { stream: logger.stream }))
|
||||||
})
|
|
||||||
|
|
||||||
app.get('/', (req, res) => {
|
app.use('/robots.txt', (req, res) => {
|
||||||
res.sendStatus(404)
|
res.type('text/plain')
|
||||||
})
|
res.send("User-agent: *\nDisallow: /")
|
||||||
|
})
|
||||||
|
|
||||||
// app /pair and /ca routes
|
app.get('/', (req, res) => {
|
||||||
app.use('/', pairingRoutes)
|
res.sendStatus(404)
|
||||||
|
})
|
||||||
|
|
||||||
app.use(findOperatorId)
|
// app /pair and /ca routes
|
||||||
app.use(populateDeviceId)
|
app.use('/', pairingRoutes)
|
||||||
app.use(computeSchema)
|
|
||||||
app.use(authorize)
|
|
||||||
app.use(configRequiredRoutes, populateSettings)
|
|
||||||
app.use(filterOldRequests)
|
|
||||||
|
|
||||||
// other app routes
|
app.use(findOperatorId)
|
||||||
app.use('/graphql', recordPing)
|
app.use(populateDeviceId)
|
||||||
app.use('/poll', pollingRoutes)
|
app.use(computeSchema)
|
||||||
app.use('/terms_conditions', termsAndConditionsRoutes)
|
app.use(authorize)
|
||||||
app.use('/state', stateRoutes)
|
app.use(configRequiredRoutes, populateSettings)
|
||||||
app.use('/cashbox', cashboxRoutes)
|
app.use(filterOldRequests)
|
||||||
|
|
||||||
app.use('/network', performanceRoutes)
|
// other app routes
|
||||||
app.use('/diagnostics', diagnosticsRoutes)
|
app.use('/graphql', recordPing)
|
||||||
app.use('/failedqrscans', failedQRScansRoutes)
|
app.use('/poll', pollingRoutes)
|
||||||
|
app.use('/terms_conditions', termsAndConditionsRoutes)
|
||||||
|
app.use('/state', stateRoutes)
|
||||||
|
app.use('/cashbox', cashboxRoutes)
|
||||||
|
|
||||||
app.use('/verify_user', verifyUserRoutes)
|
app.use('/network', performanceRoutes)
|
||||||
app.use('/verify_transaction', verifyTxRoutes)
|
app.use('/diagnostics', diagnosticsRoutes)
|
||||||
app.use('/verify_promo_code', verifyPromoCodeRoutes)
|
app.use('/failedqrscans', failedQRScansRoutes)
|
||||||
|
|
||||||
// BACKWARDS_COMPATIBILITY 9.0
|
app.use('/verify_user', verifyUserRoutes)
|
||||||
// machines before 9.0 still use the phone_code route
|
app.use('/verify_transaction', verifyTxRoutes)
|
||||||
app.use('/phone_code', phoneCodeRoutes)
|
app.use('/verify_promo_code', verifyPromoCodeRoutes)
|
||||||
|
|
||||||
app.use('/customer', customerRoutes)
|
// BACKWARDS_COMPATIBILITY 9.0
|
||||||
|
// machines before 9.0 still use the phone_code route
|
||||||
|
app.use('/phone_code', phoneCodeRoutes)
|
||||||
|
|
||||||
app.use('/tx', txRoutes)
|
app.use('/customer', customerRoutes)
|
||||||
|
|
||||||
app.use('/logs', logsRoutes)
|
app.use('/tx', txRoutes)
|
||||||
app.use('/units', unitsRoutes)
|
|
||||||
|
|
||||||
app.use('/probe', probeRoutes)
|
app.use('/logs', logsRoutes)
|
||||||
|
app.use('/units', unitsRoutes)
|
||||||
|
|
||||||
graphQLServer.applyMiddleware({ app })
|
app.use('/probe', probeRoutes)
|
||||||
|
|
||||||
app.use(errorHandler)
|
await graphQLServer.start()
|
||||||
app.use((req, res) => {
|
app.use('/graphql',
|
||||||
res.status(404).json({ error: 'No such route' })
|
express.json(),
|
||||||
})
|
expressMiddleware(graphQLServer, {
|
||||||
|
context,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = { app }
|
app.use(errorHandler)
|
||||||
|
app.use((req, res) => {
|
||||||
|
res.status(404).json({ error: 'No such route' })
|
||||||
|
})
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = { loadRoutes }
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
nodejs 22
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
with import (fetchTarball {
|
|
||||||
name = "nixpkgs-194846768975b7ad2c4988bdb82572c00222c0d7";
|
|
||||||
url = https://github.com/NixOS/nixpkgs/archive/194846768975b7ad2c4988bdb82572c00222c0d7.tar.gz;
|
|
||||||
sha256 = "0snj72i9dm99jlnnmk8id8ffjnfg1k81lr7aw8d01kz3hdiraqil";
|
|
||||||
}) {};
|
|
||||||
|
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "node";
|
|
||||||
buildInputs = [
|
|
||||||
nodejs_22
|
|
||||||
openssl
|
|
||||||
python3
|
|
||||||
entr
|
|
||||||
yasm
|
|
||||||
];
|
|
||||||
shellHook = ''
|
|
||||||
export PATH="$PWD/node_modules/.bin/:$PATH"
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
|
|
@ -37,8 +37,8 @@ const MACHINE_LOGS = gql`
|
||||||
query machineLogsCsv(
|
query machineLogsCsv(
|
||||||
$deviceId: ID!
|
$deviceId: ID!
|
||||||
$limit: Int
|
$limit: Int
|
||||||
$from: Date
|
$from: DateTimeISO
|
||||||
$until: Date
|
$until: DateTimeISO
|
||||||
$timezone: String
|
$timezone: String
|
||||||
) {
|
) {
|
||||||
machineLogsCsv(
|
machineLogsCsv(
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ const DAY_OPTIONS = R.map(
|
||||||
|
|
||||||
const GET_TRANSACTIONS = gql`
|
const GET_TRANSACTIONS = gql`
|
||||||
query transactions(
|
query transactions(
|
||||||
$from: Date
|
$from: DateTimeISO
|
||||||
$until: Date
|
$until: DateTimeISO
|
||||||
$excludeTestingCustomers: Boolean
|
$excludeTestingCustomers: Boolean
|
||||||
) {
|
) {
|
||||||
transactions(
|
transactions(
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ const GET_MACHINE_LOGS_CSV = gql`
|
||||||
query MachineLogs(
|
query MachineLogs(
|
||||||
$deviceId: ID!
|
$deviceId: ID!
|
||||||
$limit: Int
|
$limit: Int
|
||||||
$from: Date
|
$from: DateTimeISO
|
||||||
$until: Date
|
$until: DateTimeISO
|
||||||
$timezone: String
|
$timezone: String
|
||||||
) {
|
) {
|
||||||
machineLogsCsv(
|
machineLogsCsv(
|
||||||
|
|
@ -52,7 +52,7 @@ const GET_MACHINE_LOGS_CSV = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const GET_MACHINE_LOGS = gql`
|
const GET_MACHINE_LOGS = gql`
|
||||||
query MachineLogs($deviceId: ID!, $limit: Int, $from: Date, $until: Date) {
|
query MachineLogs($deviceId: ID!, $limit: Int, $from: DateTimeISO, $until: DateTimeISO) {
|
||||||
machineLogs(
|
machineLogs(
|
||||||
deviceId: $deviceId
|
deviceId: $deviceId
|
||||||
limit: $limit
|
limit: $limit
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const useStyles = makeStyles(mainStyles)
|
||||||
const NUM_LOG_RESULTS = 5
|
const NUM_LOG_RESULTS = 5
|
||||||
|
|
||||||
const GET_TRANSACTIONS = gql`
|
const GET_TRANSACTIONS = gql`
|
||||||
query transactions($limit: Int, $from: Date, $until: Date, $deviceId: String) {
|
query transactions($limit: Int, $from: DateTimeISO, $until: DateTimeISO, $deviceId: String) {
|
||||||
transactions(
|
transactions(
|
||||||
limit: $limit
|
limit: $limit
|
||||||
from: $from
|
from: $from
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ const SET_CASSETTE_BILLS = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const GET_BATCHES_CSV = gql`
|
const GET_BATCHES_CSV = gql`
|
||||||
query cashboxBatchesCsv($from: Date, $until: Date, $timezone: String) {
|
query cashboxBatchesCsv($from: DateTimeISO, $until: DateTimeISO, $timezone: String) {
|
||||||
cashboxBatchesCsv(from: $from, until: $until, timezone: $timezone)
|
cashboxBatchesCsv(from: $from, until: $until, timezone: $timezone)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const SHOW_ALL = { code: 'SHOW_ALL', display: 'Show all' }
|
||||||
const NUM_LOG_RESULTS = 500
|
const NUM_LOG_RESULTS = 500
|
||||||
|
|
||||||
const GET_CSV = gql`
|
const GET_CSV = gql`
|
||||||
query ServerData($limit: Int, $from: Date, $until: Date, $timezone: String) {
|
query ServerData($limit: Int, $from: DateTimeISO, $until: DateTimeISO, $timezone: String) {
|
||||||
serverLogsCsv(
|
serverLogsCsv(
|
||||||
limit: $limit
|
limit: $limit
|
||||||
from: $from
|
from: $from
|
||||||
|
|
@ -68,7 +68,7 @@ const GET_CSV = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const GET_SERVER_DATA = gql`
|
const GET_SERVER_DATA = gql`
|
||||||
query ServerData($limit: Int, $from: Date, $until: Date) {
|
query ServerData($limit: Int, $from: DateTimeISO, $until: DateTimeISO) {
|
||||||
serverVersion
|
serverVersion
|
||||||
uptime {
|
uptime {
|
||||||
name
|
name
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ const TX_SUMMARY = gql`
|
||||||
$txId: ID!
|
$txId: ID!
|
||||||
$deviceId: ID!
|
$deviceId: ID!
|
||||||
$limit: Int
|
$limit: Int
|
||||||
$from: Date
|
$from: DateTimeISO
|
||||||
$until: Date
|
$until: DateTimeISO
|
||||||
$txClass: String
|
$txClass: String
|
||||||
$timezone: String
|
$timezone: String
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ const GET_TRANSACTIONS_CSV = gql`
|
||||||
query transactions(
|
query transactions(
|
||||||
$simplified: Boolean
|
$simplified: Boolean
|
||||||
$limit: Int
|
$limit: Int
|
||||||
$from: Date
|
$from: DateTimeISO
|
||||||
$until: Date
|
$until: DateTimeISO
|
||||||
$timezone: String
|
$timezone: String
|
||||||
$excludeTestingCustomers: Boolean
|
$excludeTestingCustomers: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
@ -69,8 +69,8 @@ const GET_TRANSACTION_FILTERS = gql`
|
||||||
const GET_TRANSACTIONS = gql`
|
const GET_TRANSACTIONS = gql`
|
||||||
query transactions(
|
query transactions(
|
||||||
$limit: Int
|
$limit: Int
|
||||||
$from: Date
|
$from: DateTimeISO
|
||||||
$until: Date
|
$until: DateTimeISO
|
||||||
$txClass: String
|
$txClass: String
|
||||||
$deviceId: String
|
$deviceId: String
|
||||||
$customerName: String
|
$customerName: String
|
||||||
|
|
|
||||||
26836
package-lock.json
generated
26836
package-lock.json
generated
File diff suppressed because it is too large
Load diff
17
package.json
17
package.json
|
|
@ -6,6 +6,7 @@
|
||||||
"license": "./LICENSE",
|
"license": "./LICENSE",
|
||||||
"author": "Lamassu (https://lamassu.is)",
|
"author": "Lamassu (https://lamassu.is)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apollo/server": "^4.11.3",
|
||||||
"@bitgo/sdk-api": "1.33.0",
|
"@bitgo/sdk-api": "1.33.0",
|
||||||
"@bitgo/sdk-coin-bch": "1.5.22",
|
"@bitgo/sdk-coin-bch": "1.5.22",
|
||||||
"@bitgo/sdk-coin-btc": "1.7.22",
|
"@bitgo/sdk-coin-btc": "1.7.22",
|
||||||
|
|
@ -14,7 +15,9 @@
|
||||||
"@bitgo/sdk-coin-zec": "1.5.22",
|
"@bitgo/sdk-coin-zec": "1.5.22",
|
||||||
"@ethereumjs/common": "^2.6.4",
|
"@ethereumjs/common": "^2.6.4",
|
||||||
"@ethereumjs/tx": "^3.5.1",
|
"@ethereumjs/tx": "^3.5.1",
|
||||||
"@graphql-tools/merge": "^6.2.5",
|
"@graphql-tools/merge": "^9.0.22",
|
||||||
|
"@graphql-tools/schema": "^10.0.21",
|
||||||
|
"@graphql-tools/utils": "^10.8.4",
|
||||||
"@haensl/subset-sum": "^3.0.5",
|
"@haensl/subset-sum": "^3.0.5",
|
||||||
"@lamassu/coins": "v1.6.1",
|
"@lamassu/coins": "v1.6.1",
|
||||||
"@simplewebauthn/server": "^3.0.0",
|
"@simplewebauthn/server": "^3.0.0",
|
||||||
|
|
@ -22,7 +25,6 @@
|
||||||
"@vonage/server-client": "1.7.0",
|
"@vonage/server-client": "1.7.0",
|
||||||
"@vonage/sms": "1.7.0",
|
"@vonage/sms": "1.7.0",
|
||||||
"@vonage/vetch": "1.5.0",
|
"@vonage/vetch": "1.5.0",
|
||||||
"apollo-server-express": "2.25.1",
|
|
||||||
"argon2": "0.28.2",
|
"argon2": "0.28.2",
|
||||||
"axios": "0.21.1",
|
"axios": "0.21.1",
|
||||||
"base-x": "3.0.9",
|
"base-x": "3.0.9",
|
||||||
|
|
@ -50,10 +52,10 @@
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"futoin-hkdf": "^1.0.2",
|
"futoin-hkdf": "^1.0.2",
|
||||||
"got": "^7.1.0",
|
"got": "^7.1.0",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^16.10.0",
|
||||||
"graphql-iso-date": "^3.6.1",
|
"graphql-scalars": "^1.24.1",
|
||||||
"graphql-type-json": "^0.3.1",
|
"graphql-tag": "^2.12.6",
|
||||||
"graphql-upload": "12.0.0",
|
"graphql-upload": "^17.0.0",
|
||||||
"helmet": "^3.8.1",
|
"helmet": "^3.8.1",
|
||||||
"inquirer": "^5.2.0",
|
"inquirer": "^5.2.0",
|
||||||
"json2csv": "^5.0.3",
|
"json2csv": "^5.0.3",
|
||||||
|
|
@ -130,8 +132,7 @@
|
||||||
"build-admin": "npm run build-admin:css && npm run build-admin:main && npm run build-admin:lamassu",
|
"build-admin": "npm run build-admin:css && npm run build-admin:main && npm run build-admin:lamassu",
|
||||||
"server": "nodemon bin/lamassu-server --mockScoring --logLevel silly",
|
"server": "nodemon bin/lamassu-server --mockScoring --logLevel silly",
|
||||||
"admin-server": "nodemon bin/lamassu-admin-server --dev --logLevel silly",
|
"admin-server": "nodemon bin/lamassu-admin-server --dev --logLevel silly",
|
||||||
"graphql-server": "nodemon bin/new-graphql-dev-insecure",
|
"watch": "concurrently \"npm:server\" \"npm:admin-server\"",
|
||||||
"watch": "concurrently \"npm:server\" \"npm:admin-server\" \"npm:graphql-server\"",
|
|
||||||
"stress-test": "cd tests/stress/ && node index.js 50 -v"
|
"stress-test": "cd tests/stress/ && node index.js 50 -v"
|
||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
|
|
|
||||||
10
shell.nix
10
shell.nix
|
|
@ -1,13 +1,13 @@
|
||||||
with import (fetchTarball {
|
with import (fetchTarball {
|
||||||
name = "8ad5e8";
|
name = "nixpkgs-194846768975b7ad2c4988bdb82572c00222c0d7";
|
||||||
url = https://github.com/NixOS/nixpkgs/archive/8ad5e8132c5dcf977e308e7bf5517cc6cc0bf7d8.tar.gz;
|
url = https://github.com/NixOS/nixpkgs/archive/194846768975b7ad2c4988bdb82572c00222c0d7.tar.gz;
|
||||||
sha256 = "17v6wigks04x1d63a2wcd7cc4z9ca6qr0f4xvw1pdw83f8a3c0nj";
|
sha256 = "0snj72i9dm99jlnnmk8id8ffjnfg1k81lr7aw8d01kz3hdiraqil";
|
||||||
}) {};
|
}) {};
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "node";
|
name = "node";
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
nodejs-14_x
|
nodejs_22
|
||||||
python3
|
python3
|
||||||
openssl
|
openssl
|
||||||
postgresql
|
postgresql
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue