358 lines
10 KiB
JavaScript
358 lines
10 KiB
JavaScript
const Joi = require('joi');
|
|
|
|
const uuid = Joi.string().guid({ version: ['uuidv4'] });
|
|
const idParam = Joi.object({ id: uuid.required() }).required();
|
|
const emptyQuery = Joi.object().max(0);
|
|
const entityId = Joi.alternatives().try(
|
|
uuid,
|
|
Joi.object({
|
|
id: uuid.optional(),
|
|
value: uuid.optional(),
|
|
})
|
|
.or('id', 'value')
|
|
.unknown(true),
|
|
);
|
|
|
|
const sortDirection = Joi.string().valid('ASC', 'DESC', 'asc', 'desc');
|
|
|
|
const listQuery = Joi.object({
|
|
limit: Joi.number().integer().min(1).max(1000),
|
|
page: Joi.number().integer().min(1),
|
|
field: Joi.string()
|
|
.trim()
|
|
.max(128)
|
|
.pattern(/^[A-Za-z0-9_.$]+$/),
|
|
sort: sortDirection,
|
|
filetype: Joi.string().valid('csv'),
|
|
})
|
|
.unknown(true)
|
|
.required();
|
|
|
|
const countQuery = listQuery;
|
|
|
|
const autocompleteQuery = Joi.object({
|
|
query: Joi.string().allow('').max(255),
|
|
limit: Joi.number().integer().min(1).max(50),
|
|
offset: Joi.number().integer().min(0),
|
|
})
|
|
.unknown(false)
|
|
.required();
|
|
|
|
const dataEnvelope = Joi.object({
|
|
data: Joi.object().required().unknown(true),
|
|
})
|
|
.unknown(false)
|
|
.required();
|
|
|
|
const updateDataEnvelope = Joi.object({
|
|
id: uuid.optional(),
|
|
data: Joi.object({
|
|
id: uuid.optional(),
|
|
})
|
|
.required()
|
|
.unknown(true),
|
|
})
|
|
.unknown(false)
|
|
.required();
|
|
|
|
const deleteByIdsBody = Joi.object({
|
|
data: Joi.array().items(uuid.required()).min(1).required(),
|
|
})
|
|
.unknown(false)
|
|
.required();
|
|
|
|
const optionalSlug = Joi.string()
|
|
.trim()
|
|
.max(255)
|
|
.pattern(/^[a-z0-9_-]+$/i);
|
|
|
|
const fileUrl = Joi.string().trim().min(1).max(4096);
|
|
|
|
const userData = Joi.object({
|
|
id: uuid.optional(),
|
|
firstName: Joi.string().allow('', null).max(255),
|
|
lastName: Joi.string().allow('', null).max(255),
|
|
phoneNumber: Joi.string().allow('', null).max(255),
|
|
email: Joi.string().trim().email().allow(null),
|
|
disabled: Joi.boolean(),
|
|
password: Joi.string().allow('', null).max(1024),
|
|
emailVerified: Joi.boolean(),
|
|
emailVerificationToken: Joi.string().allow('', null).max(1024),
|
|
emailVerificationTokenExpiresAt: Joi.date().allow(null),
|
|
passwordResetToken: Joi.string().allow('', null).max(1024),
|
|
passwordResetTokenExpiresAt: Joi.date().allow(null),
|
|
provider: Joi.string().allow('', null).max(255),
|
|
importHash: Joi.string().allow('', null).max(255),
|
|
app_role: entityId.allow(null),
|
|
custom_permissions: Joi.array().items(entityId),
|
|
allowed_private_production_project_ids: Joi.array().items(entityId),
|
|
avatar: Joi.any(),
|
|
}).unknown(true);
|
|
|
|
const userCreateData = userData.keys({
|
|
email: Joi.string().trim().email().required(),
|
|
});
|
|
|
|
const projectData = Joi.object({
|
|
id: uuid.optional(),
|
|
name: Joi.string().trim().min(1).max(255),
|
|
slug: optionalSlug,
|
|
description: Joi.string().allow('', null),
|
|
logo_url: Joi.string().allow('', null).max(4096),
|
|
favicon_url: Joi.string().allow('', null).max(4096),
|
|
og_image_url: Joi.string().allow('', null).max(4096),
|
|
design_width: Joi.number().integer().min(1).max(20000).allow(null),
|
|
design_height: Joi.number().integer().min(1).max(20000).allow(null),
|
|
production_presentation_visibility: Joi.string().valid('public', 'private'),
|
|
importHash: Joi.string().allow('', null).max(255),
|
|
}).unknown(true);
|
|
|
|
const projectCreateData = projectData.keys({
|
|
name: Joi.string().trim().min(1).max(255).required(),
|
|
slug: optionalSlug.required(),
|
|
});
|
|
|
|
const uiSchema = Joi.alternatives().try(
|
|
Joi.object({ elements: Joi.array().default([]) }).unknown(true),
|
|
Joi.string().allow('', null),
|
|
Joi.allow(null),
|
|
);
|
|
|
|
const tourPageData = Joi.object({
|
|
id: uuid.optional(),
|
|
project: uuid.optional(),
|
|
projectId: uuid.optional(),
|
|
project_id: uuid.optional(),
|
|
environment: Joi.string().valid('dev', 'stage', 'production'),
|
|
source_key: Joi.string().allow('', null).max(4096),
|
|
name: Joi.string().trim().min(1).max(255),
|
|
slug: optionalSlug,
|
|
sort_order: Joi.number().integer().min(0),
|
|
background_image_url: Joi.string().allow('', null).max(4096),
|
|
background_video_url: Joi.string().allow('', null).max(4096),
|
|
background_embed_url: Joi.string().allow('', null).max(8192),
|
|
background_audio_url: Joi.string().allow('', null).max(4096),
|
|
background_audio_autoplay: Joi.boolean(),
|
|
background_audio_loop: Joi.boolean(),
|
|
background_audio_start_time: Joi.number().min(0).allow(null),
|
|
background_audio_end_time: Joi.number().min(0).allow(null),
|
|
background_loop: Joi.boolean(),
|
|
background_video_autoplay: Joi.boolean(),
|
|
background_video_loop: Joi.boolean(),
|
|
background_video_muted: Joi.boolean(),
|
|
background_video_start_time: Joi.number().min(0).allow(null),
|
|
background_video_end_time: Joi.number().min(0).allow(null),
|
|
design_width: Joi.number().integer().min(1).max(20000).allow(null),
|
|
design_height: Joi.number().integer().min(1).max(20000).allow(null),
|
|
requires_auth: Joi.boolean(),
|
|
ui_schema_json: uiSchema,
|
|
global_ui_controls_settings_json: Joi.alternatives().try(
|
|
Joi.object().unknown(true),
|
|
Joi.string().allow('', null),
|
|
Joi.allow(null),
|
|
),
|
|
importHash: Joi.string().allow('', null).max(255),
|
|
}).unknown(true);
|
|
|
|
const tourPageCreateData = tourPageData
|
|
.keys({
|
|
name: Joi.string().trim().min(1).max(255).required(),
|
|
slug: optionalSlug.required(),
|
|
})
|
|
.or('project', 'projectId', 'project_id');
|
|
|
|
function envelopeForData(dataSchema, { requireData = true } = {}) {
|
|
return Joi.object({
|
|
id: uuid.optional(),
|
|
data: requireData ? dataSchema.required() : dataSchema,
|
|
})
|
|
.unknown(false)
|
|
.required();
|
|
}
|
|
|
|
module.exports = {
|
|
auth: {
|
|
signinLocal: {
|
|
body: Joi.object({
|
|
email: Joi.string().trim().email().required(),
|
|
password: Joi.string().required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
passwordReset: {
|
|
body: Joi.object({
|
|
token: Joi.string().trim().required(),
|
|
password: Joi.string().required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
passwordUpdate: {
|
|
body: Joi.object({
|
|
currentPassword: Joi.string().required(),
|
|
newPassword: Joi.string().required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
sendPasswordResetEmail: {
|
|
body: Joi.object({
|
|
email: Joi.string().trim().email().required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
profile: {
|
|
body: Joi.object({
|
|
profile: Joi.object().required().unknown(true),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
verifyEmail: {
|
|
body: Joi.object({
|
|
token: Joi.string().trim().required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
socialSignin: {
|
|
query: Joi.object({
|
|
app: Joi.string().allow('').max(255),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
},
|
|
crud: {
|
|
create: { body: dataEnvelope },
|
|
update: { params: idParam, body: updateDataEnvelope },
|
|
remove: { params: idParam },
|
|
deleteByIds: { body: deleteByIdsBody },
|
|
list: { query: listQuery },
|
|
count: { query: countQuery },
|
|
autocomplete: { query: autocompleteQuery },
|
|
findOne: { params: idParam },
|
|
},
|
|
file: {
|
|
presign: {
|
|
body: Joi.object({
|
|
urls: Joi.array().items(fileUrl.required()).min(1).max(50).required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
upload: {
|
|
params: Joi.object({
|
|
table: Joi.string()
|
|
.trim()
|
|
.max(128)
|
|
.pattern(/^[A-Za-z0-9_-]+$/)
|
|
.required(),
|
|
field: Joi.string()
|
|
.trim()
|
|
.max(128)
|
|
.pattern(/^[A-Za-z0-9_-]+$/)
|
|
.required(),
|
|
}).required(),
|
|
},
|
|
initUploadSession: {
|
|
body: Joi.object({
|
|
folder: Joi.string().trim().min(1).max(512).required(),
|
|
filename: Joi.string().trim().min(1).max(255).required(),
|
|
totalChunks: Joi.number().integer().min(1).max(10000).required(),
|
|
size: Joi.number().min(0).required(),
|
|
contentType: Joi.string().trim().allow('').max(255),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
session: {
|
|
params: Joi.object({
|
|
sessionId: uuid.required(),
|
|
}).required(),
|
|
},
|
|
chunk: {
|
|
params: Joi.object({
|
|
sessionId: uuid.required(),
|
|
chunkIndex: Joi.number().integer().min(0).max(9999).required(),
|
|
}).required(),
|
|
},
|
|
},
|
|
publish: {
|
|
publish: {
|
|
body: Joi.object({
|
|
projectId: uuid.required(),
|
|
title: Joi.string().allow('', null).max(255),
|
|
description: Joi.string().allow('', null).max(2000),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
saveToStage: {
|
|
body: Joi.object({
|
|
projectId: uuid.required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
},
|
|
projects: {
|
|
create: { body: envelopeForData(projectCreateData) },
|
|
update: { params: idParam, body: envelopeForData(projectData) },
|
|
clone: { params: idParam },
|
|
},
|
|
tourPages: {
|
|
create: { body: envelopeForData(tourPageCreateData) },
|
|
update: { params: idParam, body: envelopeForData(tourPageData) },
|
|
reorder: {
|
|
body: Joi.object({
|
|
data: Joi.object({
|
|
project: uuid.optional(),
|
|
projectId: uuid.optional(),
|
|
environment: Joi.string().valid('dev').default('dev'),
|
|
orderedPageIds: Joi.array().items(uuid.required()).min(1).required(),
|
|
})
|
|
.or('project', 'projectId')
|
|
.required()
|
|
.unknown(false),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
duplicate: {
|
|
params: idParam,
|
|
body: Joi.object({
|
|
data: Joi.object({
|
|
project: uuid.optional(),
|
|
projectId: uuid.optional(),
|
|
environment: Joi.string().valid('dev').default('dev'),
|
|
name: Joi.string().trim().allow('').max(255),
|
|
slug: optionalSlug,
|
|
})
|
|
.unknown(false)
|
|
.default({}),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
reverseVideoStatus: {
|
|
body: Joi.object({
|
|
storageKeys: Joi.array()
|
|
.items(fileUrl.required())
|
|
.min(1)
|
|
.max(200)
|
|
.required(),
|
|
})
|
|
.unknown(false)
|
|
.required(),
|
|
},
|
|
},
|
|
users: {
|
|
create: { body: envelopeForData(userCreateData) },
|
|
update: { params: idParam, body: envelopeForData(userData) },
|
|
},
|
|
emptyQuery,
|
|
};
|