From 31d0fa5aebcf808ee8c7c8a3c516ae8780e1a79e Mon Sep 17 00:00:00 2001 From: Chris Millar Date: Tue, 6 Feb 2024 18:06:27 -0700 Subject: [PATCH] Add headers, fix other smaller issues --- .eslintignore | 5 +++++ package.json | 1 + src/handlers/delete.js | 11 +++++++++++ src/handlers/get.js | 11 +++++++++++ src/handlers/post.js | 11 +++++++++++ src/handlers/unkown.js | 11 +++++++++++ src/helpers/copy.js | 11 +++++++++++ src/helpers/source.js | 15 ++++++++++++++- src/routes/copy.js | 11 +++++++++++ src/routes/list.js | 11 +++++++++++ src/routes/properties.js | 17 +++++++++++++---- src/routes/source.js | 11 +++++++++++ src/storage/bucket/list.js | 11 +++++++++++ src/storage/object/copy.js | 11 +++++++++++ src/storage/object/delete.js | 11 +++++++++++ src/storage/object/get.js | 11 +++++++++++ src/storage/object/list.js | 11 +++++++++++ src/storage/object/put.js | 32 +++++++++++++++++++++++++++----- src/storage/utils/config.js | 11 +++++++++++ src/storage/utils/list.js | 12 ++++++++++++ src/utils/auth.js | 30 +++++++++++++++--------------- test/utils/auth.test.js | 13 ++++++++++++- test/utils/mocks/jose.js | 21 +++++++++++++++------ test/utils/mocks/req.js | 19 +++++++++++++++---- 24 files changed, 283 insertions(+), 36 deletions(-) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..19f2db7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +.vscode/* +coverage/* +dist/* +!.releaserc.js +test/* diff --git a/package.json b/package.json index 67e4491..23e6510 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "scripts": { "docs:build": "npx @redocly/cli build-docs -o docs/index.html admin@v1", "docs:watch": "npx @redocly/cli preview-docs admin@v1", + "lint": "eslint .", "test": "c8 mocha --spec=test/**/*.test.js", "dev": "wrangler dev", "deploy:prod": "wrangler deploy", diff --git a/src/handlers/delete.js b/src/handlers/delete.js index fc52766..ba77e3a 100644 --- a/src/handlers/delete.js +++ b/src/handlers/delete.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { deleteSource } from '../routes/source.js'; export default async function deleteHandler({ env, daCtx }) { diff --git a/src/handlers/get.js b/src/handlers/get.js index 820f4ee..4c7e20b 100644 --- a/src/handlers/get.js +++ b/src/handlers/get.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { getSource } from '../routes/source.js'; import getList from '../routes/list.js'; import { getProperties } from '../routes/properties.js'; diff --git a/src/handlers/post.js b/src/handlers/post.js index be8cd17..7600a35 100644 --- a/src/handlers/post.js +++ b/src/handlers/post.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { postSource } from '../routes/source.js'; import { postProperties } from '../routes/properties.js'; diff --git a/src/handlers/unkown.js b/src/handlers/unkown.js index 4dcd3b8..d371cbe 100644 --- a/src/handlers/unkown.js +++ b/src/handlers/unkown.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ export default function unkownHandler() { const body = JSON.stringify({ message: 'Unknown method. Please see: https://docs.da.live for more information.' }); return { body, status: 501 }; diff --git a/src/helpers/copy.js b/src/helpers/copy.js index d139490..6b86ef5 100644 --- a/src/helpers/copy.js +++ b/src/helpers/copy.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ export default async function copyHelper(req, daCtx) { const formData = await req.formData(); if (!formData) return {}; diff --git a/src/helpers/source.js b/src/helpers/source.js index 68e1755..11f75f3 100644 --- a/src/helpers/source.js +++ b/src/helpers/source.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { FORM_TYPES } from '../utils/constants.js'; /** @@ -5,7 +16,9 @@ import { FORM_TYPES } from '../utils/constants.js'; * @param {*} key */ export function sourceRespObject(daCtx, props) { - const { org, site, isFile, pathname, aemPathname } = daCtx; + const { + org, site, isFile, pathname, aemPathname, + } = daCtx; const obj = { source: { diff --git a/src/routes/copy.js b/src/routes/copy.js index 08a6f08..c3d39d2 100644 --- a/src/routes/copy.js +++ b/src/routes/copy.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import copyObject from '../storage/object/copy.js'; import copyHelper from '../helpers/copy.js'; diff --git a/src/routes/list.js b/src/routes/list.js index b0b9924..c36a5e3 100644 --- a/src/routes/list.js +++ b/src/routes/list.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import listBuckets from '../storage/bucket/list.js'; import listObjects from '../storage/object/list.js'; diff --git a/src/routes/properties.js b/src/routes/properties.js index 395bf4e..7eb477a 100644 --- a/src/routes/properties.js +++ b/src/routes/properties.js @@ -1,9 +1,18 @@ -// eslint-disable-next-line no-unused-vars +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ export function postProperties({ env, daCtx }) { - return { body: JSON.stringify([]), status: 201 }; + return { body: JSON.stringify(env, daCtx), status: 201 }; } -// eslint-disable-next-line no-unused-vars export function getProperties({ env, daCtx }) { - return { body: JSON.stringify([]), status: 200 }; + return { body: JSON.stringify(env, daCtx), status: 200 }; } diff --git a/src/routes/source.js b/src/routes/source.js index e55f794..ec74407 100644 --- a/src/routes/source.js +++ b/src/routes/source.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import getObject from '../storage/object/get.js'; import putObject from '../storage/object/put.js'; import deleteObject from '../storage/object/delete.js'; diff --git a/src/storage/bucket/list.js b/src/storage/bucket/list.js index 73e4be5..2956aff 100644 --- a/src/storage/bucket/list.js +++ b/src/storage/bucket/list.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { S3Client, ListBucketsCommand, diff --git a/src/storage/object/copy.js b/src/storage/object/copy.js index 51998d3..3530b7d 100644 --- a/src/storage/object/copy.js +++ b/src/storage/object/copy.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { S3Client, ListObjectsV2Command, diff --git a/src/storage/object/delete.js b/src/storage/object/delete.js index 1c9f6d6..cbcfcae 100644 --- a/src/storage/object/delete.js +++ b/src/storage/object/delete.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { S3Client, DeleteObjectCommand, diff --git a/src/storage/object/get.js b/src/storage/object/get.js index 7af7b51..6cc8650 100644 --- a/src/storage/object/get.js +++ b/src/storage/object/get.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { S3Client, GetObjectCommand, diff --git a/src/storage/object/list.js b/src/storage/object/list.js index ff22d5f..a76dd9c 100644 --- a/src/storage/object/list.js +++ b/src/storage/object/list.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { S3Client, ListObjectsV2Command, diff --git a/src/storage/object/put.js b/src/storage/object/put.js index 2f7a90c..db7abf9 100644 --- a/src/storage/object/put.js +++ b/src/storage/object/put.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import { S3Client, PutObjectCommand, @@ -16,14 +27,19 @@ function getObjectBody(data) { return { body: JSON.stringify(data), type: 'application/json' }; } -function buildInput({ org, key, body, type }) { +function buildInput({ + org, key, body, type, +}) { const Bucket = `${org}-content`; - return { Bucket, Key: key, Body: body, ContentType: type }; + return { + Bucket, Key: key, Body: body, ContentType: type, + }; } function createBucketIfMissing(client) { client.middlewareStack.add( (next) => async (args) => { + // eslint-disable-next-line no-param-reassign args.request.headers['cf-create-bucket-if-missing'] = 'true'; return next(args); }, @@ -50,16 +66,22 @@ export default async function putObject(env, daCtx, obj) { if (obj.data) { const isFile = obj.data instanceof File; const { body, type } = isFile ? await getFileBody(obj.data) : getObjectBody(obj.data); - inputs.push(buildInput({ org, key, body, type })); + inputs.push(buildInput({ + org, key, body, type, + })); } if (obj.props) { const { body, type } = getObjectBody(obj.props); - const inputConfig = { org, key: propsKey || key, body, type }; + const inputConfig = { + org, key: propsKey || key, body, type, + }; inputs.push(buildInput(inputConfig)); } } else { const { body, type } = getObjectBody({}); - const inputConfig = { org, key: propsKey, body, type }; + const inputConfig = { + org, key: propsKey, body, type, + }; inputs.push(buildInput(inputConfig)); } diff --git a/src/storage/utils/config.js b/src/storage/utils/config.js index 5b62dd0..cce4f35 100644 --- a/src/storage/utils/config.js +++ b/src/storage/utils/config.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ export default function getS3Config(env) { return { region: 'auto', diff --git a/src/storage/utils/list.js b/src/storage/utils/list.js index 285c8a3..da9639e 100644 --- a/src/storage/utils/list.js +++ b/src/storage/utils/list.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ export default function formatList(resp, daCtx) { function compare(a, b) { if (a.name < b.name) return -1; @@ -40,6 +51,7 @@ export default function formatList(resp, daCtx) { if (combined.some((item) => item.name === name)) return; // Remove props from the key so it can look like a folder + // eslint-disable-next-line no-param-reassign content.Key = content.Key.replace('.props', ''); } diff --git a/src/utils/auth.js b/src/utils/auth.js index c677261..7f176bd 100644 --- a/src/utils/auth.js +++ b/src/utils/auth.js @@ -36,28 +36,28 @@ export async function getUsers(req, env) { if (!token || token.trim().length === 0) { users.push({ email: 'anonymous' }); } - const { - user_id: userId, - created_at: createdAt, - expires_in: expiresIn, - } = decodeJwt(token); + const { user_id: userId, created_at: createdAt, expires_in: expiresIn } = decodeJwt(token); const expires = Number(createdAt) + Number(expiresIn); const now = Math.floor(new Date().getTime() / 1000); if (expires >= now) { - // Find the user + // Find the user in recent sessions let user = await env.DA_AUTH.get(userId); - const headers = new Headers(req.headers); - headers.delete('authorization'); - headers.set('authorization', `Bearer ${token}`); - // If not found, create them - if (!user) user = await setUser(userId, Math.floor(expires / 1000), headers, env); - // If something went wrong, be anon. + + // If not found, add them to recent sessions if (!user) { - users.push({ email: 'anonymous' }); - } else { - users.push(JSON.parse(user)); + const headers = new Headers(req.headers); + headers.delete('authorization'); + headers.set('authorization', `Bearer ${token}`); + // If not found, create them + user = await setUser(userId, Math.floor(expires / 1000), headers, env); } + + // If there's still no user, make them anon. + if (!user) user = JSON.stringify({ email: 'anonymous' }); + + // Finally, push whoever was made. + users.push(JSON.parse(user)); } else { users.push({ email: 'anonymous' }); } diff --git a/test/utils/auth.test.js b/test/utils/auth.test.js index 1f08ad6..813fc08 100644 --- a/test/utils/auth.test.js +++ b/test/utils/auth.test.js @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ import assert from 'assert'; import esmock from 'esmock'; @@ -11,7 +22,7 @@ import fetch from './mocks/fetch.js'; const { isAuthorized, setUser, - getUsers + getUsers, } = await esmock('../../src/utils/auth.js', { jose, import: { fetch } }); describe('Dark Alley auth', () => { diff --git a/test/utils/mocks/jose.js b/test/utils/mocks/jose.js index bdd3e6f..08ad60a 100644 --- a/test/utils/mocks/jose.js +++ b/test/utils/mocks/jose.js @@ -1,14 +1,23 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ const decodeJwt = (token) => { - const [ - email, - created_at = Math.floor(new Date().getTime() / 1000), - expires_in - ] = token.split(':'); + let [email, created_at = 0, expires_in = 0] = token.split(':'); + created_at += Math.floor(new Date().getTime() / 1000); + expires_in += created_at; return { user_id: email, created_at, expires_in: expires_in || created_at + 1000, - } + }; }; export default { decodeJwt }; diff --git a/test/utils/mocks/req.js b/test/utils/mocks/req.js index 10c86d3..694bc0b 100644 --- a/test/utils/mocks/req.js +++ b/test/utils/mocks/req.js @@ -1,29 +1,40 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ const optsWithEmptyHead = { headers: new Headers(), }; const optsWithEmptyBearer = { headers: new Headers({ - 'Authorization': ` `, + Authorization: ' ', }), }; const optsWithAuth = { headers: new Headers({ - 'Authorization': `Bearer aparker@geometrixx.info`, + Authorization: 'Bearer aparker@geometrixx.info:200:1000', }), }; const optsWithExpAuth = { headers: new Headers({ - 'Authorization': `Bearer aparker@geometrixx.info:100:-150`, + Authorization: 'Bearer aparker@geometrixx.info:100:-150', }), }; const optsWithForceFail = { headers: new Headers({ 'x-mock-fail': true, - 'Authorization': `Bearer aparker@geometrixx.info`, + Authorization: 'Bearer aparker@geometrixx.info', }), };