mirror of
https://github.com/pockethost/pockethost.git
synced 2025-06-27 16:32:32 +00:00
feat: delete instance
This commit is contained in:
parent
8f89dd070b
commit
00477b3c11
@ -1,5 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
CreateInstancePayloadSchema,
|
CreateInstancePayloadSchema,
|
||||||
|
DeleteInstancePayload,
|
||||||
|
DeleteInstancePayloadSchema,
|
||||||
|
DeleteInstanceResult,
|
||||||
RestCommands,
|
RestCommands,
|
||||||
RestMethods,
|
RestMethods,
|
||||||
UpdateInstancePayload,
|
UpdateInstancePayload,
|
||||||
@ -104,6 +107,12 @@ export const createPocketbaseClient = (config: PocketbaseClientConfig) => {
|
|||||||
UpdateInstancePayloadSchema,
|
UpdateInstancePayloadSchema,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const deleteInstance = mkRest<DeleteInstancePayload, DeleteInstanceResult>(
|
||||||
|
RestCommands.Instance,
|
||||||
|
RestMethods.Delete,
|
||||||
|
DeleteInstancePayloadSchema,
|
||||||
|
)
|
||||||
|
|
||||||
const getInstanceById = (
|
const getInstanceById = (
|
||||||
id: InstanceId,
|
id: InstanceId,
|
||||||
): Promise<InstanceFields | undefined> =>
|
): Promise<InstanceFields | undefined> =>
|
||||||
@ -271,5 +280,6 @@ export const createPocketbaseClient = (config: PocketbaseClientConfig) => {
|
|||||||
getAllInstancesById,
|
getAllInstancesById,
|
||||||
resendVerificationEmail,
|
resendVerificationEmail,
|
||||||
updateInstance,
|
updateInstance,
|
||||||
|
deleteInstance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
import Code from './Code.svelte'
|
import Code from './Code.svelte'
|
||||||
import AdminSync from './Danger/AdminSync.svelte'
|
import AdminSync from './Danger/AdminSync.svelte'
|
||||||
import DangerZoneTitle from './Danger/DangerZoneTitle.svelte'
|
import DangerZoneTitle from './Danger/DangerZoneTitle.svelte'
|
||||||
|
import DeleteInstance from './Danger/DeleteInstance.svelte'
|
||||||
import Maintenance from './Danger/Maintenance.svelte'
|
import Maintenance from './Danger/Maintenance.svelte'
|
||||||
import RenameInstance from './Danger/RenameInstance.svelte'
|
import RenameInstance from './Danger/RenameInstance.svelte'
|
||||||
import VersionChange from './Danger/VersionChange/VersionChange.svelte'
|
import VersionChange from './Danger/VersionChange/VersionChange.svelte'
|
||||||
@ -87,4 +88,6 @@
|
|||||||
<VersionChange />
|
<VersionChange />
|
||||||
|
|
||||||
<AdminSync />
|
<AdminSync />
|
||||||
|
|
||||||
|
<DeleteInstance />
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { goto } from '$app/navigation'
|
||||||
|
import Card from '$components/cards/Card.svelte'
|
||||||
|
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||||
|
import { DOCS_URL } from '$src/env'
|
||||||
|
import { client } from '$src/pocketbase-client'
|
||||||
|
import { globalInstancesStore } from '$util/stores'
|
||||||
|
import { instance } from '../store'
|
||||||
|
import ErrorMessage from './ErrorMessage.svelte'
|
||||||
|
|
||||||
|
$: ({ id, maintenance, version } = $instance)
|
||||||
|
|
||||||
|
// Create a copy of the version
|
||||||
|
let selectedVersion = version
|
||||||
|
$: {
|
||||||
|
selectedVersion = version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controls the disabled state of the button
|
||||||
|
let isButtonDisabled = false
|
||||||
|
|
||||||
|
// Controls visibility of an error message
|
||||||
|
let errorMessage = ''
|
||||||
|
|
||||||
|
// Update the version number
|
||||||
|
const handleSave = async (e: Event) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
// Disable the button to prevent double submissions
|
||||||
|
isButtonDisabled = true
|
||||||
|
|
||||||
|
// Prompt the user to confirm the version change
|
||||||
|
const confirmVersionChange = confirm(
|
||||||
|
`LAST CHANCE - Are you sure you want to delete this instance? Your database, all local files, logs, and subdomain will be lost.`,
|
||||||
|
)
|
||||||
|
|
||||||
|
// If they select yes, then update the version in pocketbase
|
||||||
|
if (confirmVersionChange) {
|
||||||
|
errorMessage = ''
|
||||||
|
client()
|
||||||
|
.deleteInstance({
|
||||||
|
id,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
globalInstancesStore.update((instances) => {
|
||||||
|
const newInstances = { ...instances }
|
||||||
|
delete newInstances[id]
|
||||||
|
return newInstances
|
||||||
|
})
|
||||||
|
goto('/')
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
errorMessage = error.data.message || error.message
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// If they hit cancel, reset the version number back to what it was initially
|
||||||
|
selectedVersion = version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the button back to normal
|
||||||
|
isButtonDisabled = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader documentation={DOCS_URL(`/usage/delete`)}>
|
||||||
|
Delete Instance
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<div class="mb-8">
|
||||||
|
Deleting your instance will immediately and permanently delete your
|
||||||
|
instance:
|
||||||
|
<ul class="ml-10 text-error">
|
||||||
|
<li>Your subdomain</li>
|
||||||
|
<li><pre>pb_data/*</pre></li>
|
||||||
|
<li><pre>pb_public/*</pre></li>
|
||||||
|
<li><pre>pb_migrations/*</pre></li>
|
||||||
|
<li><pre>pb_static/*</pre></li>
|
||||||
|
</ul>
|
||||||
|
If you are storing files on S3, you must delete them separately.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ErrorMessage message={errorMessage} />
|
||||||
|
|
||||||
|
<form
|
||||||
|
class="flex change-version-form-container-query gap-4"
|
||||||
|
on:submit={handleSave}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-error"
|
||||||
|
disabled={!maintenance || isButtonDisabled}>Delete Instance</button
|
||||||
|
>
|
||||||
|
</form>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.change-version-form-container-query {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (min-width: 400px) {
|
||||||
|
.change-version-form-container-query {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
66
src/mothership-app/pb_hooks/src/instances-delete.pb.js
Normal file
66
src/mothership-app/pb_hooks/src/instances-delete.pb.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/// <reference path="../types/types.d.ts" />
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"id": "kz4ngg77eaw1ho0",
|
||||||
|
"fields": {
|
||||||
|
"maintenance": true
|
||||||
|
"name": '',
|
||||||
|
"version": ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
routerAdd(
|
||||||
|
'DELETE',
|
||||||
|
'/api/instance/:id',
|
||||||
|
(c) => {
|
||||||
|
console.log(`***TOP OF DELETE`)
|
||||||
|
let data = new DynamicModel({
|
||||||
|
id: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
c.bind(data)
|
||||||
|
console.log(`***After bind`)
|
||||||
|
|
||||||
|
// This is necessary for destructuring to work correctly
|
||||||
|
data = JSON.parse(JSON.stringify(data))
|
||||||
|
|
||||||
|
const id = c.pathParam('id')
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`***vars`,
|
||||||
|
JSON.stringify({
|
||||||
|
id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
const authRecord = c.get('authRecord') // empty if not authenticated as regular auth record
|
||||||
|
console.log(`***authRecord`, JSON.stringify(authRecord))
|
||||||
|
|
||||||
|
if (!authRecord) {
|
||||||
|
throw new BadRequestError(`Expected authRecord here`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const record = $app.dao().findRecordById('instances', id)
|
||||||
|
if (!record) {
|
||||||
|
throw new BadRequestError(`Instance ${id} not found.`)
|
||||||
|
}
|
||||||
|
if (record.get('uid') !== authRecord.id) {
|
||||||
|
throw new BadRequestError(`Not authorized`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record.get('status') !== 'idle') {
|
||||||
|
throw new BadRequestError(`Instance must be shut down first.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = [$os.getenv('DATA_ROOT'), id].join('/')
|
||||||
|
console.log(`***path ${path}`)
|
||||||
|
const res = $os.removeAll(path)
|
||||||
|
console.log(`***res`, res)
|
||||||
|
|
||||||
|
$app.dao().deleteRecord(record)
|
||||||
|
|
||||||
|
return c.json(200, { status: 'ok' })
|
||||||
|
},
|
||||||
|
$apis.requireRecordAuth(),
|
||||||
|
)
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
DATA_ROOT,
|
||||||
DEBUG,
|
DEBUG,
|
||||||
DefaultSettingsService,
|
DefaultSettingsService,
|
||||||
MOTHERSHIP_ADMIN_PASSWORD,
|
MOTHERSHIP_ADMIN_PASSWORD,
|
||||||
@ -70,6 +71,9 @@ global.EventSource = EventSource
|
|||||||
name: MOTHERSHIP_NAME(),
|
name: MOTHERSHIP_NAME(),
|
||||||
slug: MOTHERSHIP_NAME(),
|
slug: MOTHERSHIP_NAME(),
|
||||||
port: MOTHERSHIP_PORT(),
|
port: MOTHERSHIP_PORT(),
|
||||||
|
env: {
|
||||||
|
DATA_ROOT: DATA_ROOT(),
|
||||||
|
},
|
||||||
extraBinds: [
|
extraBinds: [
|
||||||
`${MOTHERSHIP_HOOKS_DIR()}:/home/pocketbase/pb_hooks`,
|
`${MOTHERSHIP_HOOKS_DIR()}:/home/pocketbase/pb_hooks`,
|
||||||
`${MOTHERSHIP_MIGRATIONS_DIR()}:/home/pocketbase/pb_migrations`,
|
`${MOTHERSHIP_MIGRATIONS_DIR()}:/home/pocketbase/pb_migrations`,
|
||||||
|
21
src/shared/schema/Rest/DeleteInstance.ts
Normal file
21
src/shared/schema/Rest/DeleteInstance.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { JSONSchemaType } from 'ajv'
|
||||||
|
import { InstanceId } from '../types'
|
||||||
|
|
||||||
|
export type DeleteInstancePayload = {
|
||||||
|
id: InstanceId
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DeleteInstanceResult = {
|
||||||
|
status: 'ok' | 'error'
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DeleteInstancePayloadSchema: JSONSchemaType<DeleteInstancePayload> =
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: { type: 'string' },
|
||||||
|
},
|
||||||
|
required: ['id'],
|
||||||
|
additionalProperties: false,
|
||||||
|
}
|
@ -5,6 +5,7 @@ export enum RestMethods {
|
|||||||
Get = 'GET',
|
Get = 'GET',
|
||||||
Post = 'POST',
|
Post = 'POST',
|
||||||
Put = 'PUT',
|
Put = 'PUT',
|
||||||
|
Delete = 'DELETE',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RestCommands {
|
export enum RestCommands {
|
||||||
@ -17,5 +18,6 @@ export type RestPayloadBase = JsonObject
|
|||||||
export const ajv = new Ajv()
|
export const ajv = new Ajv()
|
||||||
|
|
||||||
export * from './CreateInstance'
|
export * from './CreateInstance'
|
||||||
|
export * from './DeleteInstance'
|
||||||
export * from './GetUserTokenInfo'
|
export * from './GetUserTokenInfo'
|
||||||
export * from './UpdateInstance'
|
export * from './UpdateInstance'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user