import joi from '@hapi/joi'; import { createHash } from 'crypto'; import { Request, Response } from 'express'; import { logger } from '../logger'; import latestSchema from '../schemas/share-latest'; import { storage } from '../storage'; interface ShareBody { editor: { language: string; code: string; dirty: boolean; title: string; }; compile: { entrypoint: string; }; dryRun: { entrypoint: string; parameters: string; storage: string; }; deploy: { entrypoint: string; storage: string; useTezBridge?: boolean; }; evaluateValue: { entrypoint: string; }; evaluateFunction: { entrypoint: string; parameters: string; }; } const validateRequest = (body: any): { value: ShareBody; error: any } => { return joi .object({ editor: joi .object({ language: joi.string().required(), code: joi.string().required(), dirty: joi.boolean().optional(), title: joi.string().allow('') }) .required(), compile: joi.object({ entrypoint: joi.string().allow('') }), dryRun: joi.object({ entrypoint: joi.string().allow(''), parameters: joi.any().allow(''), storage: joi.any().allow('') }), deploy: joi.object({ entrypoint: joi.string().allow(''), storage: joi.any().allow(''), useTezBridge: joi.boolean().optional() }), evaluateValue: joi.object({ entrypoint: joi.string().allow('') }), evaluateFunction: joi.object({ entrypoint: joi.string().allow(''), parameters: joi.any().allow('') }) }) .validate(body); }; function escapeUrl(str: string) { return str .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=/g, ''); } export async function shareHandler(req: Request, res: Response) { const { error, value } = validateRequest(req.body); if (error) { res.status(400).json({ error: error.message }); } else { try { const versionedShareState = { version: latestSchema.VERSION, state: value }; const { error } = latestSchema.validate(versionedShareState); if (error) { logger.error( `${versionedShareState} doesn't match latest schema ${latestSchema.VERSION}` ); res.sendStatus(500); } else { const fileContent = JSON.stringify(versionedShareState); const hash = createHash('md5'); hash.update(fileContent); const digest = escapeUrl(hash.digest('base64')); const filename = `${digest}.txt`; storage.write(filename, fileContent); res.send({ hash: digest }); } } catch (ex) { logger.error(ex); res.sendStatus(500); } } }