Files
falah-os-ce/src/screens/Login.tsx
T
Antigravity AI 21b48d3d53 feat: UmbrelOS-style CE with iStore, Casdoor auth, and App Manager
- iStore service (port 3021): fetches app manifests from git.falahos.my/falahos
  org via Gitea API, 5-min cache, query/search support
- UmmahID login: replaced stub form with Casdoor OAuth2 PKCE flow (RFC 7636),
  no client secret required; /api/auth/config and /api/auth/token endpoints
  added to server.cjs
- App Manager service (port 3022): installs/uninstalls Docker apps via
  /var/run/docker.sock, pulls images, starts containers on falah-net,
  persists state to /data/installed.json
- docker-compose.yml: orchestrates falah-app + istore + app-manager with
  health checks, named volumes, and shared falah-net network
- install.sh: one-line curl installer — checks prereqs, clones repo,
  prompts for credentials, builds and starts all containers
- .env.example: all env vars documented (CASDOOR_CLIENT_ID, GITEA_TOKEN,
  APP_MANAGER_PORT, etc.)
- Frontend: IStore overlay now fetches live apps from Gitea, real
  install/uninstall via App Manager with 2s polling, indeterminate
  progress bar, Uninstall button for installed apps
- app.yml.example: developer manifest spec for publishing to iStore
2026-07-06 10:05:37 +08:00

153 lines
4.2 KiB
TypeScript

import { useState, useCallback } from 'react'
import { fetchAuthConfig, initiateLogin } from '../hooks/useAuth'
function Logo({ size }: { size: number }) {
return (
<div
style={{
width: size,
height: size,
borderRadius: size * 0.225,
background: 'linear-gradient(145deg, #10B981, #059669)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: size * 0.45,
fontWeight: 800,
color: 'white',
flexShrink: 0,
boxShadow: '0 8px 32px rgba(16,185,129,0.4)',
}}
>
F
</div>
)
}
export default function Login() {
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const handleSignIn = useCallback(async () => {
setLoading(true)
setError('')
try {
const config = await fetchAuthConfig()
await initiateLogin(config)
// page will redirect — no further state updates needed
} catch (err) {
setError(err instanceof Error ? err.message : 'Could not reach auth server')
setLoading(false)
}
}, [])
return (
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: 24,
}}
>
<div
style={{
width: '100%',
maxWidth: 400,
background: 'rgba(12,26,46,0.92)',
backdropFilter: 'blur(24px)',
WebkitBackdropFilter: 'blur(24px)',
border: '1px solid var(--glass-border)',
borderRadius: 24,
padding: 40,
boxShadow: 'var(--shadow-modal)',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
{/* Arabic */}
<div
style={{
color: 'var(--green)',
fontSize: 14,
letterSpacing: 1.5,
opacity: 0.7,
marginBottom: 20,
fontFamily: 'serif',
}}
>
بِسْمِ اللَّهِ
</div>
<Logo size={72} />
<h1 style={{ fontSize: 26, fontWeight: 700, color: 'var(--text)', margin: '16px 0 4px' }}>
Falah OS
</h1>
<p style={{ fontSize: 13, color: 'var(--text-muted)', margin: '0 0 36px', textAlign: 'center' }}>
Sovereign Digital Economy
</p>
{/* UmmahID sign-in block */}
<div
style={{
width: '100%',
background: 'rgba(16,185,129,0.06)',
border: '1px solid rgba(16,185,129,0.18)',
borderRadius: 16,
padding: '20px 20px 24px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 12,
marginBottom: 24,
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontSize: 22 }}>🪪</span>
<div>
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)' }}>UmmahID</div>
<div style={{ fontSize: 11, color: 'var(--text-muted)' }}>Zero-knowledge identity · auth.falahos.my</div>
</div>
</div>
<button
onClick={handleSignIn}
disabled={loading}
className="btn-primary"
style={{ width: '100%', marginTop: 4, opacity: loading ? 0.6 : 1 }}
>
{loading ? 'Redirecting to UmmahID…' : 'Sign in with UmmahID'}
</button>
</div>
{error && (
<div
style={{
width: '100%',
fontSize: 12,
color: '#F87171',
background: 'rgba(239,68,68,0.08)',
border: '1px solid rgba(239,68,68,0.2)',
borderRadius: 8,
padding: '10px 14px',
textAlign: 'center',
marginBottom: 16,
}}
>
{error}
</div>
)}
<p style={{ fontSize: 11, color: 'var(--text-dim)', textAlign: 'center', margin: 0 }}>
Falah OS CE v1.3 · Community Edition
</p>
</div>
</div>
)
}