mirror of
https://github.com/pockethost/pockethost.git
synced 2025-03-30 15:08:30 +00:00
dao deadlock fixes
This commit is contained in:
parent
8c31615470
commit
c32c3bcb95
@ -0,0 +1,55 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const collection = new Collection({
|
||||
"id": "h055gvw3oqi2fs0",
|
||||
"created": "2024-01-12 11:12:59.598Z",
|
||||
"updated": "2024-01-12 11:12:59.598Z",
|
||||
"name": "duplicate_emails",
|
||||
"type": "view",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "9hblghvi",
|
||||
"name": "domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "csleeffq",
|
||||
"name": "user_count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, SUBSTR(email, INSTR(email, '@')) AS domain, COUNT(*) AS user_count\nFROM users\nGROUP BY domain\nORDER BY user_count DESC;\n"
|
||||
}
|
||||
});
|
||||
|
||||
return Dao(db).saveCollection(collection);
|
||||
}, (db) => {
|
||||
const dao = new Dao(db);
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0");
|
||||
|
||||
return dao.deleteCollection(collection);
|
||||
})
|
@ -0,0 +1,92 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, SUBSTR(email, INSTR(email, '@')) AS domain, COUNT(*) AS user_count\nFROM users\n WHERE email LIKE '%+%'\nGROUP BY domain\nORDER BY user_count DESC;\n"
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("9hblghvi")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("csleeffq")
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "wwltpcoc",
|
||||
"name": "domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "yy0kkdim",
|
||||
"name": "user_count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}))
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, SUBSTR(email, INSTR(email, '@')) AS domain, COUNT(*) AS user_count\nFROM users\nGROUP BY domain\nORDER BY user_count DESC;\n"
|
||||
}
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "9hblghvi",
|
||||
"name": "domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "csleeffq",
|
||||
"name": "user_count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}))
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("wwltpcoc")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("yy0kkdim")
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
@ -0,0 +1,92 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, SUBSTR(email, INSTR(email, '@')) AS domain, COUNT(*) AS user_count\nFROM users\n WHERE email LIKE '%+%'\nORDER BY user_count DESC;\n"
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("wwltpcoc")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("yy0kkdim")
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "juo93d3a",
|
||||
"name": "domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "whrph450",
|
||||
"name": "user_count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}))
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, SUBSTR(email, INSTR(email, '@')) AS domain, COUNT(*) AS user_count\nFROM users\n WHERE email LIKE '%+%'\nGROUP BY domain\nORDER BY user_count DESC;\n"
|
||||
}
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "wwltpcoc",
|
||||
"name": "domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "yy0kkdim",
|
||||
"name": "user_count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}))
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("juo93d3a")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("whrph450")
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
@ -0,0 +1,74 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, email\nFROM users\n WHERE email LIKE '%+%'\n"
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("juo93d3a")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("whrph450")
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "92iigwzl",
|
||||
"name": "email",
|
||||
"type": "email",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"exceptDomains": null,
|
||||
"onlyDomains": null
|
||||
}
|
||||
}))
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, SUBSTR(email, INSTR(email, '@')) AS domain, COUNT(*) AS user_count\nFROM users\n WHERE email LIKE '%+%'\nORDER BY user_count DESC;\n"
|
||||
}
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "juo93d3a",
|
||||
"name": "domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "whrph450",
|
||||
"name": "user_count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}))
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("92iigwzl")
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
@ -0,0 +1,91 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT \n (ROW_NUMBER() OVER()) as id,\n SUBSTR(email, 1, INSTR(email, '@') - 1) AS email_prefix,\n SUBSTR(email, INSTR(email, '@')) AS email_domain,\n COUNT(*) AS count\nFROM \n (SELECT \n CASE \n WHEN INSTR(SUBSTR(email, 1, INSTR(email, '@') - 1), '+') > 0 \n THEN SUBSTR(email, 1, INSTR(SUBSTR(email, 1, INSTR(email, '@') - 1), '+') - 1) || SUBSTR(email, INSTR(email, '@')) \n ELSE email \n END AS email \n FROM users)\nGROUP BY \n email_prefix, email_domain;\n"
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("92iigwzl")
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "y2akvv89",
|
||||
"name": "email_prefix",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "za7mr8gw",
|
||||
"name": "email_domain",
|
||||
"type": "json",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 1
|
||||
}
|
||||
}))
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "zjwougcm",
|
||||
"name": "count",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"noDecimal": false
|
||||
}
|
||||
}))
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("h055gvw3oqi2fs0")
|
||||
|
||||
collection.options = {
|
||||
"query": "SELECT (ROW_NUMBER() OVER()) as id, email\nFROM users\n WHERE email LIKE '%+%'\n"
|
||||
}
|
||||
|
||||
// add
|
||||
collection.schema.addField(new SchemaField({
|
||||
"system": false,
|
||||
"id": "92iigwzl",
|
||||
"name": "email",
|
||||
"type": "email",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"exceptDomains": null,
|
||||
"onlyDomains": null
|
||||
}
|
||||
}))
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("y2akvv89")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("za7mr8gw")
|
||||
|
||||
// remove
|
||||
collection.schema.removeField("zjwougcm")
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
@ -7,6 +7,7 @@ routerAdd(
|
||||
'POST',
|
||||
'/api/instance',
|
||||
(c) => {
|
||||
const dao = $app.dao()
|
||||
const { audit, mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
|
||||
const log = mkLog(`POST:instance`)
|
||||
@ -46,7 +47,7 @@ routerAdd(
|
||||
|
||||
const { versions } = require(`${__hooks}/versions.js`)
|
||||
|
||||
const collection = $app.dao().findCollectionByNameOrId('instances')
|
||||
const collection = dao.findCollectionByNameOrId('instances')
|
||||
const record = new Record(collection)
|
||||
record.set('uid', authRecord.getId())
|
||||
record.set('subdomain', subdomain)
|
||||
|
@ -12,6 +12,7 @@ routerAdd(
|
||||
'DELETE',
|
||||
'/api/instance/:id',
|
||||
(c) => {
|
||||
const dao = $app.dao()
|
||||
const { audit, mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
|
||||
const log = mkLog(`DELETE:instance`)
|
||||
@ -43,7 +44,7 @@ routerAdd(
|
||||
throw new BadRequestError(`Expected authRecord here`)
|
||||
}
|
||||
|
||||
const record = $app.dao().findRecordById('instances', id)
|
||||
const record = dao.findRecordById('instances', id)
|
||||
if (!record) {
|
||||
throw new BadRequestError(`Instance ${id} not found.`)
|
||||
}
|
||||
@ -60,7 +61,7 @@ routerAdd(
|
||||
const res = $os.removeAll(path)
|
||||
log(`res`, res)
|
||||
|
||||
$app.dao().deleteRecord(record)
|
||||
dao.deleteRecord(record)
|
||||
|
||||
return c.json(200, { status: 'ok' })
|
||||
},
|
||||
|
@ -1,10 +1,11 @@
|
||||
/** Migrate version numbers */
|
||||
onAfterBootstrap((e) => {
|
||||
const dao = $app.dao()
|
||||
const { audit, mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
|
||||
const log = mkLog(`bootstrap`)
|
||||
|
||||
const records = $app.dao().findRecordsByFilter(`instances`, '1=1')
|
||||
const records = dao.findRecordsByFilter(`instances`, '1=1')
|
||||
const { versions } = require(`${__hooks}/versions.js`)
|
||||
const unrecognized = []
|
||||
records.forEach((record) => {
|
||||
@ -23,7 +24,7 @@ onAfterBootstrap((e) => {
|
||||
})()
|
||||
if (versions.includes(newVersion)) {
|
||||
record.set(`version`, newVersion)
|
||||
$app.dao().saveRecord(record)
|
||||
dao.saveRecord(record)
|
||||
} else {
|
||||
unrecognized.push(v)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/// <reference path="../types/types.d.ts" />
|
||||
|
||||
onModelAfterCreate((e) => {
|
||||
const dao = e.dao || $app.dao()
|
||||
const { audit, mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
|
||||
const log = mkLog(`instances:create:discord:notify`)
|
||||
@ -22,6 +23,9 @@ onModelAfterCreate((e) => {
|
||||
timeout: 5, // in seconds
|
||||
})
|
||||
} catch (e) {
|
||||
audit(`ERROR`, `Instance creation discord notify failed with ${e}`, { log })
|
||||
audit(`ERROR`, `Instance creation discord notify failed with ${e}`, {
|
||||
log,
|
||||
dao,
|
||||
})
|
||||
}
|
||||
}, 'instances')
|
||||
|
@ -1,4 +1,6 @@
|
||||
onModelAfterUpdate((e) => {
|
||||
const dao = e.dao || $app.dao()
|
||||
|
||||
const newModel = /** @type {models.Record} */ (e.model)
|
||||
const oldModel = newModel.originalCopy()
|
||||
|
||||
@ -18,7 +20,7 @@ onModelAfterUpdate((e) => {
|
||||
|
||||
log(`switched`)
|
||||
const uid = newModel.get(`uid`)
|
||||
const user = $app.dao().findRecordById('users', uid)
|
||||
const user = dao.findRecordById('users', uid)
|
||||
|
||||
// Bail out if the user has notifications disabled globally or for the instance
|
||||
const shouldNotify =
|
||||
@ -33,6 +35,8 @@ onModelAfterUpdate((e) => {
|
||||
const address = user.getString(`email`)
|
||||
log({ instanceId, subdomain, address })
|
||||
enqueueNotification(`email`, `maintenance_mode`, uid, {
|
||||
log,
|
||||
dao,
|
||||
message_template_vars: {
|
||||
subdomain,
|
||||
instanceId,
|
||||
|
@ -2,5 +2,6 @@
|
||||
|
||||
/** Reset instance status to idle on start */
|
||||
onAfterBootstrap((e) => {
|
||||
$app.dao().db().newQuery(`update instances set status='idle'`).execute()
|
||||
const dao = $app.dao()
|
||||
dao.db().newQuery(`update instances set status='idle'`).execute()
|
||||
})
|
||||
|
@ -14,6 +14,7 @@ routerAdd(
|
||||
'PUT',
|
||||
'/api/instance/:id',
|
||||
(c) => {
|
||||
const dao = $app.dao()
|
||||
const { mkLog, audit, removeEmptyKeys } = /** @type {Lib} */ (
|
||||
require(`${__hooks}/lib.js`)
|
||||
)
|
||||
@ -88,7 +89,7 @@ routerAdd(
|
||||
}),
|
||||
)
|
||||
|
||||
const record = $app.dao().findRecordById('instances', id)
|
||||
const record = dao.findRecordById('instances', id)
|
||||
const authRecord = /** @type {models.Record} */ (c.get('authRecord')) // empty if not authenticated as regular auth record
|
||||
log(`authRecord`, JSON.stringify(authRecord))
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
/** Validate instance version */
|
||||
onModelBeforeCreate((e) => {
|
||||
const dao = e.dao || $app.dao()
|
||||
const { versions } = require(`${__hooks}/versions.js`)
|
||||
|
||||
const version = e.model.get('version')
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
/** Validate instance version */
|
||||
onModelBeforeUpdate((e) => {
|
||||
const dao = e.dao || $app.dao()
|
||||
const { versions } = require(`${__hooks}/versions.js`)
|
||||
|
||||
const version = e.model.get('version')
|
||||
@ -22,8 +23,7 @@ onModelBeforeUpdate((e) => {
|
||||
|
||||
const inUse = (() => {
|
||||
try {
|
||||
$app
|
||||
.dao()
|
||||
dao
|
||||
.db()
|
||||
.newQuery(
|
||||
`select id from instances where cname='${cname}' and id <> '${id}'`,
|
||||
|
@ -1,6 +1,5 @@
|
||||
/** @type {Lib['audit']} */
|
||||
const audit = (event, note, context = {}) => {
|
||||
const { log = mkLog(`audit`), dao = $app.dao(), extra = {} } = context
|
||||
const audit = (event, note, { log, dao, extra = {} }) => {
|
||||
log(`AUDIT:${event}: ${note}`, extra)
|
||||
dao.saveRecord(
|
||||
new Record(dao.findCollectionByNameOrId('audit'), {
|
||||
@ -47,12 +46,12 @@ function interpolateString(template, dict) {
|
||||
}
|
||||
|
||||
/** @type {Lib['enqueueNotification']} */
|
||||
const enqueueNotification = (channel, template, user_id, context = {}) => {
|
||||
const {
|
||||
log = mkLog(`enqueueNotification`),
|
||||
message_template_vars = {},
|
||||
dao = $app.dao(),
|
||||
} = context
|
||||
const enqueueNotification = (
|
||||
channel,
|
||||
template,
|
||||
user_id,
|
||||
{ log, dao, message_template_vars = {} },
|
||||
) => {
|
||||
log({ channel, template, user_id })
|
||||
const emailTemplate = dao.findFirstRecordByData(
|
||||
'message_templates',
|
||||
@ -75,12 +74,7 @@ const enqueueNotification = (channel, template, user_id, context = {}) => {
|
||||
}
|
||||
|
||||
/** @type {Lib['processNotification']} */
|
||||
const processNotification = (notificationRec, context) => {
|
||||
const {
|
||||
log = mkLog(`processNotification`),
|
||||
test = false,
|
||||
dao = $app.dao(),
|
||||
} = context
|
||||
const processNotification = (notificationRec, { log, dao, test = false }) => {
|
||||
log({ notificationRec })
|
||||
|
||||
const channel = notificationRec.getString(`channel`)
|
||||
|
@ -1,4 +1,5 @@
|
||||
routerAdd('POST', '/api/ls', (c) => {
|
||||
const dao = $app.dao()
|
||||
const { audit, mkLog, enqueueNotification } = /** @type {Lib} */ (
|
||||
require(`${__hooks}/lib.js`)
|
||||
)
|
||||
@ -57,7 +58,7 @@ routerAdd('POST', '/api/ls', (c) => {
|
||||
|
||||
const userRec = (() => {
|
||||
try {
|
||||
return $app.dao().findFirstRecordByData('users', 'id', user_id)
|
||||
return dao.findFirstRecordByData('users', 'id', user_id)
|
||||
} catch (e) {}
|
||||
})()
|
||||
if (!userRec) {
|
||||
@ -96,15 +97,12 @@ routerAdd('POST', '/api/ls', (c) => {
|
||||
}
|
||||
applyEditionSpecifics()
|
||||
|
||||
const payment = new Record(
|
||||
$app.dao().findCollectionByNameOrId('payments'),
|
||||
{
|
||||
user: user_id,
|
||||
payment_id: `ls_${order_number}`,
|
||||
},
|
||||
)
|
||||
const payment = new Record(dao.findCollectionByNameOrId('payments'), {
|
||||
user: user_id,
|
||||
payment_id: `ls_${order_number}`,
|
||||
})
|
||||
|
||||
$app.dao().runInTransaction((txDao) => {
|
||||
dao.runInTransaction((txDao) => {
|
||||
log(`transaction started`)
|
||||
if (!userRec.getDateTime(`welcome`)) {
|
||||
enqueueNotification(`email`, `welcome`, user_id, { log, dao: txDao })
|
||||
@ -138,6 +136,7 @@ routerAdd('POST', '/api/ls', (c) => {
|
||||
log(`database updated`)
|
||||
audit(`LS`, `Order ${order_number} ${product_name} processed.`, {
|
||||
log,
|
||||
dao,
|
||||
extra: {
|
||||
email,
|
||||
user: user_id,
|
||||
@ -146,6 +145,7 @@ routerAdd('POST', '/api/ls', (c) => {
|
||||
} catch (e) {
|
||||
audit(`LS_ERR`, `${e}`, {
|
||||
log,
|
||||
dao,
|
||||
extra: {
|
||||
email,
|
||||
user: user_id,
|
||||
|
@ -7,14 +7,21 @@ routerAdd(`GET`, `api/process_single_notification`, (c) => {
|
||||
const log = mkLog(`process_single_notification`)
|
||||
log(`start`)
|
||||
|
||||
const dao = $app.dao()
|
||||
try {
|
||||
const notification = $app
|
||||
.dao()
|
||||
.findFirstRecordByData(`notifications`, `delivered`, ``)
|
||||
const notification = dao.findFirstRecordByData(
|
||||
`notifications`,
|
||||
`delivered`,
|
||||
``,
|
||||
)
|
||||
if (!notification) {
|
||||
return c.json(200, `No notifications to send`)
|
||||
}
|
||||
processNotification(notification, { log, test: !!c.queryParam(`test`) })
|
||||
processNotification(notification, {
|
||||
log,
|
||||
dao,
|
||||
test: !!c.queryParam(`test`),
|
||||
})
|
||||
} catch (e) {
|
||||
c.json(500, `${e}`)
|
||||
}
|
||||
@ -22,6 +29,7 @@ routerAdd(`GET`, `api/process_single_notification`, (c) => {
|
||||
})
|
||||
|
||||
onModelAfterCreate((e) => {
|
||||
const dao = e.dao || $app.dao()
|
||||
return
|
||||
const { processNotification, mkLog, audit } = /** @type {Lib} */ (
|
||||
require(`${__hooks}/lib.js`)
|
||||
@ -33,18 +41,19 @@ onModelAfterCreate((e) => {
|
||||
log({ notificationRec })
|
||||
|
||||
try {
|
||||
$app.dao().expandRecord(notificationRec, ['message_template'], null)
|
||||
dao.expandRecord(notificationRec, ['message_template'], null)
|
||||
|
||||
const messageTemplateRec = notificationRec.expandedOne(`message_template`)
|
||||
if (!messageTemplateRec) {
|
||||
throw new Error(`Missing message template`)
|
||||
}
|
||||
if ([`maintenance-mode`].includes(messageTemplateRec.getString(`slug`))) {
|
||||
processNotification(notificationRec, { log })
|
||||
processNotification(notificationRec, { log, dao })
|
||||
}
|
||||
} catch (e) {
|
||||
audit(`ERROR`, `${e}`, {
|
||||
log,
|
||||
dao,
|
||||
extra: {
|
||||
notification: notificationRec.getId(),
|
||||
},
|
||||
|
@ -102,6 +102,7 @@ routerAdd(
|
||||
'POST',
|
||||
'/api/signup',
|
||||
(c) => {
|
||||
const dao = $app.dao()
|
||||
const parsed = (() => {
|
||||
const rawBody = readerToString(c.request().body)
|
||||
try {
|
||||
@ -145,7 +146,7 @@ routerAdd(
|
||||
|
||||
const userExists = (() => {
|
||||
try {
|
||||
const record = $app.dao().findFirstRecordByData('users', 'email', email)
|
||||
const record = dao.findFirstRecordByData('users', 'email', email)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
@ -160,8 +161,8 @@ routerAdd(
|
||||
)
|
||||
}
|
||||
|
||||
$app.dao().runInTransaction((txDao) => {
|
||||
const usersCollection = $app.dao().findCollectionByNameOrId('users')
|
||||
dao.runInTransaction((txDao) => {
|
||||
const usersCollection = dao.findCollectionByNameOrId('users')
|
||||
const instanceCollection = $app
|
||||
.dao()
|
||||
.findCollectionByNameOrId('instances')
|
||||
|
@ -1,6 +1,7 @@
|
||||
/// <reference path="../types/types.d.ts" />
|
||||
|
||||
routerAdd('POST', '/api/sns', (c) => {
|
||||
const dao = $app.dao()
|
||||
const { mkLog, audit } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
const log = mkLog(`sns`)
|
||||
|
||||
@ -10,19 +11,18 @@ routerAdd('POST', '/api/sns', (c) => {
|
||||
email: emailAddress,
|
||||
})
|
||||
try {
|
||||
const user = $app
|
||||
.dao()
|
||||
.findFirstRecordByData('users', 'email', emailAddress)
|
||||
const user = dao.findFirstRecordByData('users', 'email', emailAddress)
|
||||
log(`user is`, user)
|
||||
extra.user = user.getId()
|
||||
user.setVerified(false)
|
||||
$app.dao().saveRecord(user)
|
||||
dao.saveRecord(user)
|
||||
audit('PBOUNCE', `User ${emailAddress} has been disabled`, {
|
||||
dao,
|
||||
extra,
|
||||
log,
|
||||
})
|
||||
} catch (e) {
|
||||
audit('PBOUNCE_ERR', `${e}`, { log, extra })
|
||||
audit('PBOUNCE_ERR', `${e}`, { dao, log, extra })
|
||||
log(`After audit`)
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,7 @@ routerAdd('POST', '/api/sns', (c) => {
|
||||
break
|
||||
default:
|
||||
audit('SNS_ERR', `Unrecognized bounce type ${bounceType}`, {
|
||||
dao,
|
||||
log,
|
||||
extra: { raw_payload: raw },
|
||||
})
|
||||
@ -82,11 +83,15 @@ routerAdd('POST', '/api/sns', (c) => {
|
||||
.findFirstRecordByData('users', 'email', emailAddress)
|
||||
log(`user is`, user)
|
||||
user.set(`unsubscribe`, true)
|
||||
$app.dao().saveRecord(user)
|
||||
dao.saveRecord(user)
|
||||
audit(
|
||||
'COMPLAINT',
|
||||
`User ${emailAddress} has been unsubscribed`,
|
||||
{ log, extra: { email: emailAddress, user: user.getId() } },
|
||||
{
|
||||
log,
|
||||
dao,
|
||||
extra: { email: emailAddress, user: user.getId() },
|
||||
},
|
||||
)
|
||||
} catch (e) {
|
||||
audit(
|
||||
@ -94,6 +99,7 @@ routerAdd('POST', '/api/sns', (c) => {
|
||||
`${emailAddress} is not in the system.`,
|
||||
{
|
||||
log,
|
||||
dao,
|
||||
extra: {
|
||||
email: emailAddress,
|
||||
},
|
||||
@ -109,6 +115,7 @@ routerAdd('POST', '/api/sns', (c) => {
|
||||
`Unrecognized notification type ${notificationType}`,
|
||||
{
|
||||
log,
|
||||
dao,
|
||||
extra: { raw_payload: raw },
|
||||
},
|
||||
)
|
||||
@ -117,6 +124,7 @@ routerAdd('POST', '/api/sns', (c) => {
|
||||
default:
|
||||
audit(`SNS_ERR`, `Message ${Type} not handled`, {
|
||||
log,
|
||||
dao,
|
||||
extra: { raw_payload: raw },
|
||||
})
|
||||
}
|
||||
|
@ -1,18 +1,19 @@
|
||||
/// <reference path="../types/types.d.ts" />
|
||||
|
||||
routerAdd('GET', '/api/unsubscribe', (c) => {
|
||||
const dao = $app.dao()
|
||||
const { mkLog, audit } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
const log = mkLog(`unsubscribe`)
|
||||
|
||||
const id = c.queryParam('e')
|
||||
|
||||
try {
|
||||
const record = $app.dao().findRecordById('users', id)
|
||||
const record = dao.findRecordById('users', id)
|
||||
record.set(`unsubscribe`, true)
|
||||
$app.dao().saveRecord(record)
|
||||
dao.saveRecord(record)
|
||||
|
||||
const email = record.getString('email')
|
||||
audit('UNSUBSCRIBE', '', { log, extra: { email, user: id } })
|
||||
audit('UNSUBSCRIBE', '', { dao, log, extra: { email, user: id } })
|
||||
|
||||
$app.newMailClient().send(
|
||||
new MailerMessage({
|
||||
@ -26,7 +27,7 @@ routerAdd('GET', '/api/unsubscribe', (c) => {
|
||||
)
|
||||
return c.html(200, `<p>${email} has been unsubscribed.`)
|
||||
} catch (e) {
|
||||
audit('UNSUBSCRIBE_ERR', `User ${id} not found`, { log })
|
||||
audit('UNSUBSCRIBE_ERR', `User ${id} not found`, { dao, log })
|
||||
return c.html(200, `<p>Looks like you're already unsubscribed.`)
|
||||
}
|
||||
})
|
||||
|
@ -9,6 +9,7 @@ routerAdd(
|
||||
'GET',
|
||||
'/api/userToken/:id',
|
||||
(c) => {
|
||||
const dao = $app.dao()
|
||||
const { mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
||||
const log = mkLog(`user-token`)
|
||||
|
||||
@ -20,7 +21,7 @@ routerAdd(
|
||||
throw new BadRequestError(`User ID is required.`)
|
||||
}
|
||||
|
||||
const rec = $app.dao().findRecordById('users', id)
|
||||
const rec = dao.findRecordById('users', id)
|
||||
const tokenKey = rec.getString('tokenKey')
|
||||
const passwordHash = rec.getString('passwordHash')
|
||||
const email = rec.getString(`email`)
|
||||
|
@ -1,6 +1,7 @@
|
||||
/// <reference path="../types/types.d.ts" />
|
||||
|
||||
onModelBeforeUpdate((e) => {
|
||||
const dao = e.dao || $app.dao()
|
||||
const newModel = /** @type {models.Record} */ (e.model)
|
||||
const oldModel = newModel.originalCopy()
|
||||
|
||||
@ -22,10 +23,10 @@ onModelBeforeUpdate((e) => {
|
||||
log(`user just became verified`)
|
||||
const uid = newModel.getId()
|
||||
|
||||
enqueueNotification(`email`, `welcome`, uid, { log })
|
||||
enqueueNotification(`email`, `welcome`, uid, { log, dao })
|
||||
newModel.set(`welcome`, new DateTime())
|
||||
} catch (e) {
|
||||
audit(`ERROR`, `${e}`, { log, extra: { user: newModel.getId() } })
|
||||
audit(`ERROR`, `${e}`, { log, dao, extra: { user: newModel.getId() } })
|
||||
throw e
|
||||
}
|
||||
}, 'users')
|
||||
|
14
src/mothership-app/pb_hooks/types/lib.d.ts
vendored
14
src/mothership-app/pb_hooks/types/lib.d.ts
vendored
@ -19,7 +19,7 @@ interface Lib {
|
||||
mkLog: (namespace: string) => Logger
|
||||
processNotification: (
|
||||
notificationRec: models.Record,
|
||||
context: Partial<{ log: Logger; test?: boolean; dao: daos.Dao }>,
|
||||
context: { log: Logger; test?: boolean; dao: daos.Dao },
|
||||
) => void
|
||||
enqueueNotification: (
|
||||
channel: 'email' | 'lemonbot',
|
||||
@ -29,27 +29,27 @@ interface Lib {
|
||||
| 'lemon_order_discord'
|
||||
| 'welcome',
|
||||
user_id: string,
|
||||
context?: Partial<{
|
||||
message_template_vars: { [_: string]: string }
|
||||
context: {
|
||||
message_template_vars?: { [_: string]: string }
|
||||
dao: daos.Dao
|
||||
log: Logger
|
||||
}>,
|
||||
},
|
||||
) => void
|
||||
|
||||
audit: (
|
||||
event: AuditEvents,
|
||||
note: string,
|
||||
context?: Partial<{
|
||||
context: {
|
||||
log: Logger
|
||||
|
||||
dao: daos.Dao
|
||||
extra: Partial<{
|
||||
extra?: Partial<{
|
||||
notification: string
|
||||
email: string
|
||||
user: string
|
||||
raw_payload: string
|
||||
}>
|
||||
}>,
|
||||
},
|
||||
) => void
|
||||
removeEmptyKeys: <T>(obj: T) => T
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user