Files
graphql-api-js/src/cognito/access-control.ts
T

110 lines
3.1 KiB
TypeScript

import { GraphQLError } from 'graphql';
import { ClaimVerifyResult } from './cognito-client';
export const RESOURCE = 'https://graphql.photowall.com';
export enum Scopes {
ORDERS_READ = 'orders.read',
ORDERS_WRITE = 'orders.write',
DESIGNERS_READ = 'designers.read',
DESIGNERS_PUBLIC_READ = 'designers.public.read',
DESIGNERS_WRITE = 'designers.write',
PRODUCTS_READ = 'products.read',
PRODUCTS_PUBLIC_READ = 'products.public.read',
PRODUCTS_WRITE = 'products.write',
CATEGORIES_READ = 'categories.read',
CATEGORIES_PUBLIC_READ = 'categories.public.read',
CATEGORIES_WRITE = 'categories.write',
MARKETS_READ = 'markets.read',
KEYWORDS_READ = 'keywords.read',
KEYWORDS_WRITE = 'keywords.write',
LOCALES_READ = 'locales.read',
TEXTS_READ = 'texts.read',
INTERIORS_READ = 'interiors.read',
INTERIORS_PUBLIC_READ = 'interiors.public.read',
INTERIORS_WRITE = 'interiors.write',
}
function getScopes(user: ClaimVerifyResult): Scopes[] | [] {
if (user.accessToken) {
const authScopes = user.accessToken.scope.split(' ');
return authScopes
.map((scopeStr) => {
if (scopeStr.indexOf(RESOURCE) === 0) {
return Scopes[
scopeStr
.replace(`${RESOURCE}/`, '')
.replaceAll('.', '_')
.toLocaleUpperCase()
];
}
return null;
})
.filter(Boolean);
}
return [];
}
function throwForbidden() {
throw new GraphQLError('You are not authorized to perform this action', {
extensions: {
code: 'FORBIDDEN',
http: {
status: 403,
},
},
});
}
export const ScopeAccess = (() => {
const validationObject = (scopes) => {
return {
scopes,
all(input: Scopes[]) {
if (input.length === 0) throwForbidden(); // GUARD
// If the input list contains something thats not in this.scopes array
// then when we concat the lists and remove duplicates the length will be larger
// in the new list than this.scopes.
const checkList = [...new Set(this.scopes.concat(input))];
if (checkList.length === this.scopes.length) return this;
throwForbidden();
},
some(input: Scopes[]) {
if (input.length === 0) throwForbidden(); // GUARD
for (const s of input) {
if (this.scopes.includes(s)) {
return this;
}
}
throwForbidden();
},
};
};
return {
validate(user) {
// If ifToken user then give full access.
// TODO: Should this be removed?
if (user.idToken) {
if (user.idToken['custom:adgroups'].includes('WebAdmin')) {
return validationObject(Object.values(Scopes));
}
}
// If development environment and Basic auth user
// push all scopes to give full access
if (
(process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'test') &&
user.userName === 'development_basic_user'
) {
return validationObject(Object.values(Scopes));
}
// AccessToken with scopes
return validationObject(getScopes(user));
},
};
})();