## Diff from 2724516
```diff
diff --git a/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts b/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts
index 731467c..2fc1714 100644
--- a/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts
+++ b/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts
@@ -1,9 +1,10 @@
+import Host from '@models/Host.js'
import Place from '@models/Place.js'
import User from '@models/User.js'
-import Host from '@models/Host.js'
+import createHost from '@spec/factories/HostFactory.js'
+import createHostPlace from '@spec/factories/HostPlaceFactory.js'
import createPlace from '@spec/factories/PlaceFactory.js'
import createUser from '@spec/factories/UserFactory.js'
-import createHost from '@spec/factories/HostFactory.js'
import { RequestBody, session, SpecRequestType } from '@spec/unit/helpers/authentication.js'
describe('V1/Host/PlacesController', () => {
@@ -23,7 +24,8 @@ describe('V1/Host/PlacesController', () => {
}
it('returns the index of Places', async () => {
- const place = await createPlace({ host })
+ const place = await createPlace()
+ await createHostPlace({ host, place })
const { body } = await subject(200)
@@ -53,7 +55,8 @@ describe('V1/Host/PlacesController', () => {
}
it('returns the specified Place', async () => {
- const place = await createPlace({ host })
+ const place = await createPlace()
+ await createHostPlace({ host, place })
const { body } = await subject(place, 200)
@@ -79,19 +82,22 @@ describe('V1/Host/PlacesController', () => {
describe('POST create', () => {
const subject = async <StatusCode extends 201 | 400 | 404>(
data: RequestBody<'post', '/v1/host/places'>,
- expectedStatus: StatusCode
+ expectedStatus: StatusCode,
) => {
return request.post('/v1/host/places', expectedStatus, {
- data
+ data,
})
}
it('creates a Place for this Host', async () => {
- const { body } = await subject({
- name: 'The Place name',
- style: 'cottage',
- sleeps: 1,
- }, 201)
+ const { body } = await subject(
+ {
+ name: 'The Place name',
+ style: 'cottage',
+ sleeps: 1,
+ },
+ 201,
+ )
const place = await host.associationQuery('places').firstOrFail()
expect(place.name).toEqual('The Place name')
@@ -113,7 +119,7 @@ describe('V1/Host/PlacesController', () => {
const subject = async <StatusCode extends 204 | 400 | 404>(
place: Place,
data: RequestBody<'patch', '/v1/host/places/{id}'>,
- expectedStatus: StatusCode
+ expectedStatus: StatusCode,
) => {
return request.patch('/v1/host/places/{id}', expectedStatus, {
id: place.id,
@@ -122,13 +128,18 @@ describe('V1/Host/PlacesController', () => {
}
it('updates the Place', async () => {
- const place = await createPlace({ host })
+ const place = await createPlace()
+ await createHostPlace({ host, place })
- await subject(place, {
- name: 'Updated Place name',
- style: 'dump',
- sleeps: 2,
- }, 204)
+ await subject(
+ place,
+ {
+ name: 'Updated Place name',
+ style: 'dump',
+ sleeps: 2,
+ },
+ 204,
+ )
await place.reload()
expect(place.name).toEqual('Updated Place name')
@@ -143,11 +154,15 @@ describe('V1/Host/PlacesController', () => {
const originalStyle = place.style
const originalSleeps = place.sleeps
- await subject(place, {
- name: 'Updated Place name',
- style: 'dump',
- sleeps: 2,
- }, 404)
+ await subject(
+ place,
+ {
+ name: 'Updated Place name',
+ style: 'dump',
+ sleeps: 2,
+ },
+ 404,
+ )
await place.reload()
expect(place.name).toEqual(originalName)
@@ -165,7 +180,8 @@ describe('V1/Host/PlacesController', () => {
}
it('deletes the Place', async () => {
- const place = await createPlace({ host })
+ const place = await createPlace()
+ await createHostPlace({ host, place })
await subject(place, 204)
diff --git a/api/src/app/controllers/AuthedController.ts b/api/src/app/controllers/AuthedController.ts
index fc70d67..3f576e4 100644
--- a/api/src/app/controllers/AuthedController.ts
+++ b/api/src/app/controllers/AuthedController.ts
@@ -1,30 +1,27 @@
import AppEnv from '@conf/AppEnv.js'
import ApplicationController from '@controllers/ApplicationController.js'
+import User from '@models/User.js'
import { Encrypt } from '@rvoh/dream/utils'
import { BeforeAction } from '@rvoh/psychic'
-/** uncomment after creating User model */
-// import User from '@models/User.js'
export default class AuthedController extends ApplicationController {
- /** uncomment after creating User model */
- // protected currentUser: User
+ protected currentUser: User
@BeforeAction()
protected async authenticate() {
- /** uncomment after creating User model */
- // const userId = this.authedUserId()
- // if (!userId) return this.unauthorized()
- //
- // const user = await User.find(userId)
- // if (!user) return this.unauthorized()
- //
- // this.currentUser = user
+ const userId = this.authedUserId()
+ if (!userId) return this.unauthorized()
+
+ const user = await User.find(userId)
+ if (!user) return this.unauthorized()
+
+ this.currentUser = user
}
protected authedUserId(): string | null {
if (!AppEnv.isTest)
throw new Error(
- 'The current authentication scheme is only for early development. Replace with a production grade authentication scheme.'
+ 'The current authentication scheme is only for early development. Replace with a production grade authentication scheme.',
)
const token = (this.req.header('Authorization') ?? '').split(' ').at(-1)!
diff --git a/api/src/app/controllers/V1/Host/BaseController.ts b/api/src/app/controllers/V1/Host/BaseController.ts
index 1a200d0..1f537e5 100644
--- a/api/src/app/controllers/V1/Host/BaseController.ts
+++ b/api/src/app/controllers/V1/Host/BaseController.ts
@@ -1,5 +1,15 @@
+import Host from '@models/Host.js'
+import { BeforeAction } from '@rvoh/psychic'
import V1BaseController from '../BaseController.js'
export default class V1HostBaseController extends V1BaseController {
+ protected currentHost: Host
+ @BeforeAction()
+ protected async loadCurrentHost() {
+ const host = await this.currentUser.associationQuery('host').first()
+ if (!host) return this.forbidden()
+
+ this.currentHost = host
+ }
}
diff --git a/api/src/app/controllers/V1/Host/PlacesController.ts b/api/src/app/controllers/V1/Host/PlacesController.ts
index fb2326a..df0a8f3 100644
--- a/api/src/app/controllers/V1/Host/PlacesController.ts
+++ b/api/src/app/controllers/V1/Host/PlacesController.ts
@@ -1,6 +1,8 @@
+import ApplicationModel from '@models/ApplicationModel.js'
+import HostPlace from '@models/HostPlace.js'
+import Place from '@models/Place.js'
import { OpenAPI } from '@rvoh/psychic'
import V1HostBaseController from './BaseController.js'
-import Place from '@models/Place.js'
const openApiTags = ['places']
@@ -13,11 +15,12 @@ export default class V1HostPlacesController extends V1HostBaseController {
serializerKey: 'summary',
})
public async index() {
- // const places = await this.currentHost.associationQuery('places')
- // .preloadFor('summary')
- // .order({ createdAt: 'desc' })
- // .scrollPaginate({ cursor: this.castParam('cursor', 'string', { allowNull: true }) })
- // this.ok(places)
+ const places = await this.currentHost
+ .associationQuery('places')
+ .preloadFor('summary')
+ .order({ createdAt: 'desc' })
+ .scrollPaginate({ cursor: this.castParam('cursor', 'string', { allowNull: true }) })
+ this.ok(places)
}
@OpenAPI(Place, {
@@ -26,8 +29,8 @@ export default class V1HostPlacesController extends V1HostBaseController {
description: 'Fetch a Place',
})
public async show() {
- // const place = await this.place()
- // this.ok(place)
+ const place = await this.place()
+ this.ok(place)
}
@OpenAPI(Place, {
@@ -36,9 +39,14 @@ export default class V1HostPlacesController extends V1HostBaseController {
description: 'Create a Place',
})
public async create() {
- // let place = await this.currentHost.createAssociation('places', this.paramsFor(Place))
- // if (place.isPersisted) place = await place.loadFor('default').execute()
- // this.created(place)
+ let place = await ApplicationModel.transaction(async txn => {
+ const place = await Place.txn(txn).create(this.paramsFor(Place))
+ await HostPlace.txn(txn).create({ host: this.currentHost, place })
+ return place
+ })
+
+ if (place.isPersisted) place = await place.loadFor('default').execute()
+ this.created(place)
}
@OpenAPI(Place, {
@@ -47,9 +55,9 @@ export default class V1HostPlacesController extends V1HostBaseController {
description: 'Update a Place',
})
public async update() {
- // const place = await this.place()
- // await place.update(this.paramsFor(Place))
- // this.noContent()
+ const place = await this.place()
+ await place.update(this.paramsFor(Place))
+ this.noContent()
}
@OpenAPI({
@@ -58,14 +66,15 @@ export default class V1HostPlacesController extends V1HostBaseController {
description: 'Destroy a Place',
})
public async destroy() {
- // const place = await this.place()
- // await place.destroy()
- // this.noContent()
+ const place = await this.place()
+ await place.destroy()
+ this.noContent()
}
private async place() {
- // return await this.currentHost.associationQuery('places')
- // .preloadFor('default')
- // .findOrFail(this.castParam('id', 'string'))
+ return await this.currentHost
+ .associationQuery('places')
+ .preloadFor('default')
+ .findOrFail(this.castParam('id', 'string'))
}
}