Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,13 @@ module.exports = {
'require-jsdoc': 'warn',
'no-shadow': 'warn',
'no-unused-expressions': 'warn'
}
},
overrides: [
{
files: ['*.js'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off'
}
}
]
};
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hawk.api",
"version": "1.1.15",
"version": "1.1.16",
"main": "index.ts",
"license": "UNLICENSED",
"scripts": {
Expand Down Expand Up @@ -37,7 +37,7 @@
"@graphql-tools/schema": "^8.5.1",
"@graphql-tools/utils": "^8.9.0",
"@hawk.so/nodejs": "^3.1.1",
"@hawk.so/types": "^0.1.26",
"@hawk.so/types": "^0.1.28",
"@types/amqp-connection-manager": "^2.0.4",
"@types/bson": "^4.0.5",
"@types/debug": "^4.1.5",
Expand All @@ -49,6 +49,7 @@
"@types/node": "^16.11.46",
"@types/node-fetch": "^2.5.4",
"@types/uuid": "^8.3.4",
"@types/safe-regex": "^1.1.6",
"amqp-connection-manager": "^3.1.0",
"amqplib": "^0.5.5",
"apollo-server-express": "^3.10.0",
Expand All @@ -73,6 +74,7 @@
"mime-types": "^2.1.25",
"mongodb": "^3.7.3",
"ts-node-dev": "^2.0.0",
"uuid": "^8.3.2"
"uuid": "^8.3.2",
"safe-regex": "^2.1.0"
}
}
174 changes: 123 additions & 51 deletions src/models/project.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,9 @@
import { Collection, ObjectId } from 'mongodb';
import AbstractModel from './abstractModel';
import { NotificationsChannelsDBScheme } from '../types/notification-channels';
import { ProjectDBScheme } from '@hawk.so/types';
import { ProjectDBScheme, ProjectNotificationsRuleDBScheme, ProjectEventGroupingPatternsDBScheme } from '@hawk.so/types';
import { v4 as uuid } from 'uuid';

/**
* This structure represents a single rule of notifications settings
*/
export interface ProjectNotificationsRuleDBScheme {
/**
* Id of Rule
*/
_id: ObjectId;

/**
* Allows to disable rule without removing
*/
isEnabled: boolean;

/**
* Creator of the rule
*/
uidAdded: ObjectId;

/**
* Receive type: 'SEEN_MORE' or 'ONLY_NEW'
*/
whatToReceive: ReceiveTypes;

/**
* Only those which contains passed words
*/
including: string[];

/**
* Skip those which contains passed words
*/
excluding: string[];

/**
* Available channels to receive
*/
channels: NotificationsChannelsDBScheme;

/**
* If this number of events is reached in the eventThresholdPeriod, the rule will be triggered
*/
threshold?: number;

/**
* Size of period (in milliseconds) to count events to compare to rule threshold
*/
thresholdPeriod?: number;
}

/**
* Available options of 'What to receive'
*/
Expand Down Expand Up @@ -159,6 +109,36 @@ interface UpdateProjectNotificationsRulePayload {
thresholdPeriod?: number;
}

/**
* Payload for creating new project pattern
*/
type CreateProjectPatternPayload = {
pattern: string;
};

/**
* Payload for updating project patterns
* It will just rewrite the whole lits of patterns
*/
type UpdateProjectPatternPayload = {
/**
* Id of the pattern to be updated
*/
id: string;

/**
* New pattern string
*/
pattern: string;
};

type RemoveProjectPatternPayload = {
/**
* Id of the pattern to be removed
*/
id: string;
}

/**
* Project model to work with project data
*/
Expand Down Expand Up @@ -208,6 +188,11 @@ export default class ProjectModel extends AbstractModel<ProjectDBScheme> impleme
*/
public notifications!: ProjectNotificationsRuleDBScheme[];

/**
* Project events grouping pattern list
*/
public eventGroupingPatterns!: ProjectEventGroupingPatternsDBScheme[];

/**
* Model's collection
*/
Expand Down Expand Up @@ -282,6 +267,93 @@ export default class ProjectModel extends AbstractModel<ProjectDBScheme> impleme
return rule;
}

/**
* Method for appending patterns list with new pattern
* @param payload - object that contains pattern string
* @returns - pattern, that has been added
*/
public async createProjectEventGroupingPattern(payload: CreateProjectPatternPayload): Promise<ProjectEventGroupingPatternsDBScheme> {
const pattern: ProjectEventGroupingPatternsDBScheme = {
_id: new ObjectId(),
pattern: payload.pattern,
};

await this.collection.updateOne({
_id: this._id,
},
{
$push: {
eventGroupingPatterns: {
$each: [ pattern ],
$position: 0,
},
},
});

return pattern;
}

/**
* Method that rewrites pattern by id
* @param payload - object that contains id of the pattern to be updated and new pattern string
* @returns - updated pattern
*/
public async updateProjectEventGroupingPattern(payload: UpdateProjectPatternPayload): Promise<ProjectEventGroupingPatternsDBScheme> {
const udpatedPattern = {
_id: new ObjectId(payload.id),
pattern: payload.pattern,
};

await this.collection.updateOne({
_id: this._id,
'eventGroupingPatterns._id': new ObjectId(udpatedPattern._id),
},
{
$set: { 'eventGroupingPatterns.$.pattern': udpatedPattern.pattern },
});

return udpatedPattern;
}

/**
* Method that removes pattern by its id
* @param payload - object that contains id of the pattern to be removed
*/
public async removeProjectEventGroupingPattern(payload: RemoveProjectPatternPayload): Promise<ProjectEventGroupingPatternsDBScheme> {
const project = await this.collection.findOne({
_id: this._id,
});

if (!project) {
throw new Error('Project with such id does not exist');
}

const patternList = await this.collection.findOne(
{
_id: this._id,
'eventGroupingPatterns._id': new ObjectId(payload.id),
},
{ projection: { 'eventGroupingPatterns.$': 1 } }
);

const deletedPattern = patternList?.eventGroupingPatterns[0];

if (deletedPattern === undefined) {
throw new Error('Pattern with such id does not exist');
}

await this.collection.updateOne(
{
_id: new ObjectId(this._id),
},
{
$pull: { eventGroupingPatterns: { _id: new ObjectId(payload.id) } },
}
);

return deletedPattern;
}

/**
* Updates notifications rule in project
* @param payload - data for updating
Expand Down
2 changes: 2 additions & 0 deletions src/resolvers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const project = require('./project');
const event = require('./event');
const plans = require('./plans').default;
const projectNotifications = require('./projectNotifications').default;
const projectPatterns = require('./projectPatterns').default;
const userNotifications = require('./userNotifications').default;
const billing = require('./billingNew').default;
const EncodedJSON = require('./encodedJSON').default;
Expand Down Expand Up @@ -71,6 +72,7 @@ const resolvers = [
project,
event,
projectNotifications,
projectPatterns,
userNotifications,
plans,
billing,
Expand Down
5 changes: 3 additions & 2 deletions src/resolvers/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const ProjectModel = require('../models/project').default;
const EVENTS_GROUP_HASH_INDEX_NAME = 'groupHashUnique';
const REPETITIONS_GROUP_HASH_INDEX_NAME = 'groupHash_hashed';
const REPETITIONS_USER_ID_INDEX_NAME = 'userId';
const MAX_SEARCH_QUERY_LENGTH = 50;

/**
* See all types and fields here {@see ../typeDefs/project.graphql}
Expand Down Expand Up @@ -310,8 +311,8 @@ module.exports = {
*/
async recentEvents(project, { limit, skip, sort, filters, search }) {
if (search) {
if (search.length > 100) {
throw new UserInputError('Search query is too long. Maximum length is 100 characters');
if (search.length > MAX_SEARCH_QUERY_LENGTH) {
search = search.slice(0, MAX_SEARCH_QUERY_LENGTH);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/resolvers/projectNotifications.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {
ProjectNotificationsRuleDBScheme,
ReceiveTypes
} from '../models/project';
import { ProjectNotificationsRuleDBScheme } from '@hawk.so/types';
import { ResolverContextWithUser } from '../types/graphql';
import { ApolloError, UserInputError } from 'apollo-server-express';
import { NotificationsChannelsDBScheme, NotificationsChannelSettingsDBScheme } from '../types/notification-channels';
import { NotificationsChannelsDBScheme } from '../types/notification-channels';

/**
* Mutation payload for creating notifications rule from GraphQL Schema
Expand Down Expand Up @@ -223,7 +223,7 @@ export default {
},

/**
* Toggles isEnabled field in in project notifications rule
* Toggles isEnabled field in project notifications rule
* @param _obj - parent object
* @param user - current authorized user {@see ../index.js}
* @param factories - factories for working with models
Expand Down
Loading
Loading