diff --git a/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts b/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts
index 64923d4..830ef03 100644
--- a/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts
+++ b/api/spec/unit/controllers/V1/Host/PlacesController.spec.ts
@@ -1,6 +1,7 @@
import Place from '@models/Place.js'
import User from '@models/User.js'
import Host from '@models/Host.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'
@@ -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 index(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 show(place, 200)
@@ -122,7 +125,8 @@ describe('V1/Host/PlacesController', () => {
}
it('updates the Place', async () => {
- const place = await createPlace({ host })
+ const place = await createPlace()
+ await createHostPlace({ host, place })
await update(place, {
name: 'Updated Place name',
@@ -165,7 +169,8 @@ describe('V1/Host/PlacesController', () => {
}
it('deletes the Place', async () => {
- const place = await createPlace({ host })
+ const place = await createPlace()
+ await createHostPlace({ host, place })
await destroy(place, 204)
diff --git a/api/src/app/controllers/AuthedController.ts b/api/src/app/controllers/AuthedController.ts
index 9714b0f..9bd17df 100644
--- a/api/src/app/controllers/AuthedController.ts
+++ b/api/src/app/controllers/AuthedController.ts
@@ -1,18 +1,15 @@
import ApplicationController from '@controllers/ApplicationController.js'
import resolveCurrentUser from '@controllers/helpers/resolveCurrentUser.js'
+import User from '@models/User.js'
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() {
const user = await resolveCurrentUser(this)
if (!user) return this.unauthorized()
- /** uncomment after creating User model */
- // this.currentUser = user
+ this.currentUser = user
}
}
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 e3399a7..ebafde5 100644
--- a/api/src/app/controllers/V1/Host/PlacesController.ts
+++ b/api/src/app/controllers/V1/Host/PlacesController.ts
@@ -1,5 +1,7 @@
import { OpenAPI } from '@rvoh/psychic'
import { DreamParamSafeColumnNames } from '@rvoh/dream/types'
+import ApplicationModel from '@models/ApplicationModel.js'
+import HostPlace from '@models/HostPlace.js'
import V1HostBaseController from './BaseController.js'
import Place from '@models/Place.js'
@@ -17,10 +19,11 @@ export default class V1HostPlacesController extends V1HostBaseController {
fastJsonStringify: true,
})
public async index() {
- // const places = await this.currentHost.associationQuery('places')
- // .preloadFor('summary')
- // .cursorPaginate({ cursor: this.castParam('cursor', 'string', { allowNull: true }) })
- // this.ok(places)
+ const places = await this.currentHost
+ .associationQuery('places')
+ .preloadFor('summary')
+ .cursorPaginate({ cursor: this.castParam('cursor', 'string', { allowNull: true }) })
+ this.ok(places)
}
@OpenAPI(Place, {
@@ -30,8 +33,8 @@ export default class V1HostPlacesController extends V1HostBaseController {
fastJsonStringify: true,
})
public async show() {
- // const place = await this.place()
- // this.ok(place)
+ const place = await this.place()
+ this.ok(place)
}
@OpenAPI(Place, {
@@ -44,9 +47,14 @@ export default class V1HostPlacesController extends V1HostBaseController {
},
})
public async create() {
- // let place = await this.currentHost.createAssociation('places', this.extractParams(Place, paramSafeColumns))
- // 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.extractParams(Place, paramSafeColumns))
+ 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, {
@@ -59,9 +67,9 @@ export default class V1HostPlacesController extends V1HostBaseController {
},
})
public async update() {
- // const place = await this.place()
- // await place.update(this.extractParams(Place, paramSafeColumns))
- // this.noContent()
+ const place = await this.place()
+ await place.update(this.extractParams(Place, paramSafeColumns))
+ this.noContent()
}
@OpenAPI({
@@ -71,14 +79,15 @@ export default class V1HostPlacesController extends V1HostBaseController {
fastJsonStringify: true,
})
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', 'uuid'))
}
}
diff --git a/api/src/app/controllers/helpers/resolveCurrentUser.ts b/api/src/app/controllers/helpers/resolveCurrentUser.ts
index 0d6f1aa..24084aa 100644
--- a/api/src/app/controllers/helpers/resolveCurrentUser.ts
+++ b/api/src/app/controllers/helpers/resolveCurrentUser.ts
@@ -1,16 +1,12 @@
import AppEnv from '@conf/AppEnv.js'
+import User from '@models/User.js'
import { Encrypt } from '@rvoh/dream/utils'
import { PsychicController } from '@rvoh/psychic'
-/** uncomment after creating User model */
-// import User from '@models/User.js'
-// eslint-disable-next-line @typescript-eslint/require-await
-export default async function resolveCurrentUser(controller: PsychicController): Promise<string | null> {
- /** replace previous line with uncommented next line after creating User model */
- // export default async function resolveCurrentUser(controller: PsychicController): Promise<User | null> {
+export default async function resolveCurrentUser(controller: PsychicController): Promise<User | 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 = (controller.header('authorization') ?? '').split(' ').at(-1)!
@@ -20,11 +16,8 @@ export default async function resolveCurrentUser(controller: PsychicController):
key: AppEnv.string('APP_ENCRYPTION_KEY'),
})
- const userId =
- typeof decrypted === 'string' && (JSON.parse(decrypted) as Record<'userId', string>)?.userId
+ const userId = typeof decrypted === 'string' && (JSON.parse(decrypted) as Record<'userId', string>)?.userId
if (!userId) return null
- /** uncomment after creating User model */
- // return await User.find(userId)
- return userId
+ return await User.find(userId)
}