Skip to content

Commit

Permalink
feat: 👽 chapters no longer need auth
Browse files Browse the repository at this point in the history
remove deps, env vars, and documentation sections related to it
  • Loading branch information
djdembeck committed Jan 25, 2023
1 parent 9ffa0cc commit 6eb12b0
Show file tree
Hide file tree
Showing 8 changed files with 1 addition and 87 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/jest-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ on:
- main
jobs:
coverage:
env:
ADP_TOKEN: ${{ secrets.ADP_TOKEN }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
permissions:
checks: write
pull-requests: write
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ on:

jobs:
build:
env:
ADP_TOKEN: ${{ secrets.ADP_TOKEN }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ These instructions will get you a copy of the project up and running on your loc
- Mongo 4 or greater
- Node/NPM 16 or greater
- Redis
- Registered Audible device keys, `ADP_TOKEN` and `PRIVATE_KEY`, for chapters. You will need Python and `audible` for this. [More on that here](https://audible.readthedocs.io/en/latest/auth/register.html)

### Installing locally

- Install Mongo, Node and Redis on your system
- `pnpm install` from project directory to get dependencies
- Set `ADP_TOKEN` and `PRIVATE_KEY` environment variables as mentioned above if you are using the chapters endpoint.
- `pnpm run watch-debug` to start the server

Test an API call with
Expand Down Expand Up @@ -97,10 +95,8 @@ The stack defaults to 15 replicas for the node-server container. Customize this

Environment variables to add:

- `NODE_ADP_TOKEN`: Aforementioned `ADP_TOKEN` value
- `NODE_MAX_REQUESTS`: Maximum amount of requests per 1 minute period from a single source (default 100)
- `NODE_MONGODB_URI`: MongoDB connection URL, such as `mongodb://mongo/audnexus`
- `NODE_PRIVATE_KEY`: Aforementioned `PRIVATE_KEY` value
- `NODE_REDIS_URL`: Redis connection URL, such as `redis://redis:6379`
- `TRAEFIK_DOMAIN`: FQDN for the API server
- `TRAEFIK_EMAIL`: Email to register SSL cert with
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ services:
image: ghcr.io/laxamentumtech/audnexus:develop
restart: always
environment:
- ADP_TOKEN=${NODE_ADP_TOKEN}
- MAX_REQUESTS=${NODE_MAX_REQUESTS}
- MONGODB_URI=${NODE_MONGODB_URI}
- PRIVATE_KEY=${NODE_PRIVATE_KEY}
- REDIS_URL=${NODE_REDIS_URL}
ports:
- '3000:3000'
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@
"html-to-text": "9.0.3",
"isomorphic-fetch": "3.0.0",
"jest-mock-extended": "3.0.1",
"jsrsasign": "10.6.1",
"lodash": "4.17.21",
"module-alias": "2.2.2",
"moment": "2.29.4",
"mongodb": "4.13.0",
"papr": "9.2.1",
"typescript": "4.9.4"
Expand Down
12 changes: 0 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 1 addition & 40 deletions src/helpers/books/audible/ChapterHelper.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import jsrsasign from 'jsrsasign'
import moment from 'moment'

import { AudibleChapter, SingleChapter } from '#config/typing/audible'
import { ApiChapter, ApiSingleChapter } from '#config/typing/books'
import fetch from '#helpers/utils/fetchPlus'
import SharedHelper from '#helpers/utils/shared'
import {
ErrorMessageHTTPFetch,
ErrorMessageMissingEnv,
ErrorMessageNoData,
ErrorMessageRequiredKey
} from '#static/messages'
import { regions } from '#static/regions'

class ChapterHelper {
adpToken: string
asin: string
inputJson: AudibleChapter['content_metadata']['chapter_info'] | undefined
privateKey: string
reqUrl: string
region: string

Expand All @@ -30,13 +24,6 @@ class ChapterHelper {
const baseUrl = '1.0/content'
const params = 'metadata?response_groups=chapter_info'
this.reqUrl = helper.buildUrl(asin, baseDomain, regionTLD, baseUrl, params)
if (process.env.ADP_TOKEN && process.env.PRIVATE_KEY) {
this.adpToken = process.env.ADP_TOKEN
this.privateKey = process.env.PRIVATE_KEY
this.privateKey = this.privateKey.replace(/\\n/g, '\n')
} else {
throw new Error(ErrorMessageMissingEnv('ADP_TOKEN or PRIVATE_KEY'))
}
}

/**
Expand Down Expand Up @@ -76,38 +63,12 @@ class ChapterHelper {
return chapterTitle
}

/**
* Creates the x-adp-signature header required to auth the API call
* @param {string} adpToken from Audible-api auth file
* @param {string} privateKey from Audible-api auth file
* @returns {string} encoded 'x-adp-signature' header
*/
signRequest(adpToken: string, privateKey: string): string {
const method = 'GET'
const path = this.buildPath()
const body = ''
const date = moment.utc().format()
const data = `${method}\n${path}\n${date}\n${body}\n${adpToken}`
const sig = new jsrsasign.KJUR.crypto.Signature({ alg: 'SHA256withRSA' })
sig.init(privateKey)
const hash = sig.signString(data)
const signedEncoded = jsrsasign.hextob64(hash)

return `${signedEncoded}:${date}`
}

/**
* Fetches chapter Audible API JSON
* @returns {Promise<AudibleChapter>} data from parseResponse() function.
*/
async fetchChapter(): Promise<AudibleChapter | undefined> {
return fetch(this.reqUrl, {
headers: {
'x-adp-token': this.adpToken,
'x-adp-alg': 'SHA256withRSA:1.0',
'x-adp-signature': this.signRequest(this.adpToken, this.privateKey)
}
})
return fetch(this.reqUrl)
.then(async (response) => {
const json: AudibleChapter = await response.json()
return json
Expand Down
21 changes: 0 additions & 21 deletions tests/helpers/books/audible/ChapterHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ beforeEach(() => {
describe('ChapterHelper should', () => {
test('setup constructor correctly', () => {
expect(helper.asin).toBe(asin)
expect(helper.adpToken).toBeDefined()
expect(helper.privateKey).toBeDefined()
expect(helper.reqUrl).toBe(
`https://api.audible.com/1.0/content/${asin}/metadata?response_groups=chapter_info`
)
Expand All @@ -37,10 +35,6 @@ describe('ChapterHelper should', () => {
expect(helper.chapterTitleCleanup('123')).toBe('Chapter 123')
})

test('sign request', () => {
expect(helper.signRequest(helper.adpToken, helper.privateKey)).toBeDefined()
})

test('fetch chapters', async () => {
await expect(helper.fetchChapter()).resolves.toEqual(apiChapters)
})
Expand Down Expand Up @@ -78,21 +72,6 @@ describe('ChapterHelper should throw error when', () => {
expect(() => helper.getFinalData()).toThrowError('No input data')
})

const OLD_ENV = process.env

test('missing environment vars', () => {
// Set environment variables
process.env = { ...OLD_ENV }
process.env.ADP_TOKEN = undefined
process.env.PRIVATE_KEY = undefined
// setup function to fail if environment variables are missing
const bad_helper = function () {
new ChapterHelper(asin, region)
}
expect(bad_helper).toThrowError('Missing environment variable(s): ADP_TOKEN or PRIVATE_KEY')
// Restore environment
process.env = OLD_ENV
})
test('chapter missing required keys', async () => {
await expect(
helper.parseResponse({
Expand Down

0 comments on commit 6eb12b0

Please sign in to comment.