|
|
@ -12,14 +12,14 @@ import { Server, IncomingMessage, ServerResponse } from 'http' |
|
|
|
import pick from 'lodash/pick' |
|
|
|
|
|
|
|
import { appSchema, errorSchema } from '../../schemas' |
|
|
|
import { getUsers, userIdIsValid, userIsValid, updateItem } from '../../lib/collections' |
|
|
|
import { getUsers, userIdIsValid, userIsValid, updateItem, getUser } from '../../lib/collections' |
|
|
|
import { generateString } from '../../lib/crypto' |
|
|
|
import { containerFor, getItem, normalize, queryItems, createQuerySpec } from '../../lib/database' |
|
|
|
import { unauthorizedError, serverError, badRequestError, notFoundError, forbiddenError } from '../../lib/errors' |
|
|
|
import { attachMedia, deleteMedia } from '../../lib/media' |
|
|
|
import { createInstallationId } from '../../lib/utils' |
|
|
|
|
|
|
|
import { APP_PARTITION_KEY, MAX_NAME_LENGTH, INSTALLATION_PARTITION_KEY } from '../../constants' |
|
|
|
import { APP_PARTITION_KEY, MAX_NAME_LENGTH, INSTALLATION_PARTITION_KEY, ADMINS } from '../../constants' |
|
|
|
import { App, User, Installation, InstallationSettings } from '../../types/collections' |
|
|
|
import { PluginOptions } from '../../types' |
|
|
|
|
|
|
@ -754,11 +754,68 @@ function installationsRoute(server: FastifyInstance<Server, IncomingMessage, Ser |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
function activateRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) { |
|
|
|
interface Headers { |
|
|
|
adminkey: string |
|
|
|
function pendingRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) { |
|
|
|
interface Query { |
|
|
|
continuation?: string |
|
|
|
} |
|
|
|
|
|
|
|
const options: RouteShorthandOptions = { |
|
|
|
schema: { |
|
|
|
description: 'Get Apps awaiting activation.', |
|
|
|
tags: ['app', 'admin'], |
|
|
|
querystring: { |
|
|
|
type: 'object', |
|
|
|
properties: { |
|
|
|
continuation: { type: 'string' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
response: { |
|
|
|
200: { |
|
|
|
description: 'Successful response.', |
|
|
|
type: 'object', |
|
|
|
properties: { |
|
|
|
apps: { |
|
|
|
type: 'array', |
|
|
|
items: appSchema, |
|
|
|
}, |
|
|
|
continuation: { type: 'string' }, |
|
|
|
} |
|
|
|
}, |
|
|
|
400: errorSchema, |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
server.get<Query, DefaultParams, DefaultHeaders, DefaultBody>('/v1/apps/pending', options, async (request, reply) => { |
|
|
|
if (!server.database) return serverError(reply) |
|
|
|
if (!request.viewer) return unauthorizedError(reply) |
|
|
|
|
|
|
|
const viewer = await getUser(server.database.client, request.viewer.id) |
|
|
|
if (!viewer || !ADMINS.includes(viewer.email)) return forbiddenError(reply) |
|
|
|
|
|
|
|
const { continuation } = request.query |
|
|
|
const container = containerFor(server.database.client, 'Apps') |
|
|
|
|
|
|
|
const { resources: apps, requestCharge, continuation: newContinuation } = await container.items.query<App>( |
|
|
|
createQuerySpec('SELECT * FROM Apps a WHERE a.pk = @pk AND a.active = false', { |
|
|
|
pk: APP_PARTITION_KEY, |
|
|
|
}), |
|
|
|
{ |
|
|
|
maxItemCount: 20, |
|
|
|
continuation, |
|
|
|
} |
|
|
|
).fetchAll() |
|
|
|
|
|
|
|
request.log.trace('Query: %d', requestCharge) |
|
|
|
|
|
|
|
return { |
|
|
|
apps, |
|
|
|
continuation: newContinuation, |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
function activateRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) { |
|
|
|
interface Params { |
|
|
|
id: string |
|
|
|
} |
|
|
@ -766,14 +823,7 @@ function activateRoute(server: FastifyInstance<Server, IncomingMessage, ServerRe |
|
|
|
const options: RouteShorthandOptions = { |
|
|
|
schema: { |
|
|
|
description: 'Activate an App.', |
|
|
|
tags: ['app'], |
|
|
|
headers: { |
|
|
|
type: 'object', |
|
|
|
required: ['adminkey'], |
|
|
|
properties: { |
|
|
|
'adminkey': { type: 'string' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
tags: ['app', 'admin'], |
|
|
|
params: { |
|
|
|
type: 'object', |
|
|
|
properties: { |
|
|
@ -790,9 +840,12 @@ function activateRoute(server: FastifyInstance<Server, IncomingMessage, ServerRe |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
server.post<DefaultQuery, Params, Headers, DefaultBody>('/v1/app/:id/activate', options, async (request, reply) => { |
|
|
|
server.post<DefaultQuery, Params, DefaultHeaders, DefaultBody>('/v1/app/:id/activate', options, async (request, reply) => { |
|
|
|
if (!server.database) return serverError(reply) |
|
|
|
if (request.headers.adminkey !== process.env.ADMIN_KEY) return serverError(reply) |
|
|
|
if (!request.viewer) return unauthorizedError(reply) |
|
|
|
|
|
|
|
const viewer = await getUser(server.database.client, request.viewer.id) |
|
|
|
if (!viewer || !ADMINS.includes(viewer.email)) return forbiddenError(reply) |
|
|
|
|
|
|
|
await updateItem<App>(containerFor(server.database.client, 'Apps').item(request.params.id, APP_PARTITION_KEY), { active: true }) |
|
|
|
reply.code(204) |
|
|
@ -800,10 +853,6 @@ function activateRoute(server: FastifyInstance<Server, IncomingMessage, ServerRe |
|
|
|
} |
|
|
|
|
|
|
|
function setPreinstallRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) { |
|
|
|
interface Headers { |
|
|
|
adminkey: string |
|
|
|
} |
|
|
|
|
|
|
|
interface Params { |
|
|
|
id: string |
|
|
|
} |
|
|
@ -811,14 +860,7 @@ function setPreinstallRoute(server: FastifyInstance<Server, IncomingMessage, Ser |
|
|
|
const options: RouteShorthandOptions = { |
|
|
|
schema: { |
|
|
|
description: 'Update an App to be preinstalled on new User accounts.', |
|
|
|
tags: ['app'], |
|
|
|
headers: { |
|
|
|
type: 'object', |
|
|
|
required: ['adminkey'], |
|
|
|
properties: { |
|
|
|
adminkey: { type: 'string' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
tags: ['app', 'admin'], |
|
|
|
params: { |
|
|
|
type: 'object', |
|
|
|
properties: { |
|
|
@ -837,7 +879,14 @@ function setPreinstallRoute(server: FastifyInstance<Server, IncomingMessage, Ser |
|
|
|
|
|
|
|
server.post<DefaultQuery, Params, Headers, DefaultBody>('/v1/app/:id/preinstall', options, async (request, reply) => { |
|
|
|
if (!server.database) return serverError(reply) |
|
|
|
if (request.headers.adminkey !== process.env.ADMIN_KEY) return serverError(reply) |
|
|
|
if (!request.viewer) return unauthorizedError(reply) |
|
|
|
|
|
|
|
const viewer = await getItem<User>({ |
|
|
|
container: containerFor(server.database.client, 'Users'), |
|
|
|
id: request.viewer.id, |
|
|
|
}) |
|
|
|
|
|
|
|
if (!viewer || !ADMINS.includes(viewer.email)) return forbiddenError(reply) |
|
|
|
|
|
|
|
await updateItem<App>(containerFor(server.database.client, 'Apps').item(request.params.id, APP_PARTITION_KEY), { |
|
|
|
preinstall: true, |
|
|
|