Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for schema validation of blueprintConfiguration objects #1223

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions meteor/lib/api/rest/v1/showstyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@
showStyleBaseId: ShowStyleBaseId,
showStyleBase: APIShowStyleBase
): Promise<ClientAPI.ClientResponse<void>>
/**
* Gets a ShowStyle config, if the ShowStyle id exists.
*
* Throws if the specified ShowStyle does not exist.
* @param connection Connection data including client and header details
* @param event User event string
* @param showStyleBaseId ShowStyleBaseId to fetch
*/
getShowStyleConfig(
connection: Meteor.Connection,
event: string,
showStyleBaseId: ShowStyleBaseId
): Promise<ClientAPI.ClientResponse<object>>
/**
* Updates a ShowStyle configuration.
*
* Throws if the ShowStyle is in use in an active Rundown.
* @param connection Connection data including client and header details
* @param event User event string
* @param showStyleBaseId Id of the ShowStyleBase to update
* @param object Blueprint configuration object
*/
updateShowStyleConfig(
connection: Meteor.Connection,
event: string,
showStyleBaseId: ShowStyleBaseId,
config: object
): Promise<ClientAPI.ClientResponse<void>>

Check warning on line 89 in meteor/lib/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/lib/api/rest/v1/showstyles.ts#L62-L89

Added lines #L62 - L89 were not covered by tests
/**
* Removed a ShowStyleBase.
*
Expand Down Expand Up @@ -192,6 +220,7 @@
export interface APIShowStyleVariant {
name: string
showStyleBaseId: string
blueprintConfigPresetId?: string

Check warning on line 223 in meteor/lib/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/lib/api/rest/v1/showstyles.ts#L223

Added line #L223 was not covered by tests
config: object
rank: number
}
Expand Down
28 changes: 28 additions & 0 deletions meteor/lib/api/rest/v1/studios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,34 @@
studioId: StudioId,
studio: APIStudio
): Promise<ClientAPI.ClientResponse<void>>
/**
* Gets a Studio config, if it exists.
*
* Throws if the specified Studio does not exist.
* @param connection Connection data including client and header details
* @param event User event string
* @param studioId Id of the Studio to fetch
*/
getStudioConfig(
connection: Meteor.Connection,
event: string,
studioId: StudioId
): Promise<ClientAPI.ClientResponse<object>>
/**
* Updates a Studio configuration.
*
* Throws if the Studio already exists and is in use in an active Rundown.
* @param connection Connection data including client and header details
* @param event User event string
* @param studioId Id of the Studio to update
* @param object Blueprint configuration object
*/
updateStudioConfig(
connection: Meteor.Connection,
event: string,
studioId: StudioId,
config: object
): Promise<ClientAPI.ClientResponse<void>>

Check warning on line 86 in meteor/lib/api/rest/v1/studios.ts

View check run for this annotation

Codecov / codecov/patch

meteor/lib/api/rest/v1/studios.ts#L59-L86

Added lines #L59 - L86 were not covered by tests
/**
* Deletes a Studio.
*
Expand Down
187 changes: 180 additions & 7 deletions meteor/server/api/rest/v1/showstyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
APIShowStyleVariantFrom,
showStyleBaseFrom,
showStyleVariantFrom,
validateAPIBlueprintConfigForShowStyle,

Check warning on line 23 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L23

Added line #L23 was not covered by tests
} from './typeConversion'
import { Rundown } from '@sofie-automation/corelib/dist/dataModel/Rundown'
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
Expand Down Expand Up @@ -60,16 +61,38 @@
const showStyleBase = await ShowStyleBases.findOneAsync(showStyleBaseId)
if (!showStyleBase) throw new Meteor.Error(404, `ShowStyleBase ${showStyleBaseId} does not exist`)

return ClientAPI.responseSuccess(APIShowStyleBaseFrom(showStyleBase))
return ClientAPI.responseSuccess(await APIShowStyleBaseFrom(showStyleBase))

Check warning on line 64 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L64

Added line #L64 was not covered by tests
}

async addOrUpdateShowStyleBase(
_connection: Meteor.Connection,
_event: string,
showStyleBaseId: ShowStyleBaseId,
showStyleBase: APIShowStyleBase
apiShowStyleBase: APIShowStyleBase

Check warning on line 71 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L71

Added line #L71 was not covered by tests
): Promise<ClientAPI.ClientResponse<void>> {
const showStyle = await showStyleBaseFrom(showStyleBase, showStyleBaseId)
const blueprintConfigValidation = await validateAPIBlueprintConfigForShowStyle(
apiShowStyleBase,
protectString(apiShowStyleBase.blueprintId)
)
const blueprintConfigValidationOK = blueprintConfigValidation.reduce(
(acc, msg) => acc && msg.level === NoteSeverity.INFO,
true
)
if (!blueprintConfigValidationOK) {
const details = JSON.stringify(
blueprintConfigValidation.filter((msg) => msg.level < NoteSeverity.INFO).map((msg) => msg.message.key),
null,
2
)
logger.error(`addOrUpdateShowStyleBase failed blueprint config validation with errors: ${details}`)
throw new Meteor.Error(
409,
`ShowStyleBase ${showStyleBaseId} has failed blueprint config validation`,
details
)
}

const showStyle = await showStyleBaseFrom(apiShowStyleBase, showStyleBaseId)

Check warning on line 95 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L73-L95

Added lines #L73 - L95 were not covered by tests
if (!showStyle) throw new Meteor.Error(400, `Invalid ShowStyleBase`)

const existingShowStyle = await ShowStyleBases.findOneAsync(showStyleBaseId)
Expand Down Expand Up @@ -108,7 +131,104 @@
throw new Meteor.Error(409, `ShowStyleBase ${showStyleBaseId} has failed validation`, details)
}

return ClientAPI.responseSuccess(await runUpgradeForShowStyleBase(showStyleBaseId))
return ClientAPI.responseSuccess(
await new Promise<void>((resolve) =>
// wait for the upsert to complete before upgrade
setTimeout(async () => resolve(await runUpgradeForShowStyleBase(showStyleBaseId)), 200)
)
)
}

async getShowStyleConfig(
_connection: Meteor.Connection,
_event: string,
showStyleBaseId: ShowStyleBaseId
): Promise<ClientAPI.ClientResponse<object>> {
const showStyleBase = await ShowStyleBases.findOneAsync(showStyleBaseId)
if (!showStyleBase) throw new Meteor.Error(404, `ShowStyleBase ${showStyleBaseId} does not exist`)

return ClientAPI.responseSuccess((await APIShowStyleBaseFrom(showStyleBase)).config)
}

async updateShowStyleConfig(
_connection: Meteor.Connection,
_event: string,
showStyleBaseId: ShowStyleBaseId,
config: object
): Promise<ClientAPI.ClientResponse<void>> {
const existingShowStyleBase = await ShowStyleBases.findOneAsync(showStyleBaseId)
if (existingShowStyleBase) {
const existingShowStyle = await ShowStyleBases.findOneAsync(showStyleBaseId)
scriptorian marked this conversation as resolved.
Show resolved Hide resolved
if (existingShowStyle) {
const rundowns = (await Rundowns.findFetchAsync(
{ showStyleBaseId },
{ projection: { playlistId: 1 } }
)) as Array<Pick<Rundown, 'playlistId'>>
const playlists = (await RundownPlaylists.findFetchAsync(
{ _id: { $in: rundowns.map((r) => r.playlistId) } },
{
projection: {
activationId: 1,
},
}
)) as Array<Pick<DBRundownPlaylist, 'activationId'>>
if (playlists.some((playlist) => playlist.activationId !== undefined)) {
throw new Meteor.Error(
412,
`Cannot update ShowStyleBase ${showStyleBaseId} as it is in use by an active Playlist`
)
}
}
} else throw new Meteor.Error(404, `ShowStyleBase ${showStyleBaseId} not found`)

const apiShowStyleBase = await APIShowStyleBaseFrom(existingShowStyleBase)
apiShowStyleBase.config = config

const blueprintConfigValidation = await validateAPIBlueprintConfigForShowStyle(
apiShowStyleBase,
protectString(apiShowStyleBase.blueprintId)
)
const blueprintConfigValidationOK = blueprintConfigValidation.reduce(
(acc, msg) => acc && msg.level === NoteSeverity.INFO,
true
)
if (!blueprintConfigValidationOK) {
const details = JSON.stringify(
blueprintConfigValidation.filter((msg) => msg.level < NoteSeverity.INFO).map((msg) => msg.message.key),
null,
2
)
logger.error(`updateShowStyleBase failed blueprint config validation with errors: ${details}`)
throw new Meteor.Error(
409,
`ShowStyleBase ${showStyleBaseId} has failed blueprint config validation`,
details
)
}
scriptorian marked this conversation as resolved.
Show resolved Hide resolved

const showStyle = await showStyleBaseFrom(apiShowStyleBase, showStyleBaseId)
if (!showStyle) throw new Meteor.Error(400, `Invalid ShowStyleBase`)

await ShowStyleBases.upsertAsync(showStyleBaseId, showStyle)

const validation = await validateConfigForShowStyleBase(showStyleBaseId)
const validateOK = validation.messages.reduce((acc, msg) => acc && msg.level === NoteSeverity.INFO, true)
if (!validateOK) {
const details = JSON.stringify(
validation.messages.filter((msg) => msg.level < NoteSeverity.INFO).map((msg) => msg.message.key),
null,
2
)
logger.error(`addOrUpdateShowStyleBase failed validation with errors: ${details}`)
throw new Meteor.Error(409, `ShowStyleBase ${showStyleBaseId} has failed validation`, details)
}

return ClientAPI.responseSuccess(
await new Promise<void>((resolve) =>
// wait for the upsert to complete before upgrade
setTimeout(async () => resolve(await runUpgradeForShowStyleBase(showStyleBaseId)), 200)
scriptorian marked this conversation as resolved.
Show resolved Hide resolved
)
)

Check warning on line 231 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L134-L231

Added lines #L134 - L231 were not covered by tests
}

async deleteShowStyleBase(
Expand Down Expand Up @@ -185,20 +305,42 @@
const variant = await ShowStyleVariants.findOneAsync(showStyleVariantId)
if (!variant) throw new Meteor.Error(404, `ShowStyleVariant ${showStyleVariantId} not found`)

return ClientAPI.responseSuccess(APIShowStyleVariantFrom(variant))
return ClientAPI.responseSuccess(await APIShowStyleVariantFrom(showStyleBase, variant))

Check warning on line 308 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L308

Added line #L308 was not covered by tests
}

async addOrUpdateShowStyleVariant(
_connection: Meteor.Connection,
_event: string,
showStyleBaseId: ShowStyleBaseId,
showStyleVariantId: ShowStyleVariantId,
showStyleVariant: APIShowStyleVariant
apiShowStyleVariant: APIShowStyleVariant

Check warning on line 316 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L316

Added line #L316 was not covered by tests
): Promise<ClientAPI.ClientResponse<void>> {
const showStyleBase = await ShowStyleBases.findOneAsync(showStyleBaseId)
if (!showStyleBase) throw new Meteor.Error(404, `ShowStyleBase ${showStyleBaseId} does not exist`)

const showStyle = showStyleVariantFrom(showStyleVariant, showStyleVariantId)
const blueprintConfigValidation = await validateAPIBlueprintConfigForShowStyle(
apiShowStyleVariant,
showStyleBase.blueprintId
)
const blueprintConfigValidationOK = blueprintConfigValidation.reduce(
(acc, msg) => acc && msg.level === NoteSeverity.INFO,
true
)
if (!blueprintConfigValidationOK) {
const details = JSON.stringify(
blueprintConfigValidation.filter((msg) => msg.level < NoteSeverity.INFO).map((msg) => msg.message.key),
null,
2
)
logger.error(`addOrUpdateShowStyleVariant failed blueprint config validation with errors: ${details}`)
throw new Meteor.Error(
409,
`ShowStyleBase ${showStyleBaseId} variant has failed blueprint config validation`,
details
)
}

const showStyle = showStyleVariantFrom(apiShowStyleVariant, showStyleVariantId)

Check warning on line 343 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L321-L343

Added lines #L321 - L343 were not covered by tests
if (!showStyle) throw new Meteor.Error(400, `Invalid ShowStyleVariant`)

const existingShowStyle = await ShowStyleVariants.findOneAsync(showStyleVariantId)
Expand Down Expand Up @@ -335,6 +477,37 @@
}
)

registerRoute<{ showStyleBaseId: string }, never, object>(
'get',
'/showstyles/:showStyleBaseId/config',
new Map([[404, [UserErrorMessage.ShowStyleBaseNotFound]]]),
showStylesAPIFactory,
async (serverAPI, connection, event, params, _) => {
const showStyleBaseId = protectString<ShowStyleBaseId>(params.showStyleBaseId)
logger.info(`API GET: ShowStyleBase config ${showStyleBaseId}`)

check(showStyleBaseId, String)
return await serverAPI.getShowStyleConfig(connection, event, showStyleBaseId)
}
)

registerRoute<{ showStyleBaseId: string }, object, void>(
'put',
'/showstyles/:showStyleBaseId/config',
new Map([
[404, [UserErrorMessage.ShowStyleBaseNotFound]],
[409, [UserErrorMessage.ValidationFailed]],
]),
showStylesAPIFactory,
async (serverAPI, connection, event, params, body) => {
const showStyleBaseId = protectString<ShowStyleBaseId>(params.showStyleBaseId)
logger.info(`API PUT: Update ShowStyleBase config ${showStyleBaseId}`)

check(showStyleBaseId, String)
return await serverAPI.updateShowStyleConfig(connection, event, showStyleBaseId, body)
}
)

Check warning on line 510 in meteor/server/api/rest/v1/showstyles.ts

View check run for this annotation

Codecov / codecov/patch

meteor/server/api/rest/v1/showstyles.ts#L480-L510

Added lines #L480 - L510 were not covered by tests
registerRoute<{ showStyleBaseId: string }, never, void>(
'delete',
'/showstyles/:showStyleBaseId',
Expand Down
Loading