3d6653f73b
* Update to new specklepy (#1173) * Publish images for all branches but limit tagging * only tag 'latest' and '2' when 'SHOULD_PUBLISH' variable is 'true' * Publishing helm chart should check for `SHOULD_PUBLISH` * Move blocking step to publish-helm chart, and allow images to be published * Pin python requirements and bump to latest versions * Fix EOL whitespace * use valid version for psycopg2-binary (the clue is in the 2!) * fix(fileimports): add exception printing to file imports * fix(fileimports): bump specklepy version move to a specklepy version that contains a fix for send without writing to disk Co-authored-by: Iain Sproat <68657+iainsproat@users.noreply.github.com> * Fixes liveness and readiness checks to prevent CSRF error message (#1169) - provides content-type header - check that status code is 200 * Fixes broken helm template by adding quotation marks around liveness probe command (#1171) * fix(server activities): make sure the stream events are properly dispatched * feat(server webhooks): add scheduled orphaned webhook cleanup * test(server webhooks): add test to webhook cleanup service * feat(server webhooks): drop foreign key reference for webhooks schema to streams * refactor(server req context): refactor req context to have the ip attribute for all requests * feat(server objects rest api): add ratelimits to objects rest api endpoints * fix(server rest api): properly handle returning 419 Co-authored-by: Iain Sproat <68657+iainsproat@users.noreply.github.com>
191 lines
5.5 KiB
JavaScript
191 lines
5.5 KiB
JavaScript
'use strict'
|
|
|
|
const knex = require('@/db/knex')
|
|
|
|
const { dispatchStreamEvent } = require('../../webhooks/services/webhooks')
|
|
const StreamActivity = () => knex('stream_activity')
|
|
const StreamAcl = () => knex('stream_acl')
|
|
|
|
module.exports = {
|
|
/**
|
|
* @param {Omit<import('@/modules/activitystream/helpers/types').StreamActivityRecord, "time">} param0
|
|
*/
|
|
async saveActivity({
|
|
streamId,
|
|
resourceType,
|
|
resourceId,
|
|
actionType,
|
|
userId,
|
|
info,
|
|
message
|
|
}) {
|
|
const dbObject = {
|
|
streamId, // abc
|
|
resourceType, // "commit"
|
|
resourceId, // commit id
|
|
actionType, // "commit_receive"
|
|
userId, // populated by the api
|
|
info: JSON.stringify(info), // can be anything with conventions! (TBD)
|
|
message // something human understandable for frontend purposes mostly
|
|
}
|
|
await StreamActivity().insert(dbObject)
|
|
if (streamId) {
|
|
const webhooksPayload = {
|
|
streamId,
|
|
userId,
|
|
activityMessage: message,
|
|
event: {
|
|
// eslint-disable-next-line camelcase
|
|
event_name: actionType,
|
|
data: info
|
|
}
|
|
}
|
|
await dispatchStreamEvent({
|
|
streamId,
|
|
event: actionType,
|
|
eventPayload: webhooksPayload
|
|
})
|
|
}
|
|
},
|
|
|
|
async getStreamActivity({ streamId, actionType, after, before, cursor, limit }) {
|
|
if (!limit) {
|
|
limit = 200
|
|
}
|
|
|
|
const dbQuery = StreamActivity().where({ streamId })
|
|
if (actionType) dbQuery.andWhere({ actionType })
|
|
if (after) dbQuery.andWhere('time', '>', after)
|
|
if (before) dbQuery.andWhere('time', '<', before)
|
|
if (cursor) dbQuery.andWhere('time', '<', cursor)
|
|
dbQuery.orderBy('time', 'desc').limit(limit)
|
|
|
|
const results = await dbQuery.select('*')
|
|
|
|
return {
|
|
items: results,
|
|
cursor: results.length > 0 ? results[results.length - 1].time.toISOString() : null
|
|
}
|
|
},
|
|
|
|
async getUserActivity({ userId, actionType, after, before, cursor, limit }) {
|
|
if (!limit) {
|
|
limit = 200
|
|
}
|
|
|
|
const dbQuery = StreamActivity().where({ userId })
|
|
if (actionType) dbQuery.andWhere({ actionType })
|
|
if (after) dbQuery.andWhere('time', '>', after)
|
|
if (before) dbQuery.andWhere('time', '<', before)
|
|
if (cursor) dbQuery.andWhere('time', '<', cursor)
|
|
dbQuery.orderBy('time', 'desc').limit(limit)
|
|
|
|
const results = await dbQuery.select('*')
|
|
return {
|
|
items: results,
|
|
cursor: results.length > 0 ? results[results.length - 1].time.toISOString() : null
|
|
}
|
|
},
|
|
|
|
async getResourceActivity({
|
|
resourceType,
|
|
resourceId,
|
|
actionType,
|
|
after,
|
|
before,
|
|
cursor,
|
|
limit
|
|
}) {
|
|
if (!limit) {
|
|
limit = 200
|
|
}
|
|
|
|
const dbQuery = StreamActivity().where({ resourceType, resourceId })
|
|
if (actionType) dbQuery.andWhere({ actionType })
|
|
if (after) dbQuery.andWhere('time', '>', after)
|
|
if (before) dbQuery.andWhere('time', '<', before)
|
|
if (cursor) dbQuery.andWhere('time', '<', cursor)
|
|
dbQuery.orderBy('time', 'desc').limit(limit)
|
|
|
|
const results = await dbQuery.select('*')
|
|
return {
|
|
items: results,
|
|
cursor: results.length > 0 ? results[results.length - 1].time.toISOString() : null
|
|
}
|
|
},
|
|
|
|
async getUserTimeline({ userId, after, before, cursor, limit }) {
|
|
if (!limit) {
|
|
limit = 200
|
|
}
|
|
|
|
let sqlFilters = ''
|
|
const sqlVariables = []
|
|
if (after) {
|
|
sqlFilters += ' AND time > ?'
|
|
sqlVariables.push(after)
|
|
}
|
|
if (before || cursor) {
|
|
sqlFilters += ' AND time < ?'
|
|
sqlVariables.push(before || cursor)
|
|
}
|
|
|
|
const dbRawQuery = `
|
|
SELECT act.*
|
|
FROM stream_acl acl
|
|
INNER JOIN stream_activity act ON acl."resourceId" = act."streamId"
|
|
WHERE acl."userId" = ? ${sqlFilters}
|
|
ORDER BY time DESC
|
|
LIMIT ?
|
|
`
|
|
|
|
sqlVariables.unshift(userId)
|
|
sqlVariables.push(limit)
|
|
const results = (await knex.raw(dbRawQuery, sqlVariables)).rows
|
|
return {
|
|
items: results,
|
|
cursor: results.length > 0 ? results[results.length - 1].time.toISOString() : null
|
|
}
|
|
},
|
|
|
|
async getActivityCountByResourceId({ resourceId, actionType, after, before }) {
|
|
const query = StreamActivity().count().where({ resourceId })
|
|
if (actionType) query.andWhere({ actionType })
|
|
if (after) query.andWhere('time', '>', after)
|
|
if (before) query.andWhere('time', '<', before)
|
|
const [res] = await query
|
|
return parseInt(res.count)
|
|
},
|
|
|
|
async getActivityCountByStreamId({ streamId, actionType, after, before }) {
|
|
const query = StreamActivity().count().where({ streamId })
|
|
if (actionType) query.andWhere({ actionType })
|
|
if (after) query.andWhere('time', '>', after)
|
|
if (before) query.andWhere('time', '<', before)
|
|
const [res] = await query
|
|
return parseInt(res.count)
|
|
},
|
|
|
|
async getActivityCountByUserId({ userId, actionType, after, before }) {
|
|
const query = StreamActivity().count().where({ userId })
|
|
if (actionType) query.andWhere({ actionType })
|
|
if (after) query.andWhere('time', '>', after)
|
|
if (before) query.andWhere('time', '<', before)
|
|
const [res] = await query
|
|
return parseInt(res.count)
|
|
},
|
|
|
|
async getTimelineCount({ userId, after, before }) {
|
|
const query = StreamAcl()
|
|
.count()
|
|
.innerJoin('stream_activity', {
|
|
'stream_acl.resourceId': 'stream_activity.streamId'
|
|
})
|
|
.where({ 'stream_acl.userId': userId })
|
|
if (after) query.andWhere('stream_activity.time', '>', after)
|
|
if (before) query.andWhere('stream_activity.time', '<', before)
|
|
const [res] = await query
|
|
return parseInt(res.count)
|
|
}
|
|
}
|