Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
it('finds "GET /orders, /orders/{id}, /orders/{orderId}/shipments" endpoints', () => {
class TestController {
@get('/orders/{id}')
async getOrderById(@param.path.number('id') id: number): Promise {
return {id};
}
// A path that overlaps with `/orders/{id}`. Please note a different var
// name is used - `{orderId}`
@get('/orders/{orderId}/shipments')
async getShipmentsForOrder(
@param.path.number('orderId') id: number,
): Promise {
return [];
}
// With trailing `/`
@get('/orders/')
async findOrders(): Promise {
return [];
}
it('authenticates successfully with valid token', async () => {
class InfoController {
constructor(
@inject(JWTAuthenticationStrategyBindings.TOKEN_SERVICE)
public tokenService: JWTService,
@inject(USER_REPO)
public users: UserRepository,
@inject(AuthenticationBindings.USER_PROFILE_FACTORY)
public userProfileFactory: UserProfileFactory,
) {}
@post('/login')
async logIn() {
//
// ...Other code for verifying a valid user (e.g. basic or local strategy)...
//
// Now with a valid userProfile, let's create a JSON web token
return this.tokenService.generateToken(
this.userProfileFactory(joeUser),
);
}
@get('/whoAmI')
@authenticate('jwt')
whoAmI(@inject(SecurityBindings.USER) userProfile: UserProfile) {
if (!userProfile) return 'userProfile is undefined';
if (!userProfile[securityId])
const apispec = anOpenApiSpec()
.withOperation('get', '/name', {
'x-operation-name': 'getName',
responses: {
'200': {
schema: {
type: 'string',
},
description: '',
},
},
})
.build();
@api(apispec)
class InfoController {
constructor(@inject('application.name') public appName: string) {}
async getName(): Promise {
return this.appName;
}
}
givenControllerInServer(InfoController);
}
/* ===== HELPERS ===== */
function buildOperationArguments(
operationSpec: OperationObject,
request: Request,
pathParams: PathParameterValues,
body: RequestBody,
globalSchemas: SchemasObject,
options: RequestBodyValidationOptions = {},
): OperationArgs {
let requestBodyIndex = -1;
if (operationSpec.requestBody) {
// the type of `operationSpec.requestBody` could be `RequestBodyObject`
// or `ReferenceObject`, resolving a `$ref` value is not supported yet.
if (isReferenceObject(operationSpec.requestBody)) {
throw new Error('$ref requestBody is not supported yet.');
}
const i = operationSpec.requestBody[REQUEST_BODY_INDEX];
requestBodyIndex = i ? i : 0;
}
const paramArgs: OperationArgs = [];
for (const paramSpec of operationSpec.parameters ?? []) {
if (isReferenceObject(paramSpec)) {
// TODO(bajtos) implement $ref parameters
// See https://github.com/strongloop/loopback-next/issues/435
throw new Error('$ref parameters are not supported yet.');
}
const spec = paramSpec as ParameterObject;
const rawValue = getParamFromRequest(spec, request, pathParams);
private async _matchRequestBodySpec(
operationSpec: OperationObject,
request: Request,
) {
const requestBody: RequestBody = {
value: undefined,
};
if (!operationSpec.requestBody) return {requestBody};
const contentType = getContentType(request) ?? 'application/json';
debug('Loading request body with content type %j', contentType);
// the type of `operationSpec.requestBody` could be `RequestBodyObject`
// or `ReferenceObject`, resolving a `$ref` value is not supported yet.
if (isReferenceObject(operationSpec.requestBody)) {
throw new Error('$ref requestBody is not supported yet.');
}
let content = operationSpec.requestBody.content || {};
if (!Object.keys(content).length) {
content = {
// default to allow json and urlencoded
'application/json': {schema: {type: 'object'}},
'application/x-www-form-urlencoded': {schema: {type: 'object'}},
};
}
// Check of the request content type matches one of the expected media
// types in the request body spec
let matchedMediaType: string | false = false;
let customParser = undefined;
new HttpErrors.BadRequest('Request body is required'),
{
code: 'MISSING_REQUIRED_PARAMETER',
parameterName: 'request body',
},
);
throw err;
}
const schema = body.schema;
/* istanbul ignore if */
if (debug.enabled) {
debug('Request body schema:', util.inspect(schema, {depth: null}));
if (
schema &&
isReferenceObject(schema) &&
schema.$ref.startsWith('#/components/schemas/')
) {
const ref = schema.$ref.slice('#/components/schemas/'.length);
debug(' referencing:', util.inspect(globalSchemas[ref], {depth: null}));
}
}
if (!schema) return;
options = Object.assign({coerceTypes: !!body.coercionRequired}, options);
validateValueAgainstSchema(body.value, schema, globalSchemas, options);
}
): OperationArgs {
let requestBodyIndex = -1;
if (operationSpec.requestBody) {
// the type of `operationSpec.requestBody` could be `RequestBodyObject`
// or `ReferenceObject`, resolving a `$ref` value is not supported yet.
if (isReferenceObject(operationSpec.requestBody)) {
throw new Error('$ref requestBody is not supported yet.');
}
const i = operationSpec.requestBody[REQUEST_BODY_INDEX];
requestBodyIndex = i ? i : 0;
}
const paramArgs: OperationArgs = [];
for (const paramSpec of operationSpec.parameters ?? []) {
if (isReferenceObject(paramSpec)) {
// TODO(bajtos) implement $ref parameters
// See https://github.com/strongloop/loopback-next/issues/435
throw new Error('$ref parameters are not supported yet.');
}
const spec = paramSpec as ParameterObject;
const rawValue = getParamFromRequest(spec, request, pathParams);
const coercedValue = coerceParameter(rawValue, spec);
paramArgs.push(coercedValue);
}
debug('Validating request body - value %j', body);
validateRequestBody(body, operationSpec.requestBody, globalSchemas, options);
if (requestBodyIndex > -1) paramArgs.splice(requestBodyIndex, 0, body.value);
return paramArgs;
}
constructor(
@inject(CoreBindings.APPLICATION_INSTANCE) app: Application,
@inject(RestBindings.CONFIG) config?: RestComponentConfig,
) {
app.bind(RestBindings.SEQUENCE).toClass(DefaultSequence);
const apiSpec = createEmptyApiSpec();
// Merge the OpenAPI `servers` spec from the config into the empty one
if (config?.openApiSpec?.servers) {
Object.assign(apiSpec, {servers: config.openApiSpec.servers});
}
app.bind(RestBindings.API_SPEC).to(apiSpec);
}
}
it('allows anonymous requests to methods with no decorator', async () => {
class InfoController {
@get('/status')
status() {
return {running: true};
}
}
app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect(200, {running: true});
});
it('allows anonymous requests to methods with no decorator', async () => {
class InfoController {
@get('/status')
status() {
return {running: true};
}
}
app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect(200, {running: true});
});