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
2 changes: 1 addition & 1 deletion .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
- run: npm ci
- run: npm publish --tag latest
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.PKG_TOKEN }}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Change log

### Version: 4.0.1
#### Date: May-20-2024
Fixed SRE vulnerabilities

### Version: 4.0.0
#### Date: April-23-2024
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/delivery-sdk",
"version": "4.0.0",
"version": "4.0.1",
"type": "commonjs",
"main": "./dist/cjs/src/index.js",
"types": "./dist/types/src/index.d.ts",
Expand Down
8 changes: 8 additions & 0 deletions src/lib/contentstack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Policy, StackConfig } from './types';
import { getHost } from './utils';
export * as Utils from '@contentstack/utils';

let version = '{{VERSION}}';

/**
* @method stack
* @memberof Contentstack
Expand Down Expand Up @@ -67,10 +69,16 @@ export function stack(config: StackConfig): StackClass {
throw new Error('Environment for Stack is required');
}

if (config.branch) {
defaultConfig.headers.branch = config.branch;
}

if (config.early_access) {
defaultConfig.headers['x-header-ea'] = config.early_access.join(',');
}

defaultConfig.headers['X-User-Agent'] = 'contentstack-delivery-typescript-{{PLATFORM}}/' + version;

// return new Stack(httpClient(defaultConfig), config);
const client = httpClient(defaultConfig as any);

Expand Down
147 changes: 136 additions & 11 deletions src/lib/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@ export class Query extends BaseQuery {
this._parameters = { ...this._parameters, ...queryObj };
}
}
// Validate if input is alphanumeric
private isValidAlphanumeric(input: string): boolean {
const alphanumericRegex = /^[a-zA-Z0-9_.-]+$/;
return alphanumericRegex.test(input);
}
// Validate if input is a valid regex pattern
private isValidRegexPattern(input: string): boolean {
try {
RegExp(input)
return true;
}
catch {
return false;
}

}

// Validate if value is an array of strings, numbers, or booleans
private isValidValue(value: any[]): boolean {
return Array.isArray(value) && value.every(item => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean');
}

/**
* @method where
Expand All @@ -40,18 +61,22 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
where(
fieldUid: string,
queryOperation: QueryOperation | TaxonomyQueryOperation,
fieldUid: string,
queryOperation: QueryOperation | TaxonomyQueryOperation,
fields: string | string[] | number | number[] | object | boolean,
additionalData?: object
): Query {
if (!this.isValidAlphanumeric(fieldUid)) {
console.error("Invalid fieldUid:", fieldUid);
return this;
}
if (queryOperation == QueryOperation.EQUALS) {
this._parameters[fieldUid] = fields;
} else {
}
else {
const parameterValue: { [key in QueryOperation]?: string | string[] } = { [queryOperation]: fields, ...additionalData };
this._parameters[fieldUid] = parameterValue;
}

return this;
}

Expand All @@ -70,11 +95,18 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
regex(fieldUid: string, regexPattern: string, options?: string): Query {
this._parameters[fieldUid] = { $regex: regexPattern };

if (options) this._parameters[fieldUid].$options = options;

return this;
if (!this.isValidAlphanumeric(fieldUid)) {
console.error("Invalid fieldUid:", fieldUid);
return this;
}
if (!this.isValidRegexPattern(regexPattern)) {
throw new Error("Invalid regexPattern: Must be a valid regular expression");
}
else {
this._parameters[fieldUid] = { $regex: regexPattern };
if (options) this._parameters[fieldUid].$options = options;
return this;
}
}

/**
Expand All @@ -95,8 +127,10 @@ export class Query extends BaseQuery {
*/
whereIn(referenceUid: string, queryInstance: Query): Query {
// eslint-disable-next-line @typescript-eslint/naming-convention, prettier/prettier
if (!this.isValidAlphanumeric(referenceUid)) {
throw new Error("Invalid referenceUid: Must be alphanumeric.");
}
this._parameters[referenceUid] = { '$in_query': queryInstance._parameters };

return this;
}

Expand All @@ -118,8 +152,10 @@ export class Query extends BaseQuery {
*/
whereNotIn(referenceUid: string, queryInstance: Query): Query {
// eslint-disable-next-line @typescript-eslint/naming-convention, prettier/prettier
if (!this.isValidAlphanumeric(referenceUid)) {
throw new Error("Invalid referenceUid: Must be alphanumeric.");
}
this._parameters[referenceUid] = { '$nin_query': queryInstance._parameters };

return this;
}

Expand Down Expand Up @@ -183,6 +219,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
containedIn(key: string, value: (string | number | boolean)[]): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (!this.isValidValue(value)) {
console.error("Invalid value:", value);
return this;
}
this._parameters[key] = { '$in': value };
return this;
}
Expand All @@ -201,6 +245,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
notContainedIn(key: string, value: (string | number | boolean)[]): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (!this.isValidValue(value)) {
console.error("Invalid value:", value);
return this;
}
this._parameters[key] = { '$nin': value };
return this;
}
Expand All @@ -219,6 +271,10 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
exists(key: string): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
this._parameters[key] = { '$exists': true };
return this;
}
Expand All @@ -237,6 +293,10 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
notExists(key: string): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
this._parameters[key] = { '$exists': false };
return this;
}
Expand Down Expand Up @@ -300,6 +360,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
equalTo(key: string, value: string | number | boolean): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (typeof value !== 'string' && typeof value !== 'number') {
console.error("Invalid value (expected string or number):", value);
return this;
}
this._parameters[key] = value;
return this;
}
Expand All @@ -317,6 +385,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
notEqualTo(key: string, value: string | number | boolean): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (typeof value !== 'string' && typeof value !== 'number') {
console.error("Invalid value (expected string or number):", value);
return this;
}
this._parameters[key] = { '$ne': value };
return this;;
}
Expand All @@ -335,6 +411,10 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
referenceIn(key: string, query: Query): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
this._parameters[key] = { '$in_query': query._parameters }
return this;
}
Expand All @@ -353,6 +433,10 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
referenceNotIn(key: string, query: Query): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
this._parameters[key] = { '$nin_query': query._parameters }
return this;
}
Expand All @@ -371,6 +455,10 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
tags(values: (string | number | boolean)[]): Query {
if (!this.isValidValue(values)) {
console.error("Invalid value:", values);
return this;
}
this._parameters['tags'] = values;
return this;
}
Expand All @@ -389,6 +477,10 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
search(key: string): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
this._queryParams['typeahead'] = key
return this
}
Expand All @@ -407,6 +499,15 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
lessThan(key: string, value: (string | number)): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (typeof value !== 'string' && typeof value !== 'number') {
console.error("Invalid value (expected string or number):", value);
return this;
}

this._parameters[key] = { '$lt': value };
return this;
}
Expand All @@ -425,6 +526,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
lessThanOrEqualTo(key: string, value: (string | number)): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (typeof value !== 'string' && typeof value !== 'number') {
console.error("Invalid value (expected string or number):", value);
return this;
}
this._parameters[key] = { '$lte': value };
return this;
}
Expand All @@ -443,6 +552,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
greaterThan(key: string, value: (string | number)): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (typeof value !== 'string' && typeof value !== 'number') {
console.error("Invalid value (expected string or number):", value);
return this;
}
this._parameters[key] = { '$gt': value };
return this;
}
Expand All @@ -461,6 +578,14 @@ export class Query extends BaseQuery {
* @returns {Query}
*/
greaterThanOrEqualTo(key: string, value: (string | number)): Query {
if (!this.isValidAlphanumeric(key)) {
console.error("Invalid key:", key);
return this;
}
if (typeof value !== 'string' && typeof value !== 'number') {
console.error("Invalid value (expected string or number):", value);
return this;
}
this._parameters[key] = { '$gte': value };
return this;
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface StackConfig extends HttpClientParams {
apiKey: string;
deliveryToken: string;
environment: string;
branch?: string;
early_access?: string[];
region?: Region;
locale?: string;
Expand Down
3 changes: 3 additions & 0 deletions test/api/live-preview.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ dotenv.config();
const apiKey = process.env.API_KEY as string
const deliveryToken = process.env.DELIVERY_TOKEN as string
const environment = process.env.ENVIRONMENT as string
const branch = process.env.BRANCH as string

describe('Live preview tests', () => {
test('should check for values initialized', () => {
const stack = contentstack.stack({
apiKey: apiKey,
deliveryToken: deliveryToken,
environment: environment,
branch: branch,
});
const livePreviewObject = stack.config.live_preview;
expect(livePreviewObject).toBeUndefined();
expect(stack.config.host).toBe('cdn.contentstack.io');
expect(stack.config.branch).toBe(branch);
});

test('should check host when live preview is enabled and management token is provided', () => {
Expand Down
2 changes: 2 additions & 0 deletions test/unit/contentstack.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,14 @@ describe('Contentstack', () => {
apiKey: 'apiKey',
deliveryToken: 'delivery',
environment: 'env',
branch: 'branch',
};
const stackInstance = createStackInstance(config);
expect(stackInstance).toBeInstanceOf(Stack);
expect(stackInstance.config.apiKey).toEqual(config.apiKey);
expect(stackInstance.config.deliveryToken).toEqual(config.deliveryToken);
expect(stackInstance.config.environment).toEqual(config.environment);
expect(stackInstance.config.branch).toEqual(config.branch);
done();
});

Expand Down