feat(admin): Enhance Turnstile configuration UI and add GitHub commit links

- Move Turnstile status indicator above input fields for better visibility
- Mask secret key input with placeholder dots when already configured
- Update secret key helper text to indicate configuration status
- Enhance version API endpoint to include GitHub commit URL
- Add githubUrl field to version response for direct commit linking
- Implement emoji sizing styles for post content and compose input
- Update RightSidebar version state type to include githubUrl
- Add clickable GitHub commit link in version display when available
- Improve security by hiding sensitive Turnstile secret key values
This commit is contained in:
Christomatt
2026-01-26 19:11:09 +01:00
parent a3b158099d
commit bb9245ab99
4 changed files with 75 additions and 26 deletions
+15 -14
View File
@@ -474,6 +474,19 @@ export default function AdminPage() {
Cloudflare Dashboard
</a>.
</p>
{nodeSettings.turnstileSiteKey && nodeSettings.turnstileSecretKey && (
<div style={{
padding: '8px 12px',
background: 'rgba(34, 197, 94, 0.1)',
border: '1px solid rgba(34, 197, 94, 0.3)',
borderRadius: '6px',
fontSize: '12px',
color: 'rgb(34, 197, 94)',
marginBottom: '12px',
}}>
Turnstile is enabled and will be shown on login/registration
</div>
)}
</div>
<div style={{ display: 'grid', gap: '12px' }}>
<div>
@@ -501,25 +514,13 @@ export default function AdminPage() {
type="password"
value={nodeSettings.turnstileSecretKey}
onChange={e => setNodeSettings({ ...nodeSettings, turnstileSecretKey: e.target.value })}
placeholder="0x4AAAAAAA..."
placeholder={nodeSettings.turnstileSecretKey ? '••••••••••••••••' : '0x4AAAAAAA...'}
style={{ fontFamily: 'monospace', fontSize: '13px' }}
/>
<p style={{ fontSize: '11px', color: 'var(--foreground-tertiary)', marginTop: '4px' }}>
Secret key for server-side verification
{nodeSettings.turnstileSecretKey ? 'Secret key is configured (hidden for security)' : 'Secret key for server-side verification'}
</p>
</div>
{nodeSettings.turnstileSiteKey && nodeSettings.turnstileSecretKey && (
<div style={{
padding: '8px 12px',
background: 'rgba(34, 197, 94, 0.1)',
border: '1px solid rgba(34, 197, 94, 0.3)',
borderRadius: '6px',
fontSize: '12px',
color: 'rgb(34, 197, 94)',
}}>
Turnstile is enabled and will be shown on login/registration
</div>
)}
</div>
</div>
+31 -6
View File
@@ -9,26 +9,51 @@ export async function GET() {
stdio: ['pipe', 'pipe', 'ignore'] // Ignore stderr
}).trim();
// Also get the short hash for reference
// Get the short hash for reference
const commitHash = execSync('git rev-parse --short HEAD', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'ignore']
}).trim();
const fullHash = execSync('git rev-parse HEAD', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'ignore']
}).trim();
// Try to get the GitHub repo URL
let githubUrl = null;
try {
const remoteUrl = execSync('git config --get remote.origin.url', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'ignore']
}).trim();
// Convert git URL to GitHub web URL
// Handle both SSH (git@github.com:user/repo.git) and HTTPS (https://github.com/user/repo.git)
if (remoteUrl.includes('github.com')) {
let cleanUrl = remoteUrl
.replace('git@github.com:', 'https://github.com/')
.replace(/\.git$/, '');
githubUrl = `${cleanUrl}/commit/${fullHash}`;
}
} catch (e) {
// If we can't get the remote URL, that's okay
}
return NextResponse.json({
count: parseInt(commitCount, 10),
hash: commitHash,
fullHash: execSync('git rev-parse HEAD', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'ignore']
}).trim()
fullHash: fullHash,
githubUrl: githubUrl
});
} catch (error) {
// If git is not available or not a git repo, return unknown
return NextResponse.json({
count: null,
hash: 'unknown',
fullHash: null
fullHash: null,
githubUrl: null
});
}
}
+12 -1
View File
@@ -1797,4 +1797,15 @@ a.btn-primary:visited {
.thread-line {
margin-left: 20px;
border-left: 1px solid var(--border);
}
}
/* Big Emojis! */
.post-content img.emoji,
.compose-input img.emoji {
display: inline;
height: 2.5em;
width: 2.5em;
margin: 0 0.05em 0 0.1em;
vertical-align: -0.5em;
}
+17 -5
View File
@@ -19,7 +19,7 @@ export function RightSidebar() {
bannerUrl: '',
admins: [] as Admin[],
});
const [version, setVersion] = useState<{ count: number | null; hash: string; fullHash: string | null } | null>(null);
const [version, setVersion] = useState<{ count: number | null; hash: string; fullHash: string | null; githubUrl: string | null } | null>(null);
const [loading, setLoading] = useState(true);
@@ -45,7 +45,7 @@ export function RightSidebar() {
fetch('/api/version')
.then(res => res.json())
.then(data => setVersion(data))
.catch(() => setVersion({ count: null, hash: 'unknown', fullHash: null }));
.catch(() => setVersion({ count: null, hash: 'unknown', fullHash: null, githubUrl: null }));
}, []);
if (loading) {
@@ -119,9 +119,21 @@ export function RightSidebar() {
{version && version.count !== null && (
<>
{' • '}
<span title={`${version.hash} (${version.fullHash})`}>
Commit {version.count}
</span>
{version.githubUrl ? (
<a
href={version.githubUrl}
target="_blank"
rel="noopener noreferrer"
title={`${version.hash} (${version.fullHash})`}
style={{ color: 'var(--accent)' }}
>
Commit {version.count}
</a>
) : (
<span title={`${version.hash} (${version.fullHash})`}>
Commit {version.count}
</span>
)}
</>
)}
</p>