Skip to content

Commit

Permalink
fix: put and patch on user collection
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyben committed Jul 21, 2021
1 parent cbb510a commit 4382ef1
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
31 changes: 27 additions & 4 deletions src/__tests__/guards.ts
Expand Up @@ -3,7 +3,7 @@ import { inMemoryJsonServer, USER } from './shared/tools'

let rq: supertest.SuperTest<supertest.Test>
let bearer: { Authorization: string }
let db: { users: any[]; messages: any[] }
let db: { users: any[]; messages: any[]; secrets: any[] }

beforeEach(async () => {
db = {
Expand All @@ -12,17 +12,21 @@ beforeEach(async () => {
{ id: 1, text: 'other', userId: 1 },
{ id: 2, text: 'mine', userId: 2 },
],
secrets: [],
}

const guards = {
users: 600,
messages: 640,
secrets: 600,
}

const app = inMemoryJsonServer(db, guards)
rq = supertest(app)

// Create user (will have id:2) and keep access token
const registerRes = await rq.post('/register').send(USER)
bearer = { Authorization: `Bearer ${registerRes.body.accessToken}` }
const res = await rq.post('/register').send(USER)
bearer = { Authorization: `Bearer ${res.body.accessToken}` }
})

describe('600: owner can read/write', () => {
Expand All @@ -40,6 +44,12 @@ describe('600: owner can read/write', () => {
await rq.get('/users/2').expect(401)
await rq.get('/users/2').set(bearer).expect(200)
})

test('[HAPPY] can write and read from private collection', async () => {
await rq.post('/secrets').set(bearer).send({ size: 'big', userId: '2' }).expect(201)
const res = await rq.get('/secrets/1').set(bearer)
expect(res.body).toEqual({ id: 1, userId: '2', size: 'big' })
})
})

describe('640: owner can read/write, logged can read', () => {
Expand Down Expand Up @@ -73,7 +83,20 @@ describe('640: owner can read/write, logged can read', () => {
})

test('[HAPPY] create another user after setting guards', async () => {
await rq.post('/users').send({ email: 'arthur@email.com', password: '1234' }).expect(201)
const res = await rq
.post('/users')
.send({ email: 'arthur@email.com', password: '1234' })
.expect(201)

const otherBearer = { Authorization: `Bearer ${res.body.accessToken}` }

await rq.get('/users/3').set(otherBearer).expect(200)

await rq
.put('/users/3')
.set(otherBearer)
.send({ email: 'arthur@email.com', password: '1234' })
.expect(200)
})

test('[HAPPY] other methods pass through', async () => {
Expand Down
21 changes: 20 additions & 1 deletion src/guards.ts
Expand Up @@ -71,9 +71,10 @@ const privateOnly: Handler = (req, res, next) => {

// Creation and replacement
// check userId on the request body
if (req.method === 'POST' || req.method === 'PUT') {
if (req.method === 'POST') {
// TODO: use foreignKeySuffix instead of assuming the default "Id"
const hasRightUserId = String(req.body.userId) === req.claims!.sub

// No userId reference when creating a new user (duh)
const isUserResource = resource === 'users'

Expand All @@ -84,6 +85,24 @@ const privateOnly: Handler = (req, res, next) => {
'Private resource creation: request body must have a reference to the owner id'
)
}

return
}

if (req.method === 'PUT') {
// TODO: use foreignKeySuffix instead of assuming the default "Id"
const hasRightUserId = String(req.body.userId) === req.claims!.sub

const isUserResourceAndIsRightId = resource === 'users' && id === req.claims!.sub

if (hasRightUserId || isUserResourceAndIsRightId) {
next()
} else {
res.status(403).jsonp(
'Private resource replacement: request body must have a reference to the owner id'
)
}

return
}

Expand Down
4 changes: 3 additions & 1 deletion src/users.ts
Expand Up @@ -167,12 +167,14 @@ const update: Handler = (req, res, next) => {
/**
* Users router
*/
// Must match routes with and without guards
export default Router()
.use(bodyParsingHandler)
.post('/users|register|signup', validate({ required: true }), create)
// Bypass eventual users guards to still allow creation
.post('/[640]{3}/users', validate({ required: true }), create)
.post('/login|signin', validate({ required: true }), login)
.put('/users/:id', validate({ required: true }), update)
.put('/[640]{3}/users/:id', validate({ required: true }), update)
.patch('/users/:id', validate({ required: false }), update)
.patch('/[640]{3}/users/:id', validate({ required: false }), update)
.use(errorHandler)

0 comments on commit 4382ef1

Please sign in to comment.