init commit for iPAL-kit plugin

This commit is contained in:
2026-07-18 20:30:23 +02:00
parent 10638127a9
commit 5733a9c8bf
119 changed files with 6892 additions and 411 deletions
@@ -0,0 +1,24 @@
import type { Field } from 'payload'
/**
* Analytics configuration — GA4 measurement ID and GTM container ID.
* IDs are public (exposed client-side), so no read restriction needed.
*/
export const analyticsFields: Field[] = [
{
name: 'ga4MeasurementId',
type: 'text',
admin: {
description: 'Google Analytics 4 Measurement ID.',
placeholder: 'G-XXXXXXXXXX',
},
},
{
name: 'gtmContainerId',
type: 'text',
admin: {
description: 'Google Tag Manager container ID.',
placeholder: 'GTM-XXXXXXX',
},
},
]
@@ -0,0 +1,55 @@
import type { Field } from 'payload'
/**
* SMTP transport settings for outbound email.
*
* Protected at the global level (SiteIntegrations requires an authenticated
* user), so all fields — including the password — stay editable in the admin
* panel while remaining inaccessible to anonymous API requests.
*/
export const smtpFields: Field[] = [
{
type: 'row',
fields: [
{
name: 'smtpHost',
type: 'text',
admin: { placeholder: 'smtp.example.com', width: '70%' },
},
{
name: 'smtpPort',
type: 'number',
admin: { width: '30%' },
defaultValue: 587,
},
],
},
{
name: 'smtpUser',
type: 'text',
admin: {
description: 'SMTP account username.',
},
},
{
name: 'smtpPassword',
type: 'text',
admin: {
description: 'SMTP account password.',
},
},
{
name: 'smtpFromAddress',
type: 'email',
admin: {
description: 'Default "from" address for outgoing mail.',
},
},
{
name: 'smtpFromName',
type: 'text',
admin: {
description: 'Default "from" display name.',
},
},
]
@@ -0,0 +1,40 @@
import type { Field } from 'payload'
/**
* Cloudflare R2 storage credentials.
* Reserved for future use — media offloading to R2.
*
* Protected at the global level (SiteIntegrations requires an authenticated
* user), so the access keys stay editable in the admin panel while remaining
* inaccessible to anonymous API requests.
*/
export const storageFields: Field[] = [
{
name: 'r2Bucket',
type: 'text',
admin: {
description: 'R2 bucket name.',
},
},
{
name: 'r2Endpoint',
type: 'text',
admin: {
description: 'R2 S3-compatible endpoint URL.',
},
},
{
name: 'r2AccessKeyId',
type: 'text',
admin: {
description: 'R2 access key ID.',
},
},
{
name: 'r2SecretAccessKey',
type: 'text',
admin: {
description: 'R2 secret access key.',
},
},
]
@@ -0,0 +1,26 @@
import type { Field } from 'payload'
/**
* Cloudflare Turnstile credentials.
*
* siteKey is public (rendered in the widget); secretKey is used for
* server-side verification. Both are protected at the global level
* (SiteIntegrations requires an authenticated user) rather than per-field,
* so they remain editable in the admin panel.
*/
export const turnstileFields: Field[] = [
{
name: 'turnstileSiteKey',
type: 'text',
admin: {
description: 'Public site key rendered in the Turnstile widget.',
},
},
{
name: 'turnstileSecretKey',
type: 'text',
admin: {
description: 'Secret key used for server-side verification.',
},
},
]
+54
View File
@@ -0,0 +1,54 @@
import type { Field, GlobalConfig } from 'payload'
import { isAdmin } from '../../modules/access/index.js'
import { analyticsFields } from './fields/analytics.js'
import { smtpFields } from './fields/smtp.js'
import { storageFields } from './fields/storage.js'
import { turnstileFields } from './fields/turnstile.js'
type BuildSiteIntegrationsArgs = {
/** Extra fields injected by the client project */
additionalFields?: Field[]
}
/**
* Builds the SiteIntegrations global.
*
* Holds third-party service credentials. Access is enforced at the global
* level — the whole global requires an authenticated user — so secrets stay
* out of anonymous API responses while remaining editable in the admin panel
* and readable via the server-side Local API. (Field-level read:false was
* avoided because it also hides fields from the admin UI, making them
* impossible to enter.)
*
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
*/
export function buildSiteIntegrations({
additionalFields,
}: BuildSiteIntegrationsArgs = {}): GlobalConfig {
return {
slug: 'site-integrations',
access: {
// Admin-only — secrets live here. Anonymous and non-admin users get
// nothing through the API; admins read/edit in the panel and via Local API.
read: ({ req: { user } }) => isAdmin(user),
update: ({ req: { user } }) => isAdmin(user),
},
admin: {
group: 'Settings',
},
fields: [
{
type: 'tabs',
tabs: [
{ fields: analyticsFields, label: 'Analytics' },
{ fields: turnstileFields, label: 'Turnstile' },
{ fields: smtpFields, label: 'SMTP' },
{ fields: storageFields, label: 'Storage' },
...(additionalFields?.length ? [{ fields: additionalFields, label: 'Custom' }] : []),
],
},
],
label: 'Site Integrations',
}
}