superacli 1.1.23 → 1.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.beads/.br_history/{issues.20260427_104638_898729442.jsonl → issues.20260428_172005_240631447.jsonl} +102 -102
- package/.beads/.br_history/{issues.20260427_104638_209211116.jsonl → issues.20260430_073641_144807989.jsonl} +103 -102
- package/.beads/.br_history/{issues.20260427_104637_752744777.jsonl → issues.20260430_073642_807075699.jsonl} +104 -102
- package/.beads/.br_history/{issues.20260427_104615_669652069.jsonl → issues.20260430_073645_625754223.jsonl} +105 -102
- package/.beads/.br_history/issues.20260430_090639_154646058.jsonl +265 -0
- package/.beads/.br_history/issues.20260430_090640_350560318.jsonl +266 -0
- package/.beads/.br_history/issues.20260430_090641_509319001.jsonl +267 -0
- package/.beads/.br_history/issues.20260430_095140_396749398.jsonl +268 -0
- package/.beads/.br_history/issues.20260501_230041_334056077.jsonl +269 -0
- package/.beads/issues.jsonl +9 -0
- package/graphify-out/GRAPH_REPORT.md +158 -138
- package/graphify-out/cache/036077d325d5aa25fc6ad7f01ca32721b02e3f981231f67fb22f59380063572b.json +1 -0
- package/graphify-out/cache/5262fb95a8855fc90efbfff767eb3aacca82c4da5799605a969554580a255404.json +1 -0
- package/graphify-out/cache/68e2b11c95ede4f05b88d001040008cb3ac72d7bd27f351497c87e128fb3b221.json +1 -0
- package/graphify-out/cache/8308aa47b396b929d5b896051ca91422afdde4861108d6f18f5094901093df79.json +1 -0
- package/graphify-out/cache/9832101a7622924f58b9e7d7752b41518049447171f7955e4c50dfd386574e12.json +1 -0
- package/graphify-out/cache/b849fb88344c2f88f3d22e42b67516e071c7d1e65f77f4ca23f25af6edfca3b3.json +1 -0
- package/graphify-out/cache/f9ee11f4395cb41b6f6900079cb7e94297c89b1b0b4798398d2f7a2e244c683b.json +1 -0
- package/graphify-out/graph.json +705 -678
- package/package.json +1 -1
- package/plugins/bluebuild/install-guidance.json +11 -0
- package/plugins/bluebuild/meta.json +5 -0
- package/plugins/bluebuild/plugin.json +99 -0
- package/plugins/bluebuild/skills/quickstart/SKILL.md +47 -0
- package/plugins/cargo-public-api/install-guidance.json +11 -0
- package/plugins/cargo-public-api/meta.json +5 -0
- package/plugins/cargo-public-api/plugin.json +88 -0
- package/plugins/cargo-public-api/skills/quickstart/SKILL.md +51 -0
- package/plugins/csview/install-guidance.json +11 -0
- package/plugins/csview/meta.json +5 -0
- package/plugins/csview/plugin.json +67 -0
- package/plugins/csview/skills/quickstart/SKILL.md +51 -0
- package/plugins/cymbal/install-guidance.json +11 -0
- package/plugins/cymbal/meta.json +5 -0
- package/plugins/cymbal/plugin.json +121 -0
- package/plugins/cymbal/skills/quickstart/SKILL.md +54 -0
- package/plugins/difftastic/install-guidance.json +11 -0
- package/plugins/difftastic/meta.json +5 -0
- package/plugins/difftastic/plugin.json +87 -0
- package/plugins/difftastic/skills/quickstart/SKILL.md +53 -0
- package/plugins/dlm/install-guidance.json +11 -0
- package/plugins/dlm/meta.json +5 -0
- package/plugins/dlm/plugin.json +85 -0
- package/plugins/dlm/skills/quickstart/SKILL.md +49 -0
- package/plugins/dofigen/install-guidance.json +11 -0
- package/plugins/dofigen/meta.json +5 -0
- package/plugins/dofigen/plugin.json +84 -0
- package/plugins/dofigen/skills/quickstart/SKILL.md +50 -0
- package/plugins/http-nu/install-guidance.json +11 -0
- package/plugins/http-nu/meta.json +5 -0
- package/plugins/http-nu/plugin.json +84 -0
- package/plugins/http-nu/skills/quickstart/SKILL.md +52 -0
- package/plugins/hwatch/install-guidance.json +11 -0
- package/plugins/hwatch/meta.json +5 -0
- package/plugins/hwatch/plugin.json +100 -0
- package/plugins/hwatch/skills/quickstart/SKILL.md +54 -0
- package/plugins/hyperfine/install-guidance.json +3 -3
- package/plugins/hyperfine/meta.json +2 -2
- package/plugins/hyperfine/plugin.json +39 -16
- package/plugins/hyperfine/skills/quickstart/SKILL.md +33 -61
- package/plugins/json5/install-guidance.json +12 -0
- package/plugins/json5/meta.json +5 -0
- package/plugins/json5/plugin.json +88 -0
- package/plugins/json5/skills/quickstart/SKILL.md +55 -0
- package/plugins/mdsf/install-guidance.json +11 -0
- package/plugins/mdsf/meta.json +5 -0
- package/plugins/mdsf/plugin.json +101 -0
- package/plugins/mdsf/skills/quickstart/SKILL.md +55 -0
- package/plugins/oha/install-guidance.json +11 -0
- package/plugins/oha/meta.json +5 -0
- package/plugins/oha/plugin.json +67 -0
- package/plugins/oha/skills/quickstart/SKILL.md +44 -0
- package/plugins/pv-migrate/install-guidance.json +11 -0
- package/plugins/pv-migrate/meta.json +5 -0
- package/plugins/pv-migrate/plugin.json +102 -0
- package/plugins/pv-migrate/skills/quickstart/SKILL.md +58 -0
- package/plugins/rash/install-guidance.json +11 -0
- package/plugins/rash/meta.json +5 -0
- package/plugins/rash/plugin.json +85 -0
- package/plugins/rash/skills/quickstart/SKILL.md +46 -0
- package/plugins/rsonpath/install-guidance.json +11 -0
- package/plugins/rsonpath/meta.json +5 -0
- package/plugins/rsonpath/plugin.json +87 -0
- package/plugins/rsonpath/skills/quickstart/SKILL.md +44 -0
- package/plugins/rsql/install-guidance.json +11 -0
- package/plugins/rsql/meta.json +5 -0
- package/plugins/rsql/plugin.json +84 -0
- package/plugins/rsql/skills/quickstart/SKILL.md +52 -0
- package/plugins/temporal/install-guidance.json +11 -0
- package/plugins/temporal/meta.json +5 -0
- package/plugins/temporal/plugin.json +95 -0
- package/plugins/temporal/skills/quickstart/SKILL.md +49 -0
- package/plugins/tkn/install-guidance.json +11 -0
- package/plugins/tkn/meta.json +5 -0
- package/plugins/tkn/plugin.json +98 -0
- package/plugins/tkn/skills/quickstart/SKILL.md +50 -0
- package/plugins/toml2json/install-guidance.json +11 -0
- package/plugins/toml2json/meta.json +5 -0
- package/plugins/toml2json/plugin.json +85 -0
- package/plugins/toml2json/skills/quickstart/SKILL.md +47 -0
- package/plugins/worktrunk/install-guidance.json +11 -0
- package/plugins/worktrunk/meta.json +5 -0
- package/plugins/worktrunk/plugin.json +116 -0
- package/plugins/worktrunk/skills/quickstart/SKILL.md +62 -0
- package/server/app.js +5 -4
- package/server/middleware/auth.js +4 -4
- package/server/routes/clients.js +46 -0
- package/server/routes/plugins.js +0 -116
- package/server/routes/settings.js +93 -0
- package/server/views/api-keys.ejs +147 -0
- package/server/views/layout.ejs +37 -0
- package/server/views/partials/head.ejs +3 -1
- package/server/views/plugins.ejs +1 -80
- package/server/views/settings.ejs +99 -0
- package/.beads/.br_history/issues.20260427_104606_658098709.jsonl +0 -261
- package/.beads/.br_history/issues.20260427_104607_085798670.jsonl +0 -261
- package/.beads/.br_history/issues.20260427_104607_627598880.jsonl +0 -261
- package/.beads/.br_history/issues.20260427_104608_071298223.jsonl +0 -261
- package/.beads/.br_history/issues.20260427_104615_198124329.jsonl +0 -261
- /package/.beads/.br_history/{issues.20260427_104606_658098709.jsonl.meta.json → issues.20260428_172005_240631447.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104607_085798670.jsonl.meta.json → issues.20260430_073641_144807989.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104607_627598880.jsonl.meta.json → issues.20260430_073642_807075699.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104608_071298223.jsonl.meta.json → issues.20260430_073645_625754223.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104615_198124329.jsonl.meta.json → issues.20260430_090639_154646058.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104615_669652069.jsonl.meta.json → issues.20260430_090640_350560318.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104637_752744777.jsonl.meta.json → issues.20260430_090641_509319001.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104638_209211116.jsonl.meta.json → issues.20260430_095140_396749398.jsonl.meta.json} +0 -0
- /package/.beads/.br_history/{issues.20260427_104638_898729442.jsonl.meta.json → issues.20260501_230041_334056077.jsonl.meta.json} +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<%- include("partials/head", { title: "API Keys" }) %>
|
|
2
|
+
|
|
3
|
+
<div id="api-keys-app" class="max-w-4xl">
|
|
4
|
+
<div class="flex justify-between items-center mb-6">
|
|
5
|
+
<h1 class="text-2xl font-bold">API Keys</h1>
|
|
6
|
+
<div class="text-sm opacity-80">Manage API keys for CLI and programmatic access.</div>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div v-if="message.text" :class="['alert mb-4', message.type === 'error' ? 'alert-error' : 'alert-success']">
|
|
10
|
+
<span>{{ message.text }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="card bg-base-100 border border-base-300">
|
|
14
|
+
<div class="card-body">
|
|
15
|
+
<h2 class="card-title">Create New API Key</h2>
|
|
16
|
+
<div class="form-control">
|
|
17
|
+
<div class="label">
|
|
18
|
+
<span class="label-text">Key Name</span>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="flex gap-2">
|
|
21
|
+
<input v-model="newKeyName" class="input input-bordered flex-1" placeholder="e.g., 'CLI Agent' or 'Production'" />
|
|
22
|
+
<button class="btn btn-primary" @click="createApiKey">Create</button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="card bg-base-100 border border-base-300 mt-4">
|
|
29
|
+
<div class="card-body">
|
|
30
|
+
<h2 class="card-title">Active API Keys</h2>
|
|
31
|
+
<div v-if="settings.api_keys && settings.api_keys.length > 0">
|
|
32
|
+
<table class="table table-zebra">
|
|
33
|
+
<thead>
|
|
34
|
+
<tr>
|
|
35
|
+
<th>Name</th>
|
|
36
|
+
<th>Key</th>
|
|
37
|
+
<th>Created</th>
|
|
38
|
+
<th>Action</th>
|
|
39
|
+
</tr>
|
|
40
|
+
</thead>
|
|
41
|
+
<tbody>
|
|
42
|
+
<tr v-for="apiKey in settings.api_keys" :key="apiKey.key">
|
|
43
|
+
<td>{{ apiKey.name }}</td>
|
|
44
|
+
<td>
|
|
45
|
+
<code>{{ apiKey.key.slice(0, 12) }}...</code>
|
|
46
|
+
<button class="btn btn-xs btn-ghost ml-2" @click="copyApiKey(apiKey.key)">📋</button>
|
|
47
|
+
</td>
|
|
48
|
+
<td>{{ new Date(apiKey.created_at).toLocaleString() }}</td>
|
|
49
|
+
<td>
|
|
50
|
+
<button class="btn btn-sm btn-error" @click="deleteApiKey(apiKey.key)">Delete</button>
|
|
51
|
+
</td>
|
|
52
|
+
</tr>
|
|
53
|
+
</tbody>
|
|
54
|
+
</table>
|
|
55
|
+
</div>
|
|
56
|
+
<div v-else class="text-center py-8 opacity-60">
|
|
57
|
+
<p>No API keys created yet</p>
|
|
58
|
+
<p class="text-sm mt-2">Create an API key to enable CLI and programmatic access to the server.</p>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<script>
|
|
65
|
+
const { createApp } = Vue
|
|
66
|
+
|
|
67
|
+
createApp({
|
|
68
|
+
data() {
|
|
69
|
+
return {
|
|
70
|
+
settings: {},
|
|
71
|
+
newKeyName: '',
|
|
72
|
+
message: { text: '', type: 'success' }
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
async mounted() {
|
|
76
|
+
await this.loadSettings()
|
|
77
|
+
},
|
|
78
|
+
methods: {
|
|
79
|
+
async loadSettings() {
|
|
80
|
+
try {
|
|
81
|
+
const res = await fetch('/api/settings?format=json')
|
|
82
|
+
const data = await res.json()
|
|
83
|
+
this.settings = data
|
|
84
|
+
} catch (err) {
|
|
85
|
+
this.setMessage('error', err.message)
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
async createApiKey() {
|
|
89
|
+
if (!this.newKeyName.trim()) {
|
|
90
|
+
this.setMessage('error', 'API key name is required')
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const res = await fetch('/api/api-keys', {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
headers: { 'Content-Type': 'application/json' },
|
|
97
|
+
body: JSON.stringify({ name: this.newKeyName })
|
|
98
|
+
})
|
|
99
|
+
const result = await res.json()
|
|
100
|
+
this.setMessage('success', `Created API key '${result.name}'`)
|
|
101
|
+
this.newKeyName = ''
|
|
102
|
+
await this.loadSettings()
|
|
103
|
+
} catch (err) {
|
|
104
|
+
this.setMessage('error', err.message)
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
async deleteApiKey(key) {
|
|
108
|
+
if (!confirm('Delete this API key?')) return
|
|
109
|
+
try {
|
|
110
|
+
await fetch(`/api/api-keys/${encodeURIComponent(key)}`, {
|
|
111
|
+
method: 'DELETE'
|
|
112
|
+
})
|
|
113
|
+
this.setMessage('success', 'API key deleted')
|
|
114
|
+
await this.loadSettings()
|
|
115
|
+
} catch (err) {
|
|
116
|
+
this.setMessage('error', err.message)
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async copyApiKey(key) {
|
|
120
|
+
try {
|
|
121
|
+
// Fallback for non-HTTPS contexts
|
|
122
|
+
const textArea = document.createElement("textarea")
|
|
123
|
+
textArea.value = key
|
|
124
|
+
textArea.style.position = "fixed"
|
|
125
|
+
textArea.style.left = "-9999px"
|
|
126
|
+
document.body.appendChild(textArea)
|
|
127
|
+
textArea.select()
|
|
128
|
+
try {
|
|
129
|
+
document.execCommand("copy")
|
|
130
|
+
this.setMessage('success', 'API key copied to clipboard')
|
|
131
|
+
} catch (err) {
|
|
132
|
+
throw new Error('Copy failed')
|
|
133
|
+
}
|
|
134
|
+
document.body.removeChild(textArea)
|
|
135
|
+
} catch (err) {
|
|
136
|
+
this.setMessage('error', 'Failed to copy API key')
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
setMessage(type, text) {
|
|
140
|
+
this.message = { type, text }
|
|
141
|
+
setTimeout(() => this.message = { text: '', type: 'success' }, 3000)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}).mount('#api-keys-app')
|
|
145
|
+
</script>
|
|
146
|
+
|
|
147
|
+
<%- include("partials/foot") %>
|
package/server/views/layout.ejs
CHANGED
|
@@ -88,6 +88,43 @@
|
|
|
88
88
|
<body>
|
|
89
89
|
|
|
90
90
|
<div class="flex min-h-screen">
|
|
91
|
+
<!-- Sidebar navigation -->
|
|
92
|
+
<aside class="w-64 bg-white border-r border-[#EAEAEA] p-6">
|
|
93
|
+
<div class="mb-8">
|
|
94
|
+
<h1 class="text-xl font-bold editorial-heading">SUPERCLI</h1>
|
|
95
|
+
<p class="text-sm text-[#787774]">Command Control Plane</p>
|
|
96
|
+
</div>
|
|
97
|
+
<nav class="space-y-2">
|
|
98
|
+
<a href="/api/plugins" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
99
|
+
Plugins
|
|
100
|
+
</a>
|
|
101
|
+
<a href="/api/settings" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
102
|
+
Settings
|
|
103
|
+
</a>
|
|
104
|
+
<a href="/api/api-keys" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
105
|
+
API Keys
|
|
106
|
+
</a>
|
|
107
|
+
<a href="/api/commands" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
108
|
+
Commands
|
|
109
|
+
</a>
|
|
110
|
+
<a href="/api/jobs" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
111
|
+
Jobs
|
|
112
|
+
</a>
|
|
113
|
+
<a href="/api/clients" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
114
|
+
Clients
|
|
115
|
+
</a>
|
|
116
|
+
<a href="/api/adapters" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
117
|
+
Adapters
|
|
118
|
+
</a>
|
|
119
|
+
<a href="/api/specs" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
120
|
+
OpenAPI Specs
|
|
121
|
+
</a>
|
|
122
|
+
<a href="/api/mcp" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
|
|
123
|
+
MCP Servers
|
|
124
|
+
</a>
|
|
125
|
+
</nav>
|
|
126
|
+
</aside>
|
|
127
|
+
|
|
91
128
|
<!-- Main content -->
|
|
92
129
|
<main class="flex-1 p-8 bg-[#FBFBFA]">
|
|
93
130
|
<%- body %>
|
|
@@ -98,7 +98,9 @@
|
|
|
98
98
|
<a href="/api/specs" class="btn justify-start" id="nav-specs">OpenAPI Specs</a>
|
|
99
99
|
<a href="/api/mcp" class="btn justify-start" id="nav-mcp">MCP Servers</a>
|
|
100
100
|
<a href="/api/plugins" class="btn justify-start" id="nav-plugins">Server Plugins</a>
|
|
101
|
-
<a href="/api/
|
|
101
|
+
<a href="/api/settings" class="btn justify-start" id="nav-settings">Settings</a>
|
|
102
|
+
<a href="/api/api-keys" class="btn justify-start" id="nav-api-keys">API Keys</a>
|
|
103
|
+
<a href="/api/clients" class="btn justify-start" id="nav-clients">Clients</a>
|
|
102
104
|
<a href="/api/jobs" class="btn justify-start" id="nav-jobs">Jobs</a>
|
|
103
105
|
<a href="/api/docs" class="btn justify-start" id="nav-docs">Documentation</a>
|
|
104
106
|
</aside>
|
package/server/views/plugins.ejs
CHANGED
|
@@ -15,76 +15,7 @@
|
|
|
15
15
|
<span><strong>Admin Mode Enabled:</strong> CLI clients can modify server state without authentication. Disable when not needed.</span>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
<div class="grid grid-cols-1 lg:grid-cols-
|
|
19
|
-
<div class="card bg-base-100 border border-base-300">
|
|
20
|
-
<div class="card-body p-4">
|
|
21
|
-
<h2 class="card-title text-base">Settings</h2>
|
|
22
|
-
<label class="form-control mb-2">
|
|
23
|
-
<span class="label-text text-xs">Max ZIP Size (MB)</span>
|
|
24
|
-
<input v-model.number="settings.max_zip_mb" type="number" min="1" class="input input-bordered input-sm" />
|
|
25
|
-
</label>
|
|
26
|
-
<label class="form-control mb-3">
|
|
27
|
-
<span class="label-text text-xs">Default Hooks Policy</span>
|
|
28
|
-
<select v-model="settings.default_hooks_policy" class="select select-bordered select-sm">
|
|
29
|
-
<option value="deny">deny</option>
|
|
30
|
-
<option value="allow">allow</option>
|
|
31
|
-
</select>
|
|
32
|
-
</label>
|
|
33
|
-
<label class="label cursor-pointer justify-start gap-2 mb-3">
|
|
34
|
-
<input type="checkbox" v-model="settings.admin_mode_enabled" class="checkbox checkbox-error checkbox-sm" />
|
|
35
|
-
<span class="label-text text-xs text-error font-semibold">Admin Mode (allows CLI modifications)</span>
|
|
36
|
-
</label>
|
|
37
|
-
<label class="label cursor-pointer justify-start gap-2 mb-3">
|
|
38
|
-
<input type="checkbox" v-model="settings.public_access" class="checkbox checkbox-sm" />
|
|
39
|
-
<span class="label-text text-xs">Public Access (allow without API key)</span>
|
|
40
|
-
</label>
|
|
41
|
-
<button class="btn btn-sm btn-primary" @click="saveSettings">Save Settings</button>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div class="card bg-base-100 border border-base-300">
|
|
46
|
-
<div class="card-body p-4">
|
|
47
|
-
<h2 class="card-title text-base">API Keys</h2>
|
|
48
|
-
<div class="form-control mb-3">
|
|
49
|
-
<div class="label">
|
|
50
|
-
<span class="label-text text-xs">Create New API Key</span>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="flex gap-2">
|
|
53
|
-
<input v-model="newKeyName" class="input input-bordered input-sm flex-1" placeholder="Key name (e.g., 'CLI Agent')" />
|
|
54
|
-
<button class="btn btn-sm btn-primary" @click="createApiKey">Create</button>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
<div v-if="settings.api_keys && settings.api_keys.length > 0" class="overflow-x-auto">
|
|
58
|
-
<table class="table table-zebra table-xs">
|
|
59
|
-
<thead>
|
|
60
|
-
<tr>
|
|
61
|
-
<th>Name</th>
|
|
62
|
-
<th>Key</th>
|
|
63
|
-
<th>Created</th>
|
|
64
|
-
<th>Action</th>
|
|
65
|
-
</tr>
|
|
66
|
-
</thead>
|
|
67
|
-
<tbody>
|
|
68
|
-
<tr v-for="apiKey in settings.api_keys" :key="apiKey.key">
|
|
69
|
-
<td>{{ apiKey.name }}</td>
|
|
70
|
-
<td>
|
|
71
|
-
<code class="text-xs">{{ apiKey.key.slice(0, 8) }}...</code>
|
|
72
|
-
<button class="btn btn-xs btn-ghost ml-1" @click="copyApiKey(apiKey.key)">📋</button>
|
|
73
|
-
</td>
|
|
74
|
-
<td class="text-xs">{{ new Date(apiKey.created_at).toLocaleDateString() }}</td>
|
|
75
|
-
<td>
|
|
76
|
-
<button class="btn btn-xs btn-error" @click="deleteApiKey(apiKey.key)">Delete</button>
|
|
77
|
-
</td>
|
|
78
|
-
</tr>
|
|
79
|
-
</tbody>
|
|
80
|
-
</table>
|
|
81
|
-
</div>
|
|
82
|
-
<div v-else class="text-xs opacity-60 text-center py-2">
|
|
83
|
-
No API keys created yet
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
|
|
18
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-6">
|
|
88
19
|
<div class="card bg-base-100 border border-base-300">
|
|
89
20
|
<div class="card-body p-4">
|
|
90
21
|
<h2 class="card-title text-base">Create JSON Plugin</h2>
|
|
@@ -201,7 +132,6 @@
|
|
|
201
132
|
archive_file: null,
|
|
202
133
|
manifestStr: '{\n "name": "my-plugin",\n "version": "0.0.0",\n "commands": []\n}',
|
|
203
134
|
},
|
|
204
|
-
newKeyName: '',
|
|
205
135
|
}
|
|
206
136
|
},
|
|
207
137
|
methods: {
|
|
@@ -228,15 +158,6 @@
|
|
|
228
158
|
this.plugins = out.plugins || []
|
|
229
159
|
if (out.settings) this.settings = out.settings
|
|
230
160
|
},
|
|
231
|
-
async saveSettings() {
|
|
232
|
-
try {
|
|
233
|
-
await this.api('/api/plugins/settings', 'PUT', this.settings)
|
|
234
|
-
this.setMessage('success', 'Settings updated')
|
|
235
|
-
await this.reloadPlugins()
|
|
236
|
-
} catch (err) {
|
|
237
|
-
this.setMessage('error', err.message)
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
161
|
async createJsonPlugin() {
|
|
241
162
|
try {
|
|
242
163
|
const manifest = JSON.parse(this.jsonForm.manifestStr)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<%- include("partials/head", { title: "Server Settings" }) %>
|
|
2
|
+
|
|
3
|
+
<div id="settings-app" class="max-w-4xl">
|
|
4
|
+
<div class="flex justify-between items-center mb-6">
|
|
5
|
+
<h1 class="text-2xl font-bold">Server Settings</h1>
|
|
6
|
+
<div class="text-sm opacity-80">Configure server-wide behavior and security.</div>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div v-if="message.text" :class="['alert mb-4', message.type === 'error' ? 'alert-error' : 'alert-success']">
|
|
10
|
+
<span>{{ message.text }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div v-if="settings.admin_mode_enabled" class="alert alert-error mb-4">
|
|
14
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>
|
|
15
|
+
<span><strong>Admin Mode Enabled:</strong> CLI clients can modify server state without authentication. Disable when not needed.</span>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="card bg-base-100 border border-base-300">
|
|
19
|
+
<div class="card-body">
|
|
20
|
+
<h2 class="card-title">General Settings</h2>
|
|
21
|
+
<label class="form-control mb-3">
|
|
22
|
+
<span class="label-text">Max ZIP Size (MB)</span>
|
|
23
|
+
<input v-model.number="settings.max_zip_mb" type="number" min="1" class="input input-bordered" />
|
|
24
|
+
</label>
|
|
25
|
+
<label class="form-control mb-3">
|
|
26
|
+
<span class="label-text">Default Hooks Policy</span>
|
|
27
|
+
<select v-model="settings.default_hooks_policy" class="select select-bordered">
|
|
28
|
+
<option value="deny">deny</option>
|
|
29
|
+
<option value="allow">allow</option>
|
|
30
|
+
</select>
|
|
31
|
+
</label>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div class="card bg-base-100 border border-base-300 mt-4">
|
|
36
|
+
<div class="card-body">
|
|
37
|
+
<h2 class="card-title">Security Settings</h2>
|
|
38
|
+
<label class="label cursor-pointer justify-start gap-2 mb-3">
|
|
39
|
+
<input type="checkbox" v-model="settings.admin_mode_enabled" class="checkbox checkbox-error" />
|
|
40
|
+
<span class="label-text text-error font-semibold">Admin Mode (allows CLI modifications without auth)</span>
|
|
41
|
+
</label>
|
|
42
|
+
<label class="label cursor-pointer justify-start gap-2 mb-3">
|
|
43
|
+
<input type="checkbox" v-model="settings.public_access" class="checkbox" />
|
|
44
|
+
<span class="label-text">Public Access (allow API requests without API key)</span>
|
|
45
|
+
</label>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="mt-6">
|
|
50
|
+
<button class="btn btn-primary" @click="saveSettings">Save Settings</button>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<script>
|
|
55
|
+
const { createApp } = Vue
|
|
56
|
+
|
|
57
|
+
createApp({
|
|
58
|
+
data() {
|
|
59
|
+
return {
|
|
60
|
+
settings: {},
|
|
61
|
+
message: { text: '', type: 'success' }
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
async mounted() {
|
|
65
|
+
await this.loadSettings()
|
|
66
|
+
},
|
|
67
|
+
methods: {
|
|
68
|
+
async loadSettings() {
|
|
69
|
+
try {
|
|
70
|
+
const res = await fetch('/api/settings?format=json')
|
|
71
|
+
const data = await res.json()
|
|
72
|
+
this.settings = data
|
|
73
|
+
} catch (err) {
|
|
74
|
+
this.setMessage('error', err.message)
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async saveSettings() {
|
|
78
|
+
try {
|
|
79
|
+
const res = await fetch('/api/settings', {
|
|
80
|
+
method: 'PUT',
|
|
81
|
+
headers: { 'Content-Type': 'application/json' },
|
|
82
|
+
body: JSON.stringify(this.settings)
|
|
83
|
+
})
|
|
84
|
+
const data = await res.json()
|
|
85
|
+
this.settings = data.settings
|
|
86
|
+
this.setMessage('success', 'Settings saved')
|
|
87
|
+
} catch (err) {
|
|
88
|
+
this.setMessage('error', err.message)
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
setMessage(type, text) {
|
|
92
|
+
this.message = { type, text }
|
|
93
|
+
setTimeout(() => this.message = { text: '', type: 'success' }, 3000)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}).mount('#settings-app')
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<%- include("partials/foot") %>
|