Skip to content

Commit

Permalink
feat: resync
Browse files Browse the repository at this point in the history
  • Loading branch information
hugomrdias committed Jul 29, 2022
1 parent ee3eb94 commit 5cae9cd
Show file tree
Hide file tree
Showing 67 changed files with 2,555 additions and 2,376 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"devDependencies": {
"lint-staged": "^12.4.0",
"prettier": "2.6.2",
"prettier": "2.7.1",
"simple-git-hooks": "^2.8.0",
"wrangler": "^2.0.8"
},
Expand Down
46 changes: 31 additions & 15 deletions packages/api/package.json → packages/access-api/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
{
"name": "api",
"name": "@web3-storage/w3access-api",
"version": "0.0.1",
"description": "Auth API",
"private": true,
"type": "module",
"main": "dist/worker.js",
"types": "dist/src/index.d.ts",
"files": [
"dist/src/*.d.ts",
"dist/src/*.d.ts.map"
],
"typesVersions": {
"*": {
"*": [
"dist/src/*"
]
}
},
"scripts": {
"lint": "tsc && eslint '**/*.{js,ts}' && prettier --check '**/*.{js,ts,md,yml,json}' --ignore-path ../../.gitignore",
"deploy": "wrangler publish",
Expand All @@ -15,36 +26,41 @@
"author": "Hugo Dias <hugomrdias@gmail.com> (hugodias.me)",
"license": "(Apache-2.0 OR MIT)",
"dependencies": {
"@ipld/dag-ucan": "1.5.0-beta",
"merge-options": "^3.0.4",
"@ipld/dag-ucan": "1.7.0-beta",
"@ucanto/authority": "link:/Users/hd/code/ucanto/packages/authority",
"@ucanto/client": "link:/Users/hd/code/ucanto/packages/client",
"@ucanto/core": "link:/Users/hd/code/ucanto/packages/core",
"@ucanto/interface": "link:/Users/hd/code/ucanto/packages/interface",
"@ucanto/server": "link:/Users/hd/code/ucanto/packages/server",
"@ucanto/transport": "link:/Users/hd/code/ucanto/packages/transport",
"@ucanto/validator": "link:/Users/hd/code/ucanto/packages/validator",
"@web3-storage/w3access": "workspace:^",
"@web3-storage/worker-utils": "0.2.0-dev",
"multiformats": "^9.6.5",
"nanoid": "^3.3.3",
"regexparam": "^2.0.0",
"toucan-js": "^2.6.0",
"ucan-storage": "^1.2.0",
"ucans": "^0.9.1"
"toucan-js": "^2.6.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^3.7.1",
"@sentry/cli": "^1.71.0",
"@cloudflare/workers-types": "^3.14.0",
"@sentry/cli": "^2.1.0",
"@sentry/webpack-plugin": "^1.16.0",
"@types/assert": "^1.5.6",
"@types/git-rev-sync": "^2.0.0",
"@types/node": "^18.6.2",
"assert": "^2.0.0",
"ava": "^4.3.0",
"buffer": "^6.0.3",
"delay": "^5.0.0",
"dotenv": "^16.0.0",
"esbuild": "^0.14.42",
"esbuild": "^0.14.51",
"execa": "^6.1.0",
"git-rev-sync": "^3.0.1",
"hd-scripts": "^2.0.1",
"miniflare": "^2.5.0",
"process": "^0.11.10",
"readable-stream": "^3.6.0",
"readable-stream": "^4.1.0",
"sade": "^1.7.4",
"typescript": "4.7.3",
"wrangler": "^2.0.8"
"typescript": "4.7.4",
"wrangler": "^2.0.23"
},
"eslintConfig": {
"extends": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ prog
inject: [path.join(__dirname, 'node-globals.js')],
plugins: [PluginAlias],
define: {
VERSION: JSON.stringify(version),
COMMITHASH: JSON.stringify(git.long(__dirname)),
BRANCH: JSON.stringify(git.branch(__dirname)),
ACCOUNT_VERSION: JSON.stringify(version),
ACCOUNT_COMMITHASH: JSON.stringify(git.long(__dirname)),
ACCOUNT_BRANCH: JSON.stringify(git.branch(__dirname)),
global: 'globalThis',
},
minify: opts.env !== 'dev',
Expand All @@ -71,7 +71,8 @@ prog
const cli = new Sentry(undefined, {
authToken: process.env.SENTRY_TOKEN,
org: 'protocol-labs-it',
project: 'api',
project: 'w3account-api',
// @ts-ignore
dist: git.short(__dirname),
})

Expand Down
File renamed without changes.
File renamed without changes.
21 changes: 21 additions & 0 deletions packages/access-api/src/bindings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Logging } from '@web3-storage/worker-utils/logging'
import type { SigningAuthority } from '@ucanto/interface'
import type { config } from './config'

export {}

declare global {
const ACCOUNTS: KVNamespace
}

export interface RouteContext {
params: Record<string, string>
log: Logging
keypair: SigningAuthority
config: typeof config
}

export type Handler = (
event: FetchEvent,
ctx: RouteContext
) => Promise<Response> | Response
80 changes: 80 additions & 0 deletions packages/access-api/src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
export const config = loadConfigVariables()

/**
* Loads configuration variables from the global environment and returns a JS object
* keyed by variable names.
*
*/
export function loadConfigVariables() {
/** @type Record<string, string> */
const vars = {}

/** @type Record<string, unknown> */
const globals = globalThis

const required = [
'ENV',
'DEBUG',
'PRIVATE_KEY',
'SENTRY_DSN',
'POSTMARK_TOKEN',
]

for (const name of required) {
const val = globals[name]
if (typeof val === 'string' && val.length > 0) {
vars[name] = val
} else {
throw new Error(
`Missing required config variables: ${name}. Check your .env, testing globals or cloudflare vars.`
)
}
}

return {
DEBUG: boolValue(vars.DEBUG),
ENV: parseRuntimeEnv(vars.ENV),

PRIVATE_KEY: vars.PRIVATE_KEY,
POSTMARK_TOKEN: vars.POSTMARK_TOKEN,
SENTRY_DSN: vars.SENTRY_DSN,

// These are injected in esbuild
// @ts-ignore
// eslint-disable-next-line no-undef
BRANCH: ACCOUNT_BRANCH,
// @ts-ignore
// eslint-disable-next-line no-undef
VERSION: ACCOUNT_VERSION,
// @ts-ignore
// eslint-disable-next-line no-undef
COMMITHASH: ACCOUNT_COMMITHASH,
}
}

/**
* Returns `true` if the string `s` is equal to `"true"` (case-insensitive) or `"1", and false for `"false"`, `"0"` or an empty value.
*
* @param {string} s
* @returns {boolean}
*/
function boolValue(s) {
return Boolean(s && JSON.parse(String(s).toLowerCase()))
}

/**
* Validates that `s` is a defined runtime environment name and returns it.
*
* @param {unknown} s
*/
function parseRuntimeEnv(s) {
switch (s) {
case 'test':
case 'dev':
case 'staging':
case 'production':
return s
default:
throw new Error('invalid runtime environment name: ' + s)
}
}
82 changes: 82 additions & 0 deletions packages/access-api/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as Server from '@ucanto/server'
import * as CAR from '@ucanto/transport/car'
import * as CBOR from '@ucanto/transport/cbor'
import { version } from './routes/version.js'
import { serverCodec } from './ucanto/server-codec.js'
import { service } from './ucanto/service.js'
import { getContext } from './utils/context.js'

import { corsHeaders, preflight } from '@web3-storage/worker-utils/cors'
import { errorHandler } from '@web3-storage/worker-utils/error'
import { notFound } from '@web3-storage/worker-utils/response'
import { Router } from '@web3-storage/worker-utils/router'

/** @type Router<import('./bindings.js').RouteContext> */
const r = new Router({ onNotFound: notFound })
r.add('options', '*', preflight)
r.add('get', '/version', version)
r.add('post', '/', async (request, env) => {
const server = Server.create({
id: env.keypair,
encoder: CBOR,
decoder: CAR,
service: service(env),
catch: (/** @type {string | Error} */ err) => {
env.log.error(err)
},
canIssue: (
/** @type {{ with: any; can: string; }} */ capability,
/** @type {import("@ucanto/interface").DID<unknown>} */ issuer
) => {
if (capability.with === issuer || issuer === env.keypair.did()) {
return true
}

if (capability.can === 'identity/validate') {
return true
}

return false
},
})

const rsp = await server.request({
body: new Uint8Array(await request.arrayBuffer()),
headers: Object.fromEntries(request.headers.entries()),
})
return new Response(rsp.body, { headers: rsp.headers })
})

r.add('post', '/raw', async (request, env) => {
const server = Server.create({
id: env.keypair,
encoder: serverCodec,
decoder: serverCodec,
service: service(env),
catch: (/** @type {string | Error} */ err) => {
env.log.error(err)
},
})

const rsp = await server.request({
body: new Uint8Array(await request.arrayBuffer()),
headers: Object.fromEntries(request.headers.entries()),
})
return new Response(rsp.body, { headers: rsp.headers })
})

addEventListener('fetch', (event) => {
const env = getContext(event, {})
env.log.time('request')
event.respondWith(
r
.handle(event, env)
.then((rsp) => {
env.log.timeEnd('request')
return env.log.end(corsHeaders(event.request, rsp))
})
.catch((error) => {
return errorHandler(error, env.log)
})
)
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import { sha256 } from 'multiformats/hashes/sha2'

/**
* @typedef {{account: string, proof: string}} AccountValue
*/
Expand All @@ -22,17 +18,18 @@ export class Accounts {
*
* @param {string} issuerDID
* @param {string} resourceDID
* @param {string} proof
* @param {import('@ucanto/interface').LinkedProof} proof
*/
async register(issuerDID, resourceDID, proof) {
const bytes = raw.encode(new TextEncoder().encode(proof))
const account = CID.create(
1,
raw.code,
await sha256.digest(bytes)
).toString()
await this.kv.put(issuerDID, JSON.stringify({ account, proof }))
await this.kv.put(resourceDID, JSON.stringify({ account, proof }))
const account = `did:ipld:${proof}`
await this.kv.put(
issuerDID,
JSON.stringify({ account, proof: proof.toString() })
)
await this.kv.put(
resourceDID,
JSON.stringify({ account, proof: proof.toString() })
)
}

/**
Expand Down
14 changes: 14 additions & 0 deletions packages/access-api/src/routes/version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { JSONResponse } from '@web3-storage/worker-utils/response'

/**
* @param {import('@web3-storage/worker-utils/router').ParsedRequest} event
* @param {import('../bindings.js').RouteContext} env
*/
export function version(event, env) {
return new JSONResponse({
version: env.config.VERSION,
commit: env.config.COMMITHASH,
branch: env.config.BRANCH,
did: env.keypair.did(),
})
}
Loading

0 comments on commit 5cae9cd

Please sign in to comment.