mirror of
https://github.com/pockethost/pockethost.git
synced 2025-06-27 08:22:32 +00:00
feat: delete instance
This commit is contained in:
parent
8f89dd070b
commit
00477b3c11
@ -1,5 +1,8 @@
|
||||
import {
|
||||
CreateInstancePayloadSchema,
|
||||
DeleteInstancePayload,
|
||||
DeleteInstancePayloadSchema,
|
||||
DeleteInstanceResult,
|
||||
RestCommands,
|
||||
RestMethods,
|
||||
UpdateInstancePayload,
|
||||
@ -104,6 +107,12 @@ export const createPocketbaseClient = (config: PocketbaseClientConfig) => {
|
||||
UpdateInstancePayloadSchema,
|
||||
)
|
||||
|
||||
const deleteInstance = mkRest<DeleteInstancePayload, DeleteInstanceResult>(
|
||||
RestCommands.Instance,
|
||||
RestMethods.Delete,
|
||||
DeleteInstancePayloadSchema,
|
||||
)
|
||||
|
||||
const getInstanceById = (
|
||||
id: InstanceId,
|
||||
): Promise<InstanceFields | undefined> =>
|
||||
@ -271,5 +280,6 @@ export const createPocketbaseClient = (config: PocketbaseClientConfig) => {
|
||||
getAllInstancesById,
|
||||
resendVerificationEmail,
|
||||
updateInstance,
|
||||
deleteInstance,
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
import Code from './Code.svelte'
|
||||
import AdminSync from './Danger/AdminSync.svelte'
|
||||
import DangerZoneTitle from './Danger/DangerZoneTitle.svelte'
|
||||
import DeleteInstance from './Danger/DeleteInstance.svelte'
|
||||
import Maintenance from './Danger/Maintenance.svelte'
|
||||
import RenameInstance from './Danger/RenameInstance.svelte'
|
||||
import VersionChange from './Danger/VersionChange/VersionChange.svelte'
|
||||
@ -87,4 +88,6 @@
|
||||
<VersionChange />
|
||||
|
||||
<AdminSync />
|
||||
|
||||
<DeleteInstance />
|
||||
</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 {
|
||||
DATA_ROOT,
|
||||
DEBUG,
|
||||
DefaultSettingsService,
|
||||
MOTHERSHIP_ADMIN_PASSWORD,
|
||||
@ -70,6 +71,9 @@ global.EventSource = EventSource
|
||||
name: MOTHERSHIP_NAME(),
|
||||
slug: MOTHERSHIP_NAME(),
|
||||
port: MOTHERSHIP_PORT(),
|
||||
env: {
|
||||
DATA_ROOT: DATA_ROOT(),
|
||||
},
|
||||
extraBinds: [
|
||||
`${MOTHERSHIP_HOOKS_DIR()}:/home/pocketbase/pb_hooks`,
|
||||
`${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',
|
||||
Post = 'POST',
|
||||
Put = 'PUT',
|
||||
Delete = 'DELETE',
|
||||
}
|
||||
|
||||
export enum RestCommands {
|
||||
@ -17,5 +18,6 @@ export type RestPayloadBase = JsonObject
|
||||
export const ajv = new Ajv()
|
||||
|
||||
export * from './CreateInstance'
|
||||
export * from './DeleteInstance'
|
||||
export * from './GetUserTokenInfo'
|
||||
export * from './UpdateInstance'
|
||||
|
Loading…
x
Reference in New Issue
Block a user