diff --git a/.env.tpl b/.env.tpl index 7346843dfb..5987f86695 100644 --- a/.env.tpl +++ b/.env.tpl @@ -37,7 +37,7 @@ PICKUP_BASIC_AUTH_TOKEN = dGVzdDp0ZXN0 PICKUP_API_URL = http://127.0.0.1:9094 # Maintenance Mode -MAINTENANCE_MODE = rw +MAINTENANCE_MODE = r-- # S3 S3_ENDPOINT = http://127.0.0.1:9000 diff --git a/packages/api/src/index.js b/packages/api/src/index.js index 1ef0931dfa..b94a2ad9ab 100644 --- a/packages/api/src/index.js +++ b/packages/api/src/index.js @@ -31,7 +31,8 @@ import { getServiceConfig } from './config.js' import { withMode, READ_ONLY as RO, - READ_WRITE as RW, + READ_WRITE_ONLY as RW, + READ_WRITE_CREATE as RWC, } from './middleware/maintenance.js' import { getContext } from './utils/context.js' import { withAuth } from './middleware/auth.js' @@ -96,7 +97,7 @@ r.add( r.add( 'post', '/pins', - withAuth(withMode(pinsAdd, RW), { + withAuth(withMode(pinsAdd, RWC), { checkHasPsaAccess, checkHasAccountRestriction, }), @@ -105,7 +106,7 @@ r.add( r.add( 'post', '/pins/:requestid', - withAuth(withMode(pinsReplace, RW), { + withAuth(withMode(pinsReplace, RWC), { checkHasPsaAccess, checkHasAccountRestriction, }), @@ -114,7 +115,7 @@ r.add( r.add( 'delete', '/pins/:requestid', - withAuth(withMode(pinsDelete, RW), { + withAuth(withMode(pinsDelete, RWC), { checkHasDeleteRestriction, checkHasPsaAccess, }), @@ -128,7 +129,7 @@ r.add('get', '/:cid', withAuth(withMode(nftGet, RO)), [postCors]) r.add( 'post', '/upload', - withAuth(withMode(nftUpload, RW), { + withAuth(withMode(nftUpload, RWC), { checkHasAccountRestriction, checkUcan, }), @@ -137,24 +138,24 @@ r.add( r.add( 'patch', '/upload/:cid', - withAuth(withMode(nftUpdateUpload, RW), { checkHasAccountRestriction }), + withAuth(withMode(nftUpdateUpload, RWC), { checkHasAccountRestriction }), [postCors] ) r.add( 'post', '/store', - withAuth(withMode(nftStore, RW), { checkHasAccountRestriction }), + withAuth(withMode(nftStore, RWC), { checkHasAccountRestriction }), [postCors] ) r.add( 'delete', '/:cid', - withAuth(withMode(nftDelete, RW), { checkHasDeleteRestriction }), + withAuth(withMode(nftDelete, RWC), { checkHasDeleteRestriction }), [postCors] ) // Temporary Metaplex upload route, mapped to metaplex user account. -r.add('post', '/metaplex/upload', withMode(metaplexUpload, RW), [postCors]) +r.add('post', '/metaplex/upload', withMode(metaplexUpload, RWC), [postCors]) // User r.add( @@ -206,7 +207,7 @@ r.add( r.add( 'post', '/api/pins', - withAuth(withMode(pinsAdd, RW), { + withAuth(withMode(pinsAdd, RWC), { checkHasPsaAccess, checkHasAccountRestriction, }), @@ -215,7 +216,7 @@ r.add( r.add( 'post', '/api/pins/:requestid', - withAuth(withMode(pinsReplace, RW), { + withAuth(withMode(pinsReplace, RWC), { checkHasPsaAccess, checkHasAccountRestriction, }), @@ -224,7 +225,7 @@ r.add( r.add( 'delete', '/api/pins/:requestid', - withAuth(withMode(pinsDelete, RW), { + withAuth(withMode(pinsDelete, RWC), { checkHasDeleteRestriction, checkHasPsaAccess, }), @@ -238,13 +239,13 @@ r.add('get', '/api/:cid', withAuth(withMode(nftGet, RO)), [postCors]) r.add( 'post', '/api/upload', - withAuth(withMode(nftUpload, RW), { checkUcan, checkHasAccountRestriction }), + withAuth(withMode(nftUpload, RWC), { checkUcan, checkHasAccountRestriction }), [postCors] ) r.add( 'delete', '/api/:cid', - withAuth(withMode(nftDelete, RW), { checkHasDeleteRestriction }), + withAuth(withMode(nftDelete, RWC), { checkHasDeleteRestriction }), [postCors] ) diff --git a/packages/api/src/middleware/maintenance.js b/packages/api/src/middleware/maintenance.js index ab0e4f2daa..d96f252e02 100644 --- a/packages/api/src/middleware/maintenance.js +++ b/packages/api/src/middleware/maintenance.js @@ -2,32 +2,42 @@ import { ErrorMaintenance, HTTPError } from '../errors.js' import { getServiceConfig } from '../config.js' /** - * @typedef {'rw' | 'r-' | '--'} Mode + * @typedef {'rwc' | 'rw-' | 'r--' | '---'} Mode * @typedef {import('../bindings').Handler} Handler */ +/** + * Read and write and create + */ +export const READ_WRITE_CREATE = 'rwc' + /** * Read and write. */ -export const READ_WRITE = 'rw' +export const READ_WRITE_ONLY = 'rw-' /** * Read only mode. */ -export const READ_ONLY = 'r-' +export const READ_ONLY = 'r--' /** * No reading or writing. */ -export const NO_READ_OR_WRITE = '--' +export const NO_READ_OR_WRITE = '---' /** @type {readonly Mode[]} */ -export const modes = Object.freeze([NO_READ_OR_WRITE, READ_ONLY, READ_WRITE]) +export const modes = Object.freeze([ + NO_READ_OR_WRITE, + READ_ONLY, + READ_WRITE_ONLY, + READ_WRITE_CREATE, +]) /** * The default maintenance mode (normal operation). */ -export const DEFAULT_MODE = READ_WRITE +export const DEFAULT_MODE = READ_WRITE_CREATE /** @type {() => Mode} */ let getMaintenanceMode = () => getServiceConfig().MAINTENANCE_MODE diff --git a/packages/api/test/maintenance.spec.js b/packages/api/test/maintenance.spec.js index 505f31ad6a..086575bd2a 100644 --- a/packages/api/test/maintenance.spec.js +++ b/packages/api/test/maintenance.spec.js @@ -1,7 +1,7 @@ import test from 'ava' import { READ_ONLY, - READ_WRITE, + READ_WRITE_ONLY, NO_READ_OR_WRITE, } from '../src/middleware/maintenance.js' import { createClientWithUser } from './scripts/helpers.js' @@ -46,7 +46,7 @@ test('maintenance middleware should throw error when in maintenance mode', async const expectedError = { message: /API undergoing maintenance/ } - await setMode(t, READ_WRITE) + await setMode(t, READ_WRITE_ONLY) await t.notThrowsAsync(tryRead(t, token)) await t.notThrowsAsync(tryWrite(t, token))