110 lines
3.1 KiB
TypeScript
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));
|
|
},
|
|
};
|
|
})();
|