import { test } from '@japa/runner' import { DateTime } from 'luxon' import User from '#models/user' import Component from '#models/component' import ComponentType from '#models/component_type' async function createUser(email: string) { return User.create({ name: 'Test User', email, password: 'secret@123A', }) } async function createType(name: string, unique = true) { return ComponentType.firstOrCreate({ name }, { name, unique }) } async function createComponent(userId: number, typeId: number) { return Component.create({ name: 'Test Component', price: 20, typeId, userId, computerId: null, purchaseDate: DateTime.now(), }) } test.group('Components authorization (IDOR)', () => { test('owner can update their own component', async ({ client, assert }) => { const owner = await createUser('owner-comp-update@example.com') const type = await createType('RAM-comp-1') const component = await createComponent(owner.id, type.id) const response = await client .put(`/components/${component.id}`) .loginAs(owner) .withCsrfToken() .redirects(0) .json({ name: 'Updated name', price: 30, typeId: type.id, purchaseDate: DateTime.now().toFormat('yyyy-MM-dd'), }) response.assertStatus(302) await component.refresh() assert.equal(component.name, 'Updated name') }) test('a user cannot update another user component', async ({ client, assert }) => { const owner = await createUser('owner-comp-a@example.com') const attacker = await createUser('attacker-comp-a@example.com') const type = await createType('RAM-comp-2') const component = await createComponent(owner.id, type.id) const response = await client .put(`/components/${component.id}`) .loginAs(attacker) .withCsrfToken() .redirects(0) .json({ name: 'Hacked name', price: 1, typeId: type.id, purchaseDate: DateTime.now().toFormat('yyyy-MM-dd'), }) response.assertStatus(404) await component.refresh() assert.notEqual(component.name, 'Hacked name') }) test('a user cannot delete another user component', async ({ client, assert }) => { const owner = await createUser('owner-comp-b@example.com') const attacker = await createUser('attacker-comp-b@example.com') const type = await createType('RAM-comp-3') const component = await createComponent(owner.id, type.id) const response = await client .delete(`/components/${component.id}`) .loginAs(attacker) .withCsrfToken() .redirects(0) response.assertStatus(404) const stillExists = await Component.find(component.id) assert.isNotNull(stillExists) }) test('an unauthenticated request cannot delete a component', async ({ client, assert }) => { const owner = await createUser('owner-comp-c@example.com') const type = await createType('RAM-comp-4') const component = await createComponent(owner.id, type.id) const response = await client.delete(`/components/${component.id}`) response.assertRedirectsTo('/auth/login') const stillExists = await Component.find(component.id) assert.isNotNull(stillExists) }) })