diff --git a/CHANGELOG.md b/CHANGELOG.md index 75fb4c2..4edb624 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.0.11 (October 27th, 2023) + +- fix production configs +- upgrade dependencies +- use decorators of new acs-client lib + ## 0.0.10 (October 18th, 2023) - fix config typo @@ -10,6 +16,10 @@ - change default config redis url +## 0.0.7 (October 17st, 2023) + +- add access-control support + ## 0.0.6 (September 1st, 2023) - updated dependencies diff --git a/src/experimental/access_control_decorators.ts b/src/experimental/access_control_decorators.ts deleted file mode 100644 index 957fb93..0000000 --- a/src/experimental/access_control_decorators.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Logger } from 'winston'; -import { Provider as ServiceConfig } from 'nconf'; -import { - Client, - createClient, - createChannel, - GrpcClientConfig -} from '@restorecommerce/grpc-client'; -import { - AuthZAction, - accessRequest, - ACSClientContext, - Operation, - Resource, - initAuthZ, - initializeCache, -} from '@restorecommerce/acs-client'; -import { - UserServiceDefinition -} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/user'; -import { Response_Decision } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/access_control'; - - -/* eslint-disable prefer-arrow-functions/prefer-arrow-functions */ -export type ACSClientContextFactory = (self: any, ...args: any) => Promise; -export type ResourceFactory = (self: any, ...args: any) => Promise; - -export function access_controlled_service(baseService: T): any { - return class extends baseService { - public readonly user_service: Client; - - constructor(...args: any) { - super(...args); - const cfg = args.find((arg: any) => (arg instanceof ServiceConfig)) as ServiceConfig; - const logger = args.find((arg: any) => (arg instanceof Logger)) as Logger; - this.user_service = createClient( - { - ...cfg.get('client:user'), - logger - } as GrpcClientConfig, - UserServiceDefinition, - createChannel(cfg.get('client:user:address')) - ); - initAuthZ(cfg); - initializeCache(); - } - }; -} - -export function access_controlled_function(kwargs: { - action: AuthZAction; - operation: Operation; - context?: ACSClientContext | ACSClientContextFactory; - resource?: Resource[] | ResourceFactory; - database?: 'arangoDB' | 'postgres'; - useCache?: true; -}) { - return function ( - target: any, - propertyName: string, - descriptor: TypedPropertyDescriptor, - ) { - const method = descriptor.value!; - - descriptor.value = async function () { - try { - if (!this.user_service) { - throw new Error('An @access_controlled_function must be member of an @access_controlled_service class'); - } - - const context = typeof(kwargs.context) === 'function' - ? await kwargs.context(this, ...arguments) - : kwargs.context; - - const resource = typeof(kwargs.resource) === 'function' - ? await kwargs.resource(this, ...arguments) - : kwargs.resource; - - const subject = context?.subject; - if (subject?.token) { - const user = await this.user_service.findByToken({ token: subject.token }); - if (user?.payload?.id) { - subject.id = user.payload.id; - } - } - - const response = await accessRequest( - subject, - resource ?? [], - kwargs.action, - context, - kwargs.operation, - kwargs.database ?? 'arangoDB', - kwargs.useCache ?? false - ); - - if (response?.decision !== Response_Decision.PERMIT) { - return response; - } - } - catch (err) { - return { - decision: Response_Decision.DENY, - operation_status: { - code: err.code ?? 500, - message: err.details ?? err.message ?? err, - } - }; - } - return await method.apply(this, arguments); - }; - }; -} - -export const DefaultACSClientContextFactory: ACSClientContextFactory = ( - self: any, - request: any, - context: any, -): Promise => ({ - ...context, - subject: request.subject, - resources: [], -}); \ No newline at end of file diff --git a/src/service.ts b/src/service.ts index 36f9da7..c33aa59 100644 --- a/src/service.ts +++ b/src/service.ts @@ -9,6 +9,9 @@ import { import { ACSClientContext, AuthZAction, + access_controlled_function, + access_controlled_service, + DefaultACSClientContextFactory, Operation } from '@restorecommerce/acs-client'; import { @@ -95,11 +98,6 @@ import { VAT } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/amount'; import { Subject } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/auth'; -import { - access_controlled_service, - access_controlled_function, - DefaultACSClientContextFactory -} from './experimental/access_control_decorators'; import { COUNTRY_CODES_EU } from './utils'; export type RatioedTax = Tax & { diff --git a/test/mocks.ts b/test/mocks.ts index b9b8909..339d381 100644 --- a/test/mocks.ts +++ b/test/mocks.ts @@ -8,23 +8,29 @@ import { OrderState, } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/order'; import { - ProductListResponse, ProductResponse + ProductListResponse, + ProductResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/product'; import { - OrganizationListResponse, OrganizationResponse + OrganizationListResponse, + OrganizationResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/organization'; import { - ContactPointListResponse, ContactPointResponse + ContactPointListResponse, + ContactPointResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/contact_point'; import { - AddressListResponse, BillingAddress, ShippingAddress + AddressListResponse, + BillingAddress, + ShippingAddress } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/address'; import { CountryListResponse, CountryResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/country'; import { - TaxListResponse, TaxResponse + TaxListResponse, + TaxResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/tax'; import { TaxTypeListResponse @@ -33,10 +39,13 @@ import { PackingSolutionListResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/fulfillment_product'; import { - UserListResponse, UserResponse, UserType + UserListResponse, + UserResponse, + UserType } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/user'; import { - ShopListResponse, ShopResponse + ShopListResponse, + ShopResponse } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/shop'; import { CustomerListResponse @@ -45,13 +54,29 @@ import { FulfillmentListResponse, State as FulfillmentState } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/fulfillment'; -import { OperationStatus } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/status'; -import { InvoiceListResponse, PaymentState } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/invoice'; -import { DeepPartial } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/resource_base'; -import { Effect } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/rule'; -import { Subject } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/auth'; -import { getRedisInstance, logger } from '.'; -import { HierarchicalScope } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/auth'; +import { + OperationStatus +} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/status'; +import { + InvoiceListResponse, + PaymentState +} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/invoice'; +import { + DeepPartial +} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/resource_base'; +import { + Effect +} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/rule'; +import { + Subject +} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/auth'; +import { + HierarchicalScope +} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/auth'; +import { + getRedisInstance, + logger +} from './utils'; type Address = ShippingAddress & BillingAddress; diff --git a/test/ordering-srv.spec.ts b/test/ordering-srv.spec.ts index 254f0d1..e8ebfa5 100644 --- a/test/ordering-srv.spec.ts +++ b/test/ordering-srv.spec.ts @@ -23,7 +23,7 @@ import { connectEvents, connectTopics, mockServices, -} from '.'; +} from './utils'; describe('The Ordering Service:', () => { let mocking: GrpcMockServer[]; diff --git a/test/index.ts b/test/utils.ts similarity index 100% rename from test/index.ts rename to test/utils.ts