Update Cloudflare credential handling
This commit is contained in:
parent
4fd54a9633
commit
02387f28c6
3 changed files with 33 additions and 5 deletions
|
|
@ -284,6 +284,8 @@ Funções disponíveis:
|
||||||
- `hello-world`: Função exemplo
|
- `hello-world`: Função exemplo
|
||||||
- `sync-github`: Sincroniza dados de repositórios GitHub
|
- `sync-github`: Sincroniza dados de repositórios GitHub
|
||||||
- `check-cloudflare-status`: Verifica status de contas Cloudflare
|
- `check-cloudflare-status`: Verifica status de contas Cloudflare
|
||||||
|
- Gere um **API Token** no Cloudflare com permissões **Zone:Read** e **Workers:Read**.
|
||||||
|
- Salve o token no Appwrite na coleção `cloud_accounts` com `provider=cloudflare`, `apiKey` e, opcionalmente, `cloudflareAccountId` (usado para listar Workers).
|
||||||
|
|
||||||
## 🏃 Executando o Projeto
|
## 🏃 Executando o Projeto
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ export default async function ({ req, res, log, error }) {
|
||||||
|
|
||||||
const payload = req.body ? JSON.parse(req.body) : {};
|
const payload = req.body ? JSON.parse(req.body) : {};
|
||||||
const accountId = payload.accountId;
|
const accountId = payload.accountId;
|
||||||
const cloudflareAccountId = payload.cloudflareAccountId;
|
|
||||||
const requesterId =
|
const requesterId =
|
||||||
(req.headers && (req.headers['x-appwrite-user-id'] || req.headers['x-appwrite-userid'])) ||
|
(req.headers && (req.headers['x-appwrite-user-id'] || req.headers['x-appwrite-userid'])) ||
|
||||||
process.env.APPWRITE_FUNCTION_USER_ID ||
|
process.env.APPWRITE_FUNCTION_USER_ID ||
|
||||||
|
|
@ -90,6 +89,8 @@ export default async function ({ req, res, log, error }) {
|
||||||
return res.json({ error: 'Cloudflare token is missing for this account.' }, 400);
|
return res.json({ error: 'Cloudflare token is missing for this account.' }, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cloudflareAccountId = payload.cloudflareAccountId || account.cloudflareAccountId;
|
||||||
|
|
||||||
const [zones, workers] = await Promise.all([
|
const [zones, workers] = await Promise.all([
|
||||||
fetchZones(token, log),
|
fetchZones(token, log),
|
||||||
fetchWorkers(token, cloudflareAccountId, log)
|
fetchWorkers(token, cloudflareAccountId, log)
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,10 @@ type Worker = {
|
||||||
export default function Cloudflare() {
|
export default function Cloudflare() {
|
||||||
const [label, setLabel] = useState('')
|
const [label, setLabel] = useState('')
|
||||||
const [apiKey, setApiKey] = useState('')
|
const [apiKey, setApiKey] = useState('')
|
||||||
|
const [credentialAccountId, setCredentialAccountId] = useState('')
|
||||||
const [accountId, setAccountId] = useState('')
|
const [accountId, setAccountId] = useState('')
|
||||||
const [cloudflareAccountId, setCloudflareAccountId] = useState('')
|
const [cloudflareAccountId, setCloudflareAccountId] = useState('')
|
||||||
const [credentials, setCredentials] = useState<{ $id: string; label: string }[]>([])
|
const [credentials, setCredentials] = useState<{ $id: string; label: string; cloudflareAccountId?: string }[]>([])
|
||||||
const [zones, setZones] = useState<Zone[]>([])
|
const [zones, setZones] = useState<Zone[]>([])
|
||||||
const [workers, setWorkers] = useState<Worker[]>([])
|
const [workers, setWorkers] = useState<Worker[]>([])
|
||||||
const [execution, setExecution] = useState<Models.Execution | null>(null)
|
const [execution, setExecution] = useState<Models.Execution | null>(null)
|
||||||
|
|
@ -45,7 +46,11 @@ export default function Cloudflare() {
|
||||||
const response = await databases.listDocuments(appwriteDatabaseId, appwriteCollectionCloudflareAccountsId, [
|
const response = await databases.listDocuments(appwriteDatabaseId, appwriteCollectionCloudflareAccountsId, [
|
||||||
Query.equal('provider', 'cloudflare'),
|
Query.equal('provider', 'cloudflare'),
|
||||||
])
|
])
|
||||||
const docs = response.documents.map((doc) => ({ $id: doc.$id, label: (doc as { label?: string }).label || doc.$id }))
|
const docs = response.documents.map((doc) => ({
|
||||||
|
$id: doc.$id,
|
||||||
|
label: (doc as { label?: string }).label || doc.$id,
|
||||||
|
cloudflareAccountId: (doc as { cloudflareAccountId?: string }).cloudflareAccountId,
|
||||||
|
}))
|
||||||
setCredentials(docs)
|
setCredentials(docs)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
@ -86,10 +91,15 @@ export default function Cloudflare() {
|
||||||
provider: 'cloudflare',
|
provider: 'cloudflare',
|
||||||
apiKey,
|
apiKey,
|
||||||
label,
|
label,
|
||||||
|
cloudflareAccountId: credentialAccountId || undefined,
|
||||||
})
|
})
|
||||||
setCredentials((prev) => [...prev, { $id: document.$id, label: label || document.$id }])
|
setCredentials((prev) => [
|
||||||
|
...prev,
|
||||||
|
{ $id: document.$id, label: label || document.$id, cloudflareAccountId: credentialAccountId || undefined },
|
||||||
|
])
|
||||||
setLabel('')
|
setLabel('')
|
||||||
setApiKey('')
|
setApiKey('')
|
||||||
|
setCredentialAccountId('')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
setError('Não foi possível salvar a API Key.')
|
setError('Não foi possível salvar a API Key.')
|
||||||
|
|
@ -167,6 +177,16 @@ export default function Cloudflare() {
|
||||||
className="mt-1 w-full rounded-lg border border-slate-800 bg-slate-950 px-3 py-2 text-sm text-slate-100 outline-none focus:border-cyan-400"
|
className="mt-1 w-full rounded-lg border border-slate-800 bg-slate-950 px-3 py-2 text-sm text-slate-100 outline-none focus:border-cyan-400"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm text-slate-200">Cloudflare Account ID (opcional)</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={credentialAccountId}
|
||||||
|
onChange={(e) => setCredentialAccountId(e.target.value)}
|
||||||
|
placeholder="Conta para listar Workers"
|
||||||
|
className="mt-1 w-full rounded-lg border border-slate-800 bg-slate-950 px-3 py-2 text-sm text-slate-100 outline-none focus:border-cyan-400"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="rounded-lg bg-cyan-500 px-4 py-2 text-sm font-semibold text-slate-900 transition hover:bg-cyan-400"
|
className="rounded-lg bg-cyan-500 px-4 py-2 text-sm font-semibold text-slate-900 transition hover:bg-cyan-400"
|
||||||
|
|
@ -186,7 +206,12 @@ export default function Cloudflare() {
|
||||||
<label className="text-sm text-slate-200">Credencial</label>
|
<label className="text-sm text-slate-200">Credencial</label>
|
||||||
<select
|
<select
|
||||||
value={accountId}
|
value={accountId}
|
||||||
onChange={(e) => setAccountId(e.target.value)}
|
onChange={(e) => {
|
||||||
|
const selected = e.target.value
|
||||||
|
setAccountId(selected)
|
||||||
|
const selectedCredential = credentials.find((cred) => cred.$id === selected)
|
||||||
|
setCloudflareAccountId(selectedCredential?.cloudflareAccountId || '')
|
||||||
|
}}
|
||||||
className="mt-1 w-full rounded-lg border border-slate-800 bg-slate-950 px-3 py-2 text-sm text-slate-100 outline-none focus:border-cyan-400"
|
className="mt-1 w-full rounded-lg border border-slate-800 bg-slate-950 px-3 py-2 text-sm text-slate-100 outline-none focus:border-cyan-400"
|
||||||
>
|
>
|
||||||
<option value="">Selecione um documento</option>
|
<option value="">Selecione um documento</option>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue