post api stacks honors the target environment in the body
This commit is contained in:
1 file changed
+16
-6
@@ -84,9 +84,9 @@ export const GET: RequestHandler = async ({ url, cookies }) => {
|
|||||||
/**
|
/**
|
||||||
* @openapi
|
* @openapi
|
||||||
* summary: Create and (optionally) deploy a compose stack
|
* summary: Create and (optionally) deploy a compose stack
|
||||||
* description: Writes the compose + .env to the stack dir, stores secrets in the DB, and with start deploys it. Can bind a secret provider.
|
* description: Writes the compose + .env to the stack dir, stores secrets in the DB, and with start deploys it. Can bind a secret provider. Target environment comes from the env query param, or from envId/environmentId in the body when the query is absent.
|
||||||
* query: env:integer Target environment id
|
* query: env:integer Target environment id (takes precedence over envId/environmentId in the body)
|
||||||
* body: {name:string!, compose:string!, composePath:string, envPath:string, envVars:array<object>, rawEnvContent:string, secretProviderId:integer, start:boolean}
|
* body: {name:string!, compose:string!, composePath:string, envPath:string, envVars:array<object>, rawEnvContent:string, secretProviderId:integer, start:boolean, envId:integer, environmentId:integer}
|
||||||
* resp-400: Invalid request (e.g. missing name/compose, or secretProviderId wrong type)
|
* resp-400: Invalid request (e.g. missing name/compose, or secretProviderId wrong type)
|
||||||
* resp-403: Permission denied (needs stacks:create; binding a secret provider also needs secrets:view)
|
* resp-403: Permission denied (needs stacks:create; binding a secret provider also needs secrets:view)
|
||||||
* resp-500: Failed to create or deploy the stack
|
* resp-500: Failed to create or deploy the stack
|
||||||
@@ -95,8 +95,19 @@ export const POST: RequestHandler = async (event) => {
|
|||||||
const { request, url, cookies } = event;
|
const { request, url, cookies } = event;
|
||||||
const auth = await authorize(cookies);
|
const auth = await authorize(cookies);
|
||||||
|
|
||||||
const envId = url.searchParams.get('env');
|
let body: any;
|
||||||
const envIdNum = envId ? parseInt(envId) : undefined;
|
try {
|
||||||
|
body = await request.json();
|
||||||
|
} catch {
|
||||||
|
return json({ error: 'Invalid JSON body' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target env: the ?env= query wins (the UI uses it), else fall back to envId /
|
||||||
|
// environmentId in the body so an API caller can target a remote env that way too
|
||||||
|
// (#1491). Resolve BEFORE the permission checks so they scope to the real target.
|
||||||
|
const queryEnv = url.searchParams.get('env');
|
||||||
|
const bodyEnv = body?.envId ?? body?.environmentId;
|
||||||
|
const envIdNum = queryEnv ? parseInt(queryEnv) : (typeof bodyEnv === 'number' ? bodyEnv : undefined);
|
||||||
|
|
||||||
// Permission check with environment context
|
// Permission check with environment context
|
||||||
if (auth.authEnabled && !(await auth.can('stacks', 'create', envIdNum))) {
|
if (auth.authEnabled && !(await auth.can('stacks', 'create', envIdNum))) {
|
||||||
@@ -109,7 +120,6 @@ export const POST: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const body = await request.json();
|
|
||||||
const { name, compose, start, envVars, rawEnvContent, composePath, envPath, secretProviderId } = body;
|
const { name, compose, start, envVars, rawEnvContent, composePath, envPath, secretProviderId } = body;
|
||||||
|
|
||||||
if (!name || typeof name !== 'string') {
|
if (!name || typeof name !== 'string') {
|
||||||
|
|||||||
Reference in new issue
Block a user