Skip to content

Commit

Permalink
feat: integrate tokens api into the frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
hugomrdias committed Mar 16, 2021
1 parent 1806adc commit 357514e
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 39 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ wrangler publish --env production
```bash
cd site
yarn install
yarn start
yarn dev
```

### Deploy
Expand Down
4 changes: 3 additions & 1 deletion site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"start": "wrangler dev",
"deploy": "wrangler publish --env production",
"test": "echo \"Error: no test specified\" && exit 1",
"format": "prettier --write '**/*.{js,css,json,md}'"
"format": "prettier --write '**/*.{js,css,json,md}'",
"build": "cd ../website && npx next build && npx next export -o ../site/public",
"dev": "yarn build && yarn start"
},
"author": "Hugo Dias <hugomrdias@gmail.com> (hugodias.me)",
"license": "MIT",
Expand Down
11 changes: 4 additions & 7 deletions site/src/routes/manage.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { authorize } from '../utils/auth0.js'
import { getUser } from '../models/users.js'
import { getUser, tokens } from '../models/users.js'
import { getAsset, hydrateState } from '../utils/utils.js'
import { list } from '../models/nfts.js'

/**
* @param {FetchEvent} event
*/
export async function manage (event) {
export async function manage(event) {
const result = await authorize(event)
// Must be logged in to manage API keys
if (!result.ok) {
Expand All @@ -15,11 +15,8 @@ export async function manage (event) {

const [rsp, user] = await Promise.all([
getAsset(event),
getUser(result.value.userInfo.sub)
getUser(result.value.userInfo.sub),
])
const tokens = [{ name: 'Default', token: user.token }] // TODO: multiple tokens

return new HTMLRewriter()
.on('head', hydrateState({ user, tokens }))
.transform(rsp)
return new HTMLRewriter().on('head', hydrateState({ user })).transform(rsp)
}
15 changes: 15 additions & 0 deletions website/lib/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const env = process.env.ENV || 'development';

const configs = {
development: {
api: 'http://127.0.0.1:8787',
},
staging: {
api: 'https://staging.nft.storage',
},
production: {
api: 'https://nft.storage',
},
}[env];

export default configs;
35 changes: 21 additions & 14 deletions website/lib/state.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
export function getEdgeState () {
if (typeof document === 'undefined') {
return {} // static export
}
const stateEl = document.querySelector('script#edge_state')
if (!stateEl) {
return {}
}
try {
return JSON.parse(stateEl.innerText)
} catch (err) {
console.error('failed to parse state JSON', stateEl.innerText, err)
return {}
}
export function getEdgeState() {
if (typeof document === 'undefined') {
return {}; // static export
}
const stateEl = document.querySelector('script#edge_state');
if (!stateEl) {
return {};
}
try {
const { user } = JSON.parse(stateEl.innerText);
return {
user,
tokens: Object.keys(user.tokens).map((k) => ({
name: k,
token: user.tokens[k]
}))
};
} catch (err) {
console.error('failed to parse state JSON', stateEl.innerText, err);
return {};
}
}
6 changes: 6 additions & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,11 @@
"react-dom": "17.0.1",
"swr": "^0.5.3",
"tachyons": "^4.12.0"
},
"prettier": {
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true
}
}
26 changes: 21 additions & 5 deletions website/pages/manage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,25 @@ import Navbar from '../components/navbar.js'
import Footer from '../components/footer.js'
import Button from '../components/button.js'
import { getEdgeState } from '../lib/state.js'
import configs from '../lib/config.js'

export default function ManageKeys () {
const { data } = useSWR('edge_state', getEdgeState)
const { user, loginUrl = '#', tokens = [] } = data ?? {}
async function deleteToken(e) {
e.preventDefault()
const name = e.target.name.value
const rsp = await fetch(configs.api + '/api/internal/tokens', {
method: 'delete',
body: JSON.stringify({ name }),
})
const data = await rsp.json()
if (data.ok) {
location = '/manage'
} else {
console.error(data.error)
}
}
return (
<div className='sans-serif'>
<Head>
Expand All @@ -19,12 +34,12 @@ export default function ManageKeys () {
<div>
<div className='flex mb3 items-center'>
<h1 className='chicagoflf mv4 flex-auto'>Manage API Keys</h1>
<Button href='/new-key.html' className='flex-none'>+ New Key</Button>
<Button href='/new-key' className='flex-none'>+ New Key</Button>
</div>
{tokens.length ? (
<table className='bg-white ba b--black w-100 collapse mb4'>
<tr className='bb b--black'>
<th className='pa2 tl bg-nsgray br b--black w-50'>Name</th>
<th className='pa2 tl bg-nsgray br b--black w-20'>Name</th>
<th className='pa2 tl bg-nsgray br b--black w-50'>Key</th>
<th className='pa2 tc bg-nsgray' />
</tr>
Expand All @@ -34,11 +49,12 @@ export default function ManageKeys () {
{t.name}
</td>
<td className='pa2 br b--black mw7'>
<code style={{ wordWrap: 'break-word' }}>{t.token}</code>
<input className='w-90' value={t.token}/>
{/* <code style={{ wordWrap: 'break-word' }}>{t.token}</code> */}
</td>
<td className='pa2'>
<form action='/delete' method='DELETE'>
<input type='hidden' name='id' value='1' />
<form onSubmit={deleteToken}>
<input type='hidden' name='name' id='name' value={t.name} />
<Button className='bg-nsorange white' type='submit'>Delete</Button>
</form>
</td>
Expand Down
54 changes: 43 additions & 11 deletions website/pages/new-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,59 @@ import Footer from '../components/footer.js'
import Box from '../components/box.js'
import Button from '../components/button.js'
import { getEdgeState } from '../lib/state.js'
import configs from '../lib/config.js'
import { useRouter } from 'next/router'

export default function NewKey () {
export default function NewKey() {
const { data } = useSWR('edge_state', getEdgeState)
const { user, loginUrl = '#' } = data ?? {}
const router = useRouter()

async function createToken(e) {
e.preventDefault()
const name = e.target.name.value
const rsp = await fetch(configs.api + '/api/internal/tokens', {
method: 'post',
body: JSON.stringify({ name }),
})
const data = await rsp.json()
if (data.ok) {
location = '/manage'
} else {
console.error(data.error)
}
}
return (
<div className='sans-serif'>
<div className="sans-serif">
<Head>
<title>New API Key</title>
<link rel='icon' href='/favicon.ico' />
<link rel="icon" href="/favicon.ico" />
</Head>
<Navbar user={user} loginUrl={loginUrl} />
<main className='mw9 center bg-nspeach pv3 ph5 min-vh-100'>
<Box bgColor='nsgray' borderColor='nspink' wrapperClassName='center mv4 mw6'>
<h1 className='chicagoflf f4 fw4'>New API Key</h1>
<form action='/keys' method='POST'>
<div className='mv3'>
<label for='name' className='dib mb2'>Name</label>
<input id='name' name='name' placeholder='Give this API key a name' className='db ba b--black w5 pa2' required />
<main className="mw9 center bg-nspeach pv3 ph5 min-vh-100">
<Box
bgColor="nsgray"
borderColor="nspink"
wrapperClassName="center mv4 mw6"
>
<h1 className="chicagoflf f4 fw4">New API Key</h1>
<form onSubmit={createToken}>
<div className="mv3">
<label htmlFor="name" className="dib mb2">
Name
</label>
<input
id="name"
name="name"
placeholder="Give this API key a name"
className="db ba b--black w5 pa2"
required
/>
</div>
<div>
<Button className='bg-nslime' type='submit'>Create</Button>
<Button className="bg-nslime" type="submit">
Create
</Button>
</div>
</form>
</Box>
Expand Down

0 comments on commit 357514e

Please sign in to comment.