Update Cloudflare credential handling

This commit is contained in:
Tiago Yamamoto 2026-01-08 15:43:32 -03:00
parent 4fd54a9633
commit 02387f28c6
3 changed files with 33 additions and 5 deletions

View file

@ -284,6 +284,8 @@ Funções disponíveis:
- `hello-world`: Função exemplo
- `sync-github`: Sincroniza dados de repositórios GitHub
- `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

View file

@ -59,7 +59,6 @@ export default async function ({ req, res, log, error }) {
const payload = req.body ? JSON.parse(req.body) : {};
const accountId = payload.accountId;
const cloudflareAccountId = payload.cloudflareAccountId;
const requesterId =
(req.headers && (req.headers['x-appwrite-user-id'] || req.headers['x-appwrite-userid'])) ||
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);
}
const cloudflareAccountId = payload.cloudflareAccountId || account.cloudflareAccountId;
const [zones, workers] = await Promise.all([
fetchZones(token, log),
fetchWorkers(token, cloudflareAccountId, log)

View file

@ -27,9 +27,10 @@ type Worker = {
export default function Cloudflare() {
const [label, setLabel] = useState('')
const [apiKey, setApiKey] = useState('')
const [credentialAccountId, setCredentialAccountId] = useState('')
const [accountId, setAccountId] = 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 [workers, setWorkers] = useState<Worker[]>([])
const [execution, setExecution] = useState<Models.Execution | null>(null)
@ -45,7 +46,11 @@ export default function Cloudflare() {
const response = await databases.listDocuments(appwriteDatabaseId, appwriteCollectionCloudflareAccountsId, [
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)
} catch (err) {
console.error(err)
@ -86,10 +91,15 @@ export default function Cloudflare() {
provider: 'cloudflare',
apiKey,
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('')
setApiKey('')
setCredentialAccountId('')
} catch (err) {
console.error(err)
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"
/>
</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
type="submit"
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>
<select
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"
>
<option value="">Selecione um documento</option>