Skip to content

Commit

Permalink
Merge pull request #973 from ReliefApplications/2.x.x
Browse files Browse the repository at this point in the history
2.x.x
  • Loading branch information
AntoineRelief authored Feb 7, 2024
2 parents 3fe9796 + 45f1c89 commit db1a265
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 37 deletions.
61 changes: 61 additions & 0 deletions .devops/dev-CD.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- dev

pool:
vmImage: ubuntu-latest

steps:
- task: NodeTool@0
inputs:
versionSpec: '18.x'
displayName: 'Install Node.js'

- script: |
npm install
npm run build
displayName: 'npm install and build'

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/build'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: true

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/node_modules'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/config'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/package.json'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/package-lock.json'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false
61 changes: 61 additions & 0 deletions .devops/sit-CD.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- stage

pool:
vmImage: ubuntu-latest

steps:
- task: NodeTool@0
inputs:
versionSpec: '18.x'
displayName: 'Install Node.js'

- script: |
npm install
npm run build
displayName: 'npm install and build'

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/build'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: true

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/node_modules'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/config'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/package.json'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false

- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/package-lock.json'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/sit/api/$(Build.BuildId).zip'
replaceExistingArchive: false
2 changes: 2 additions & 0 deletions src/utils/schema/resolvers/Entity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ export const getEntityResolver = (
return Object.assign(resolvers, {
[field.name]: getReferenceDataResolver(field, referenceData),
});
} else {
return resolvers;
}
}, {});

Expand Down
35 changes: 24 additions & 11 deletions src/utils/schema/resolvers/Query/all.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GraphQLError } from 'graphql';
import { Form, Record, ReferenceData, User } from '@models';
import { Record, ReferenceData, User } from '@models';
import extendAbilityForRecords from '@security/extendAbilityForRecords';
import { decodeCursor, encodeCursor } from '@schema/types';
import getReversedFields from '../../introspection/getReversedFields';
Expand All @@ -19,10 +19,15 @@ import checkPageSize from '@utils/schema/errors/checkPageSize.util';
import { flatten, get, isArray, set } from 'lodash';
import { accessibleBy } from '@casl/mongoose';
import { graphQLAuthCheck } from '@schema/shared';
import NodeCache from 'node-cache';
import { AppAbility } from '@security/defineUserAbility';

/** Default number for items to get */
const DEFAULT_FIRST = 25;

/** Ability Cache, based on user id, time to live: 5min */
const abilityCache = new NodeCache({ stdTTL: 60 * 5, checkperiod: 60 });

// todo: improve by only keeping used fields in the $project stage
/**
* Project aggregation.
Expand Down Expand Up @@ -233,6 +238,7 @@ export default (entityName: string, fieldsByName: any, idsByName: any) =>
checkPageSize(first);
try {
const user: User = context.user;
const userId = user._id.toString();
// Id of the form / resource
const id = idsByName[entityName];
// List of form / resource fields
Expand Down Expand Up @@ -407,16 +413,23 @@ export default (entityName: string, fieldsByName: any, idsByName: any) =>
};

// Additional filter from the user permissions
const form = await Form.findOne({
$or: [{ _id: id }, { resource: id, core: true }],
})
.select('_id permissions fields')
.populate({ path: 'resource', model: 'Resource' });
const ability = await extendAbilityForRecords(user, form);
set(context, 'user.ability', ability);
const permissionFilters = Record.find(
accessibleBy(ability, 'read').Record
).getFilter();
let permissionFilters;
// Try to get ability from cache
let ability = abilityCache.get<AppAbility>(userId);
if (!ability) {
// If not available, build ability
ability = await extendAbilityForRecords(user);
set(context, 'user.ability', ability);
permissionFilters = Record.find(
accessibleBy(ability, 'read').Record
).getFilter();
// And cache it
abilityCache.set(userId, ability);
} else {
permissionFilters = Record.find(
accessibleBy(ability, 'read').Record
).getFilter();
}

// Finally putting all filters together
const filters = {
Expand Down
65 changes: 39 additions & 26 deletions src/utils/schema/resolvers/Query/getSearchFilter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// import { isNumber } from 'lodash';
import mongoose from 'mongoose';
// import { MULTISELECT_TYPES, DATE_TYPES } from '@const/fieldTypes';

/** The default fields */
const DEFAULT_FIELDS = [
Expand Down Expand Up @@ -31,7 +29,7 @@ const DEFAULT_FIELDS = [
];

/**
*
* Wild card search interface.
*/
interface WildcardSearch {
wildcard: {
Expand All @@ -46,7 +44,7 @@ interface WildcardSearch {
}

/**
*
* Search stage interface.
*/
interface SearchStage {
$search: {
Expand All @@ -57,18 +55,6 @@ interface SearchStage {
};
}

/**
*
*/
let searchStage: SearchStage = {
$search: {
index: 'data_keyword_lowercase',
compound: {
must: [],
},
},
};

/** Names of the default fields */
// eslint-disable-next-line @typescript-eslint/naming-convention
export const FLAT_DEFAULT_FIELDS = DEFAULT_FIELDS.map((x) => x.name);
Expand All @@ -93,26 +79,28 @@ export const extractFilterFields = (filter: any): string[] => {
return fields;
};

let searchStageUsed = false;

/**
* Transforms query filter into mongo filter.
*
* @param filter filter to transform to mongo filter.
* @param fields list of structure fields
* @param context request context
* @param prefix prefix to access field
* @param searchStage Search stage being built
* @returns Mongo filter.
*/
const buildMongoFilter = (
filter: any,
fields: any[],
context: any,
prefix = ''
prefix = '',
searchStage
): any => {
if (filter.filters) {
const filters = filter.filters
.map((x: any) => buildMongoFilter(x, fields, context, prefix))
.map((x: any) =>
buildMongoFilter(x, fields, context, prefix, searchStage)
)
.filter((x) => x);
if (filters.length > 0) {
switch (filter.logic) {
Expand Down Expand Up @@ -253,7 +241,6 @@ const buildMongoFilter = (
allowAnalyzedField: true,
},
});
searchStageUsed = true;
return;
}
} else {
Expand All @@ -264,11 +251,36 @@ const buildMongoFilter = (
allowAnalyzedField: true,
},
});
searchStageUsed = true;
return;
}
}
}
case 'startswith': {
if (fieldName.includes('id')) {
return;
}
searchStage.$search.compound.must.unshift({
wildcard: {
query: `${value}*`,
path: fieldName,
allowAnalyzedField: true,
},
});
return;
}
case 'endswith': {
if (fieldName.includes('id')) {
return;
}
searchStage.$search.compound.must.unshift({
wildcard: {
query: `*${value}`,
path: fieldName,
allowAnalyzedField: true,
},
});
return;
}
default: {
return;
}
Expand All @@ -295,8 +307,8 @@ export default (
context?: any,
prefix = 'data.'
) => {
searchStageUsed = false;
searchStage = {
// Default search stage
const searchStage: SearchStage = {
$search: {
index: 'keyword_lowercase',
compound: {
Expand All @@ -305,9 +317,10 @@ export default (
},
};
const expandedFields = fields.concat(DEFAULT_FIELDS);
buildMongoFilter(filter, expandedFields, context, prefix);
buildMongoFilter(filter, expandedFields, context, prefix, searchStage);

if (searchStageUsed) {
// If some rules are defined, return search stage, to be added to main pipeline
if (searchStage.$search.compound.must.length > 0) {
return searchStage;
}
return;
Expand Down

0 comments on commit db1a265

Please sign in to comment.