Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: return invalid document in error message #248

Merged
merged 46 commits into from
Jan 23, 2023
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
37ab522
fix: discard undefined security provider
y-lakhdar Dec 14, 2022
854d854
create permissionSetBuilder
y-lakhdar Dec 14, 2022
383306d
update comments
y-lakhdar Dec 14, 2022
1ff4898
add additional method to KnwonKey class
y-lakhdar Dec 14, 2022
fb95925
use `PermissionSetBuilder` class
y-lakhdar Dec 14, 2022
57dd8c1
unit tests
y-lakhdar Dec 14, 2022
d9a121e
lint
y-lakhdar Dec 14, 2022
7191904
make allowed and denied keys optional
y-lakhdar Dec 14, 2022
3945eee
use existing interfaces from platform-client
y-lakhdar Dec 16, 2022
97a1a19
parse permissions
y-lakhdar Dec 16, 2022
e1fabe6
support interface as records
y-lakhdar Dec 16, 2022
5369881
move parsePermission.spec.ts to future PR
y-lakhdar Dec 16, 2022
5729a06
fix UTs
y-lakhdar Dec 16, 2022
c010a6b
Merge branch 'CDX-1278' of github.com:coveo/push-api-client.js into C…
y-lakhdar Dec 16, 2022
746770e
test: update snapshots
y-lakhdar Dec 16, 2022
3718e75
Merge branch 'CDX-1278' of github.com:coveo/push-api-client.js into C…
y-lakhdar Dec 16, 2022
255ac7a
test: test permission parser
y-lakhdar Dec 16, 2022
ec3ee06
fix: prevent pushing empty permission array
y-lakhdar Dec 16, 2022
46dda23
lint
y-lakhdar Dec 16, 2022
ee433ef
Merge branch 'CDX-1280' of github.com:coveo/push-api-client.js into C…
y-lakhdar Dec 16, 2022
90826ec
remove comments
y-lakhdar Dec 16, 2022
b6c72df
BREAKING CHANGE: remove deprecated methods
y-lakhdar Dec 16, 2022
bf3efa2
lint
y-lakhdar Dec 16, 2022
60848c3
chore: remove unused imports
y-lakhdar Dec 16, 2022
0116ab6
set identitytype value case insensitive
y-lakhdar Dec 19, 2022
c39cb9f
test: update unit tests
y-lakhdar Dec 20, 2022
e720507
refactor: extend caseInsensitiveDocument
y-lakhdar Dec 21, 2022
025af74
add document in error in error class
y-lakhdar Dec 21, 2022
3392ba6
reorder parameters
y-lakhdar Dec 21, 2022
c12f7b0
test: add UTs
y-lakhdar Dec 21, 2022
492eb4e
rename method
y-lakhdar Dec 21, 2022
f0cc301
final version
y-lakhdar Dec 21, 2022
9363097
lint
y-lakhdar Dec 21, 2022
1353913
remove comment
y-lakhdar Dec 21, 2022
94cef6c
Merge branch 'main' of github.com:coveo/push-api-client.js into CDX-1278
y-lakhdar Jan 20, 2023
0aad0ac
lock
y-lakhdar Jan 20, 2023
06c7980
Merge branch 'CDX-1278' into CDX-1280
y-lakhdar Jan 20, 2023
1f42c80
Merge branch 'CDX-1280' of github.com:coveo/push-api-client.js into C…
y-lakhdar Jan 20, 2023
df92f68
Merge branch 'CDX-1282' into CDX-1283
y-lakhdar Jan 20, 2023
90b8129
Merge branch 'CDX-1283' of github.com:coveo/push-api-client.js into C…
y-lakhdar Jan 20, 2023
a872de7
fix snapshot
y-lakhdar Jan 20, 2023
ec36263
Merge branch 'main' of github.com:coveo/push-api-client.js into CDX-1283
y-lakhdar Jan 23, 2023
81f0d56
Merge branch 'CDX-1283' of github.com:coveo/push-api-client.js into C…
y-lakhdar Jan 23, 2023
15e2448
Merge branch 'CDX-1283' of github.com:coveo/push-api-client.js into C…
y-lakhdar Jan 23, 2023
ad48522
apply corrections
y-lakhdar Jan 23, 2023
989abbd
Merge branch 'main' of github.com:coveo/push-api-client.js into CDX-1284
y-lakhdar Jan 23, 2023
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
Prev Previous commit
Next Next commit
parse permissions
  • Loading branch information
y-lakhdar committed Dec 16, 2022

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
commit 97a1a19af6453f86a9d31eff1b8db5ab514399c5
83 changes: 83 additions & 0 deletions src/validation/__snapshots__/parsePermissions.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`parsePermissions should marhsal allowed permssion set 1`] = `
[
{
"allowAnonymous": false,
"allowedPermissions": [
{
"identity": "asmith@example.com",
"identityType": "USER",
},
{
"identity": "bjones@example.com",
"identityType": "USER",
},
],
"deniedPermissions": [],
},
]
`;

exports[`parsePermissions should marhsal combined permssion sets 1`] = `
[
{
"allowAnonymous": true,
"allowedPermissions": [],
"deniedPermissions": [
{
"identity": "foo@example.com",
"identityType": "USER",
},
],
},
{
"allowAnonymous": false,
"allowedPermissions": [
{
"identity": "asmith@example.com",
"identityType": "USER",
},
{
"identity": "bjones@example.com",
"identityType": "USER",
},
],
"deniedPermissions": [],
},
{
"allowAnonymous": false,
"allowedPermissions": [
{
"identity": "Sample_group",
"identityType": "GROUP",
},
{
"identity": "bjones@example.com",
"identityType": "USER",
},
],
"deniedPermissions": [
{
"identity": "foo",
"identityType": "VIRTUAL_GROUP",
},
],
},
]
`;

exports[`parsePermissions should marhsal denied permssion set 1`] = `
[
{
"allowAnonymous": true,
"allowedPermissions": [],
"deniedPermissions": [
{
"identity": "foo@example.com",
"identityType": "USER",
},
],
},
]
`;
197 changes: 4 additions & 193 deletions src/validation/parseFile.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import {
ArrayValue,
BooleanValue,
PrimitivesValues,
RecordValue,
StringValue,
} from '@coveo/bueno';
import {
DocumentBuilder,
Document,
SecurityIdentity,
AnySecurityIdentityBuilder,
MetadataValue,
} from '..';
import {PrimitivesValues, StringValue} from '@coveo/bueno';
import {DocumentBuilder, MetadataValue} from '..';
import {existsSync, lstatSync, PathLike, readFileSync} from 'fs';
import {CaseInsensitiveDocument} from './caseInsensitiveDocument';
import {KnownKeys} from './knownKey';
@@ -21,9 +9,9 @@ import {
NotAJsonFileError,
} from '../errors/validatorErrors';
import {RequiredKeyValidator} from './requiredKeyValidator';
import {Metadata, PermissionLevelModel, PermissionSetModel} from '../document';
import {Metadata} from '../document';
import {ParseDocumentOptions} from '../interfaces';
import {PermissionSetBuilder} from '../permissionSetBuilder';
import {processPermissionList} from './parsePermissions';

export const parseAndGetDocumentBuilderFromJSONDocument = async (
documentPath: PathLike,
@@ -164,162 +152,6 @@ const processKnownKeys = (
);
};

const ensurePermissionArray = (
caseInsensitiveDoc: CaseInsensitiveDocument<PrimitivesValues>,
documentPath: PathLike
) => {
const requiredPermissionArray = new RequiredKeyValidator(
'permissions',
caseInsensitiveDoc,
new ArrayValue({required: false})
);
if (!requiredPermissionArray.isValid) {
throw new InvalidDocument(
documentPath,
requiredPermissionArray.explanation
);
}
};

const processPermissionList = (
caseInsensitiveDoc: CaseInsensitiveDocument<PrimitivesValues>,
documentBuilder: DocumentBuilder,
documentPath: PathLike
) => {
ensurePermissionArray(caseInsensitiveDoc, documentPath);
new KnownKeys<Document['permissions']>(
'permissions',
caseInsensitiveDoc
).whenExists((permissions) => {
permissions!.forEach((permission) => {
const caseInsensitivePermission =
new CaseInsensitiveDocument<PrimitivesValues>(permission);

new KnownKeys('permissionsets', caseInsensitivePermission)
.whenExists<PermissionLevelModel>((permissionLevel) =>
processPermissionLevel(permissionLevel, documentBuilder, documentPath)
)
.whenDoesNotExist<PermissionSetModel>((permissionSet) =>
processPermissionSet(permissionSet, documentBuilder, documentPath)
);
});

delete caseInsensitiveDoc.documentRecord['permissions'];
});
};

const processPermissionSet = (
permissionSet: PermissionSetModel,
documentBuilder: DocumentBuilder,
documentPath: PathLike
) => {
const permissionSetBuilder =
validateRequiredPermissionSetKeysAndGetPermissionSetBuilder(
permissionSet,
documentPath
);

documentBuilder.withPermissionSet(permissionSetBuilder);
};

const processPermissionLevel = (
permission: PermissionLevelModel,
documentBuilder: DocumentBuilder,
documentPath: PathLike
) => {
const permissionSetBuilders = permission.permissionSets.map(
(permissionSet) => {
const caseInsensitivePermissions = new CaseInsensitiveDocument(
permission
);
const requiredPermissionLevelName = new RequiredKeyValidator<string>(
'name',
caseInsensitivePermissions,
new StringValue({required: true, emptyAllowed: false})
);
if (!requiredPermissionLevelName.isValid) {
throw new InvalidDocument(
documentPath,
requiredPermissionLevelName.explanation
);
}
return validateRequiredPermissionSetKeysAndGetPermissionSetBuilder(
permissionSet,
documentPath
);
}
);

documentBuilder.withPermissionLevel(permission.name, permissionSetBuilders);
};

const validateRequiredPermissionSetKeysAndGetPermissionSetBuilder = (
permission: PermissionSetModel,
documentPath: PathLike
): PermissionSetBuilder => {
const caseInsensitivePermissions = new CaseInsensitiveDocument(permission);
const requiredAllowAnonymous = new RequiredKeyValidator(
'allowanonymous',
caseInsensitivePermissions,
new BooleanValue({required: true})
);
if (!requiredAllowAnonymous.isValid) {
throw new InvalidDocument(documentPath, requiredAllowAnonymous.explanation);
}

const requiredAllowedPermissions = new RequiredKeyValidator(
'allowedpermissions',
caseInsensitivePermissions,
getSecurityIdentitySchemaValidation()
);

if (!requiredAllowedPermissions.isValid) {
throw new InvalidDocument(
documentPath,
requiredAllowedPermissions.explanation
);
}

const requiredDeniedPermissions = new RequiredKeyValidator(
'deniedpermissions',
caseInsensitivePermissions,
getSecurityIdentitySchemaValidation()
);

if (!requiredDeniedPermissions.isValid) {
throw new InvalidDocument(
documentPath,
requiredDeniedPermissions.explanation
);
}

const permissionSetBuilder = new PermissionSetBuilder(
permission.allowAnonymous
);

permission.allowedPermissions?.forEach((p) => {
permissionSetBuilder.withAllowedPermissions(
new AnySecurityIdentityBuilder(
p.identityType,
p.identity,
p.securityProvider
)
);
});

permission.deniedPermissions?.forEach((p) => {
permissionSetBuilder.withDeniedPermissions(
new AnySecurityIdentityBuilder(
p.identityType,
p.identity,
p.securityProvider
)
);
});

return permissionSetBuilder;
};

const processMetadata = (
caseInsensitiveDoc: CaseInsensitiveDocument<PrimitivesValues>,
documentBuilder: DocumentBuilder,
@@ -344,24 +176,3 @@ const isFile = (p: PathLike) => {
}
return lstatSync(p).isFile();
};

const getSecurityIdentitySchemaValidation =
(): ArrayValue<SecurityIdentity> => {
return new ArrayValue({
required: true,
each: new RecordValue({
values: {
identity: new StringValue({required: true, emptyAllowed: false}),
identityType: new StringValue({
constrainTo: ['UNKNOWN', 'USER', 'GROUP', 'VIRTUAL_GROUP'],
required: true,
emptyAllowed: false,
}),
securityProvider: new StringValue({
emptyAllowed: false,
required: true,
}),
},
}),
});
};
92 changes: 92 additions & 0 deletions src/validation/parsePermissions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {PrimitivesValues} from '@coveo/bueno';
import {join} from 'path';
import {DocumentBuilder} from '..';
import {CaseInsensitiveDocument} from './caseInsensitiveDocument';
import {processPermissionList} from './parsePermissions';

describe('parsePermissions', () => {
let documentBuilder: DocumentBuilder;
const dummyPath = join('dummy', 'path');
const publicPermissionsSet = {
allowAnonymous: true,
deniedpermissions: [
{
identity: 'foo@example.com',
identityType: 'USER',
},
],
};
const restrictedPermissionSet = {
allowAnonymous: false,
ALLOWEDPERMISSIONS: [
{
identity: 'asmith@example.com',
identityType: 'USER',
},
{
identity: 'bjones@example.com',
identityType: 'USER',
},
],
};

const complexPermissionSet = {
aLLowAnonyMOUS: false,
deniedpermissions: [
{
identity: 'foo',
identityType: 'VIRTUAL_GROUP',
},
],
allowedPERMISSIONS: [
{
identity: 'Sample_group',
identityType: 'GROUP',
},
{
identity: 'bjones@example.com',
identityType: 'USER',
},
],
};

beforeEach(() => {
documentBuilder = new DocumentBuilder('https://foo.com', 'Some Document');
});

it('should not marhsal empty permssion when is empty array', () => {
const caseInsensitiveDoc = new CaseInsensitiveDocument<PrimitivesValues>({
permissions: [],
});
processPermissionList(caseInsensitiveDoc, documentBuilder, dummyPath);
expect(documentBuilder.marshal()).not.toHaveProperty('permissions');
});

it('should marhsal denied permssion set', () => {
const caseInsensitiveDoc = new CaseInsensitiveDocument<PrimitivesValues>({
permissions: [publicPermissionsSet],
});
processPermissionList(caseInsensitiveDoc, documentBuilder, dummyPath);
expect(documentBuilder.marshal().permissions).toMatchSnapshot();
});

it('should marhsal allowed permssion set', () => {
const caseInsensitiveDoc = new CaseInsensitiveDocument<PrimitivesValues>({
permissions: [restrictedPermissionSet],
});
processPermissionList(caseInsensitiveDoc, documentBuilder, dummyPath);
expect(documentBuilder.marshal().permissions).toMatchSnapshot();
});

it('should marhsal combined permssion sets', () => {
const caseInsensitiveDoc = new CaseInsensitiveDocument<PrimitivesValues>({
permissions: [
publicPermissionsSet,
restrictedPermissionSet,
complexPermissionSet,
],
});
processPermissionList(caseInsensitiveDoc, documentBuilder, dummyPath);
expect(documentBuilder.marshal().permissions).toMatchSnapshot();
});
});
Loading