Skip to content

Commit

Permalink
feat: Adding HasDeleteRestriction user_tag (#1952)
Browse files Browse the repository at this point in the history
* Adding the type and failing HTTP DELETE operations if this tag is set.
* See nftstorage/admin.storage#66
  • Loading branch information
jsdevel authored Jun 1, 2022
1 parent 1d1bcb5 commit 1d895e0
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TYPE user_tag_type ADD VALUE 'HasDeleteRestriction';
3 changes: 2 additions & 1 deletion packages/api/db/tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ CREATE TYPE auth_key_blocked_status_type AS ENUM (
CREATE TYPE user_tag_type AS ENUM
(
'HasAccountRestriction',
'HasDeleteRestriction',
'HasPsaAccess',
'HasSuperHotAccess',
'StorageLimitBytes'
Expand Down Expand Up @@ -208,4 +209,4 @@ CREATE TABLE IF NOT EXISTS metric
value BIGINT NOT NULL,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
);
1 change: 1 addition & 0 deletions packages/api/src/bindings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export interface Auth {
export interface AuthOptions {
checkUcan?: boolean
checkHasAccountRestriction?: boolean
checkHasDeleteRestriction?: boolean
checkHasPsaAccess?: boolean
}

Expand Down
9 changes: 9 additions & 0 deletions packages/api/src/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ export class ErrorPinningUnauthorized extends HTTPError {
}
ErrorPinningUnauthorized.CODE = 'ERROR_PINNING_UNAUTHORIZED'

export class ErrorDeleteRestricted extends HTTPError {
constructor(msg = 'Delete operations restricted.') {
super(msg, 403)
this.name = 'DeleteRestricted'
this.code = ErrorDeleteRestricted.CODE
}
}
ErrorDeleteRestricted.CODE = 'ERROR_DELETE_RESTRICTED'

export class ErrorAccountRestricted extends HTTPError {
constructor(msg = 'Account restricted.') {
super(msg, 403)
Expand Down
36 changes: 28 additions & 8 deletions packages/api/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ const r = new Router(getContext, {
},
})

const checkHasPsaAccess = true
const checkHasAccountRestriction = true
const checkHasDeleteRestriction = true
const checkHasPsaAccess = true
const checkUcan = true

// Monitoring
Expand Down Expand Up @@ -117,7 +118,10 @@ r.add(
r.add(
'delete',
'/pins/:requestid',
withAuth(withMode(pinsDelete, RW), { checkHasPsaAccess }),
withAuth(withMode(pinsDelete, RW), {
checkHasDeleteRestriction,
checkHasPsaAccess,
}),
[postCors]
)

Expand Down Expand Up @@ -146,7 +150,12 @@ r.add(
withAuth(withMode(nftStore, RW), { checkHasAccountRestriction }),
[postCors]
)
r.add('delete', '/:cid', withAuth(withMode(nftDelete, RW)), [postCors])
r.add(
'delete',
'/:cid',
withAuth(withMode(nftDelete, RW), { checkHasDeleteRestriction }),
[postCors]
)

// Temporary Metaplex upload route, mapped to metaplex user account.
r.add('post', '/metaplex/upload', withMode(metaplexUpload, RW), [postCors])
Expand All @@ -168,9 +177,12 @@ r.add(
withAuth(withMode(tokensCreate, RW), { checkHasAccountRestriction }),
[postCors]
)
r.add('delete', '/internal/tokens', withAuth(withMode(tokensDelete, RW)), [
postCors,
])
r.add(
'delete',
'/internal/tokens',
withAuth(withMode(tokensDelete, RW), { checkHasDeleteRestriction }),
[postCors]
)

// Blog
r.add('post', '/internal/blog/subscribe', blogSubscribe, [postCors])
Expand Down Expand Up @@ -209,7 +221,10 @@ r.add(
r.add(
'delete',
'/api/pins/:requestid',
withAuth(withMode(pinsDelete, RW), { checkHasPsaAccess }),
withAuth(withMode(pinsDelete, RW), {
checkHasDeleteRestriction,
checkHasPsaAccess,
}),
[postCors]
)

Expand All @@ -223,7 +238,12 @@ r.add(
withAuth(withMode(nftUpload, RW), { checkUcan, checkHasAccountRestriction }),
[postCors]
)
r.add('delete', '/api/:cid', withAuth(withMode(nftDelete, RW)), [postCors])
r.add(
'delete',
'/api/:cid',
withAuth(withMode(nftDelete, RW), { checkHasDeleteRestriction }),
[postCors]
)

r.add('all', '*', notFound)
addEventListener('fetch', r.listen.bind(r))
13 changes: 12 additions & 1 deletion packages/api/src/middleware/auth.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ErrorAccountRestricted, ErrorPinningUnauthorized } from '../errors'
import {
ErrorAccountRestricted,
ErrorDeleteRestricted,
ErrorPinningUnauthorized,
} from '../errors'
import { validate } from '../utils/auth'
import { hasTag } from '../utils/utils'

Expand All @@ -19,6 +23,13 @@ export function withAuth(handler, options) {
throw new ErrorAccountRestricted()
}

if (
options?.checkHasDeleteRestriction &&
hasTag(auth.user, 'HasDeleteRestriction', 'true')
) {
throw new ErrorDeleteRestricted()
}

if (
options?.checkHasPsaAccess &&
!hasTag(auth.user, 'HasPsaAccess', 'true')
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/routes/user-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const userTags = async (event, ctx) => {
const tags = {
HasAccountRestriction: hasTag(user, 'HasAccountRestriction', 'true'),
HasPsaAccess: hasTag(user, 'HasPsaAccess', 'true'),
HasDeleteRestriction: hasTag(user, 'HasDeleteRestriction', 'true'),
HasSuperHotAccess: hasTag(user, 'HasSuperHotAccess', 'true'),
StorageLimitBytes: getTagValue(user, 'StorageLimitBytes', ''),
}
Expand Down

0 comments on commit 1d895e0

Please sign in to comment.