Files
speckle-server/packages/server/modules/activitystream/services/index.js
T
Gergő Jedlicska 3d6653f73b hotfix/2.9.2 (#1175)
* 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>
2022-11-09 13:23:32 +01:00

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)
}
}