Skip to content
Draft
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
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:18-alpine as base
FROM node:22-alpine AS base

WORKDIR /home/node/app

Expand All @@ -10,7 +10,7 @@ COPY . .

RUN mkdir -p files

FROM base as production
FROM base AS production

ENV NODE_PATH=./build
ENV NODE_CONFIG_DIR=/home/node/app/config
Expand Down
11 changes: 10 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SafeServer } from './server';
import mongoose from 'mongoose';
// import { Record } from '@models';
import pullJobScheduler from './server/pullJobScheduler';
import customNotificationScheduler from './server/customNotificationScheduler';
import { startDatabase } from './server/database';
Expand Down Expand Up @@ -45,8 +46,16 @@ const launchServer = async () => {
};

startDatabase();
mongoose.connection.once('open', () => {
mongoose.connection.once('open', async () => {
logger.log({ level: 'info', message: '📶 Connected to database' });
// try {
// const collection = mongoose.connection.db.collection('records');
// await collection.dropIndex('incrementalId_1_resource_1').catch(() => {});
// await Record.syncIndexes();
// logger.info('✅ Record indexes synced');
// } catch (e) {
// logger.warn(`⚠️ Could not auto-sync Record indexes: ${e?.message || e}`);
// }
launchServer();
// subscriberSafe();
pullJobScheduler();
Expand Down
2 changes: 1 addition & 1 deletion src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export * from './template.model';
export * from './distributionList.model';
export * from './customNotification.model';
export * from './layer.model';
export * from './draftRecord.model';
// export * from './draftRecord.model';
export * from './emailNotification.model';
export * from './activityLog.model';
export * from './emailDistributionList.model';
17 changes: 15 additions & 2 deletions src/models/record.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface Record extends AccessibleFieldsDocument {
createdAt: Date;
modifiedAt: Date;
archived: boolean;
draft: boolean;
data: any;
versions: any;
permissions: {
Expand All @@ -45,7 +46,7 @@ const recordSchema = new Schema<Record>(
{
incrementalId: {
type: String,
required: true,
required: false,
},
form: {
type: mongoose.Schema.Types.ObjectId,
Expand Down Expand Up @@ -97,6 +98,10 @@ const recordSchema = new Schema<Record>(
type: Boolean,
default: false,
},
draft: {
type: Boolean,
default: false,
},
data: {
type: mongoose.Schema.Types.Mixed,
required: true,
Expand All @@ -112,14 +117,22 @@ const recordSchema = new Schema<Record>(
);
recordSchema.index(
{ incrementalId: 1, resource: 1 },
{ unique: true, partialFilterExpression: { resource: { $exists: true } } }
{
unique: true,
partialFilterExpression: {
resource: { $exists: true },
draft: false,
incrementalId: { $exists: true },
},
}
);

recordSchema.index({ '$**': 'text' });
recordSchema.index({ 'data.$**': 1 });

recordSchema.index({ archived: 1, form: 1, resource: 1, createdAt: 1 });
recordSchema.index({ resource: 1, archived: 1 });
recordSchema.index({ draft: 1, form: 1, resource: 1, createdAt: 1 });
recordSchema.index({ createdAt: 1 });
recordSchema.index({ form: 1 });

Expand Down
3 changes: 3 additions & 0 deletions src/routes/download/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ router.get('/form/records/:id', async (req, res) => {
const filter = {
form: req.params.id,
archived: { $ne: true },
draft: { $ne: true },
...Record.find(accessibleBy(formAbility, 'read').Record).getFilter(),
};
const columns = await getColumns(
Expand Down Expand Up @@ -187,6 +188,7 @@ router.get('/form/records/:id/history', async (req, res) => {
const record: Record = await Record.findOne({
_id: req.params.id,
archived: { $ne: true },
draft: { $ne: true },
})
.populate({
path: 'versions',
Expand Down Expand Up @@ -316,6 +318,7 @@ router.get('/resource/records/:id', async (req, res) => {
records = await Record.find({
resource: req.params.id,
archived: { $ne: true },
draft: { $ne: true },
});
}
const rows = await getRows(columns, records);
Expand Down
1 change: 1 addition & 0 deletions src/routes/file/file.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export default class FileController extends BaseController {
const associatedRecord = await Record.findOne({
resource: new Types.ObjectId(String(resourceId)),
archived: { $ne: true },
draft: { $ne: true },
$or: fileFieldQueries,
}).select('_id');

Expand Down
49 changes: 31 additions & 18 deletions src/schema/mutation/addRecord.mutation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { GraphQLID, GraphQLNonNull, GraphQLError } from 'graphql';
import {
GraphQLID,
GraphQLNonNull,
GraphQLError,
GraphQLBoolean,
} from 'graphql';
import GraphQLJSON from 'graphql-type-json';
import { RecordType } from '../types';
import { Form, Record, Notification, Channel } from '@models';
Expand All @@ -15,6 +20,7 @@ import { Context } from '@server/apollo/context';
type AddRecordArgs = {
form?: string | Types.ObjectId;
data: any;
draft?: boolean;
};

/**
Expand All @@ -27,6 +33,7 @@ export default {
args: {
form: { type: GraphQLID },
data: { type: new GraphQLNonNull(GraphQLJSON) },
draft: { type: GraphQLBoolean },
},
async resolve(parent, args: AddRecordArgs, context: Context) {
graphQLAuthCheck(context);
Expand All @@ -48,6 +55,7 @@ export default {

// Check unicity of record
if (
!args.draft &&
form.permissions.recordsUnicity &&
form.permissions.recordsUnicity.length > 0 &&
form.permissions.recordsUnicity[0].role
Expand All @@ -60,7 +68,7 @@ export default {
if (unicityFilters.length > 0) {
const uniqueRecordAlreadyExists = await Record.exists({
$and: [
{ form: form._id, archived: { $ne: true } },
{ form: form._id, archived: { $ne: true }, draft: { $ne: true } },
{ $or: unicityFilters },
],
});
Expand All @@ -75,9 +83,9 @@ export default {
// Create the record instance
transformRecord(args.data, form.fields);
const record = new Record({
incrementalId: await getNextId(
String(form.resource ? form.resource : args.form)
),
incrementalId: args.draft
? null
: await getNextId(String(form.resource ? form.resource : args.form)),
form: args.form,
//createdAt: new Date(),
//modifiedAt: new Date(),
Expand Down Expand Up @@ -109,26 +117,31 @@ export default {
_id: form._id,
name: form.name,
},
draft: args.draft || false,
});
// Update the createdBy property if we pass some owner data
const ownership = getOwnership(form.fields, args.data);
if (ownership) {
record.createdBy = { ...record.createdBy, ...ownership };
}
// send notifications to channel
const channel = await Channel.findOne({ form: form._id });
if (channel) {
const notification = new Notification({
action: `New record - ${form.name}`,
content: record,
//createdAt: new Date(),
channel: channel.id,
seenBy: [],
});
await notification.save();
const publisher = await pubsub();
publisher.publish(channel.id, { notification });

// send notifications to channel (skip for draft records)
if (!args.draft) {
const channel = await Channel.findOne({ form: form._id });
if (channel) {
const notification = new Notification({
action: `New record - ${form.name}`,
content: record,
//createdAt: new Date(),
channel: channel.id,
seenBy: [],
});
await notification.save();
const publisher = await pubsub();
publisher.publish(channel.id, { notification });
}
}

await record.save();
return record;
} catch (err) {
Expand Down
6 changes: 3 additions & 3 deletions src/schema/mutation/deleteDraftRecord.mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { GraphQLNonNull, GraphQLID, GraphQLError } from 'graphql';
import { logger } from '@services/logger.service';
import { graphQLAuthCheck } from '@schema/shared';
import { Context } from '@server/apollo/context';
import { DraftRecordType } from '../types';
import { DraftRecord } from '@models';
import { DraftRecordType } from '../types/draftRecord.type';
import { DraftRecord } from '../../models/draftRecord.model';
import { Types } from 'mongoose';

/** Arguments for the deleteRecord mutation */
Expand All @@ -24,7 +24,7 @@ export default {
graphQLAuthCheck(context);
try {
// Get draft Record and associated form
const draftRecord = await DraftRecord.findById(args.id);
const draftRecord = DraftRecord.findById(args.id);
return await DraftRecord.findByIdAndDelete(draftRecord._id);
} catch (err) {
logger.error(err.message, { stack: err.stack });
Expand Down
2 changes: 1 addition & 1 deletion src/schema/mutation/editDraftRecord.mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default {
const draftRecord = DraftRecord.findByIdAndUpdate(args.id, update, {
new: true,
});
return await draftRecord;
return draftRecord;
} catch (err) {
logger.error(err.message, { stack: err.stack });
if (err instanceof GraphQLError) {
Expand Down
Loading