Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Changes for location service hook refactor (#9032)
Browse files Browse the repository at this point in the history
* Updated location hooks

* Updated create result

* Updated test

* Updated search and errors

* Removed location admin

* Added transactions

* Typecasted sceneID

---------

Co-authored-by: HexaField <[email protected]>
Co-authored-by: hanzlamateen <[email protected]>
  • Loading branch information
3 people authored Oct 26, 2023
1 parent 2a06607 commit d265eff
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 315 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,18 @@ const LocationTable = ({ className, search }: Props) => {
query: {
$sort: { name: 1 },
$limit: 20,
adminnedLocations: true,
search: search
$or: [
{
name: {
$like: `%${search}%`
}
},
{
sceneId: {
$like: `%${search}%` as SceneID
}
}
]
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import TableRow from '@etherealengine/ui/src/primitives/mui/TableRow'
import TextField from '@etherealengine/ui/src/primitives/mui/TextField'
import Typography from '@etherealengine/ui/src/primitives/mui/Typography'

import { SceneID } from '@etherealengine/engine/src/schemas/projects/scene.schema'
import { API } from '../../../../API'
import { LocationSeed } from '../../../../social/services/LocationService'
import styles from '../index.module.scss'
Expand Down Expand Up @@ -74,8 +75,18 @@ const LocationMenu = (props: Props) => {
query: {
$limit: rows,
$skip: page * rows,
adminnedLocations: true,
search
$or: [
{
name: {
$like: `%${search}%`
}
},
{
sceneId: {
$like: `%${search}%` as SceneID
}
}
]
}
})
.then((res: Paginated<LocationType>) => {
Expand Down
8 changes: 1 addition & 7 deletions packages/engine/src/schemas/social/location.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,7 @@ export const locationQuerySchema = Type.Intersect(
}
}),
// Add additional query properties here
Type.Object(
{
adminnedLocations: Type.Optional(Type.Boolean()),
search: Type.Optional(Type.String())
},
{ additionalProperties: false }
)
Type.Object({}, { additionalProperties: false })
],
{ additionalProperties: false }
)
Expand Down
2 changes: 1 addition & 1 deletion packages/server-core/src/bot/bot/bot.resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const botResolver = resolve<BotType, HookContext>({})
export const botExternalResolver = resolve<BotType, HookContext>({
location: virtual(async (bot, context) => {
if (context.event !== 'removed' && bot.locationId)
return await context.app.service(locationPath)._get(bot.locationId)
return await context.app.service(locationPath).get(bot.locationId)
}),
instance: virtual(async (bot, context) => {
if (context.event !== 'removed' && bot.instanceId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class InstanceFriendsService implements ServiceInterface<InstanceType, In
.map((instance) => (instance?.locationId ? instance.locationId : undefined))
.filter((instance) => instance !== undefined) as string[]

const locations = (await this.app.service(locationPath)._find({
const locations = (await this.app.service(locationPath).find({
query: {
id: {
$in: locationIds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { fromDateTimeSql, getDateTimeSql } from '../../util/datetime-sql'
export const instanceResolver = resolve<InstanceType, HookContext>({
location: virtual(async (instance, context) => {
if (context.event !== 'removed' && instance.locationId)
return await context.app.service(locationPath)._get(instance.locationId)
return await context.app.service(locationPath).get(instance.locationId)
}),
assignedAt: virtual(async (location) => (location.assignedAt ? fromDateTimeSql(location.assignedAt) : '')),
createdAt: virtual(async (location) => fromDateTimeSql(location.createdAt)),
Expand Down
231 changes: 3 additions & 228 deletions packages/server-core/src/social/location/location.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,10 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20
Ethereal Engine. All Rights Reserved.
*/

import { Id, NullableId, Params } from '@feathersjs/feathers'
import type { KnexAdapterOptions } from '@feathersjs/knex'
import { KnexAdapter } from '@feathersjs/knex'
import { Params } from '@feathersjs/feathers'
import { KnexService } from '@feathersjs/knex'
import { Knex } from 'knex'
import slugify from 'slugify'

import {
locationSettingPath,
LocationSettingType
} from '@etherealengine/engine/src/schemas/social/location-setting.schema'
import {
LocationData,
LocationDatabaseType,
Expand All @@ -42,16 +36,8 @@ import {
LocationType
} from '@etherealengine/engine/src/schemas/social/location.schema'

import { SceneID } from '@etherealengine/engine/src/schemas/projects/scene.schema'
import { locationAdminPath, LocationAdminType } from '@etherealengine/engine/src/schemas/social/location-admin.schema'
import {
locationAuthorizedUserPath,
LocationAuthorizedUserType
} from '@etherealengine/engine/src/schemas/social/location-authorized-user.schema'
import { UserType } from '@etherealengine/engine/src/schemas/user/user.schema'
import { KnexAdapterParams } from '@feathersjs/knex'
import { Application } from '../../../declarations'
import logger from '../../ServerLogger'

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface LocationParams extends KnexAdapterParams<LocationQuery> {}
Expand All @@ -62,223 +48,12 @@ export interface LocationParams extends KnexAdapterParams<LocationQuery> {}

export const locationSettingSorts = ['locationType', 'audioEnabled', 'videoEnabled']

export class LocationService<T = LocationType, ServiceParams extends Params = LocationParams> extends KnexAdapter<
export class LocationService<T = LocationType, ServiceParams extends Params = LocationParams> extends KnexService<
LocationType,
LocationData,
LocationParams,
LocationPatch
> {
app: Application

constructor(options: KnexAdapterOptions, app: Application) {
super(options)
this.app = app
}

async get(id: Id, params?: LocationParams) {
return super._get(id, params)
}

/**
* A function which help to find and display all locations
*
* @param params of query with limit number and skip number
* @returns {@Array} of all locations
*/
async find(params: LocationParams) {
const { adminnedLocations, search } = params.query || {}

if (adminnedLocations && search) {
params.query = {
...params.query,
$or: [
{
name: {
$like: `%${search}%`
}
},
{
sceneId: {
$like: `%${search}%` as SceneID
}
}
]
}
}

const paramsWithoutExtras = {
...params,
// Explicitly cloned sort object because otherwise it was affecting default params object as well.
query: params.query ? JSON.parse(JSON.stringify(params.query)) : {}
}

// Remove extra params
if (paramsWithoutExtras.query?.adminnedLocations) delete paramsWithoutExtras.query.adminnedLocations
if (paramsWithoutExtras.query?.search || paramsWithoutExtras.query?.search === '')
delete paramsWithoutExtras.query.search

// Remove location setting sorts
if (paramsWithoutExtras.query?.$sort) {
for (const sort of locationSettingSorts) {
const hasLocationSettingSort = Object.keys(paramsWithoutExtras.query.$sort).find((item) => item === sort)

if (hasLocationSettingSort) {
delete paramsWithoutExtras.query.$sort[sort]
}
}
}

return super._find(paramsWithoutExtras)
}

/**
* A function which is used to create new location
*
* @param data of location
* @param params
* @returns new location object
*/
async create(data: LocationData, params?: LocationParams) {
const trx = await (this.app.get('knexClient') as Knex).transaction()

try {
const selfUser = params?.user

if (data.isLobby) {
await this.makeLobby(trx, selfUser)
}

data.slugifiedName = slugify(data.name, { lower: true })

const insertData = JSON.parse(JSON.stringify(data))
delete insertData.locationSetting
delete insertData.locationAdmin

await trx.from<LocationDatabaseType>(locationPath).insert(insertData)

await trx.from<LocationSettingType>(locationSettingPath).insert({
...data.locationSetting,
locationId: (data as LocationType).id
})

if ((data as LocationType).locationAdmin) {
await trx.from<LocationAdminType>(locationAdminPath).insert({
...(data as LocationType).locationAdmin,
userId: selfUser?.id,
locationId: (data as LocationType).id
})

await trx.from<LocationAuthorizedUserType>(locationAuthorizedUserPath).insert({
...(data as LocationType).locationAdmin,
userId: selfUser?.id,
locationId: (data as LocationType).id
})
}

await trx.commit()

const location = await this.get((data as LocationType).id)

return location
} catch (err) {
logger.error(err)
await trx.rollback()
if (err.code === 'ER_DUP_ENTRY') {
throw new Error('Name is in use.')
}
throw err
}
}

/**
* A function which is used to update location
*
* @param id of location to update
* @param data of location going to be updated
* @returns updated location
*/
async patch(id: Id, data: LocationPatch, params?: LocationParams) {
const trx = await (this.app.get('knexClient') as Knex).transaction()

try {
const selfUser = params?.user

const oldLocation = await this.app.service(locationPath).get(id)

if (!oldLocation.isLobby && data.isLobby) {
await this.makeLobby(trx, selfUser)
}

if (data.name) {
data.slugifiedName = slugify(data.name, { lower: true })
}

const updateData = JSON.parse(JSON.stringify(data))
delete updateData.locationSetting

await trx.from<LocationDatabaseType>(locationPath).update(updateData).where({ id: id.toString() })

if (data.locationSetting) {
await trx
.from<LocationSettingType>(locationSettingPath)
.update({
videoEnabled: data.locationSetting.videoEnabled,
audioEnabled: data.locationSetting.audioEnabled,
faceStreamingEnabled: data.locationSetting.faceStreamingEnabled,
screenSharingEnabled: data.locationSetting.screenSharingEnabled,
locationType: data.locationSetting.locationType || 'private'
})
.where({ id: oldLocation.locationSetting.id })
}

await trx.commit()

const location = await this.get(id)

return location
} catch (err) {
logger.error(err)
await trx.rollback()
if (err.errors && err.errors[0].message === 'slugifiedName must be unique') {
throw new Error('That name is already in use')
}
throw err
}
}

/**
* A function which is used to remove location
*
* @param id of location which is going to be removed
* @param params which contain user information
* @returns {@function} of remove data
*/
async remove(id: NullableId, params?: LocationParams) {
if (id) {
const location = await this.app.service(locationPath).get(id)

if (location && location.isLobby) {
throw new Error("Lobby can't be deleted")
}

const selfUser = params!.user
if (location.locationSetting) await this.app.service(locationSettingPath).remove(location.locationSetting.id)

try {
await this.app.service(locationAdminPath).remove(null, {
query: {
locationId: id.toString(),
userId: selfUser?.id
}
})
} catch (err) {
logger.error(err, `Could not remove location-admin: ${err.message}`)
}
}

return await super._remove(id, params)
}

async makeLobby(trx: Knex.Transaction, selfUser?: UserType) {
if (!selfUser || !selfUser.scopes || !selfUser.scopes.find((scope) => scope.type === 'admin:admin')) {
throw new Error('Only Admin can set Lobby')
Expand Down
Loading

0 comments on commit d265eff

Please sign in to comment.