auth: add JWT email/password auth + Login UI; security: kms rotate helper; preview sync endpoint + UI

This commit is contained in:
TLimoges33
2025-08-28 17:26:02 +00:00
parent 7702d3711b
commit a2b8950d9a
6 changed files with 205 additions and 1 deletions
+3 -1
View File
@@ -1,13 +1,15 @@
import React from 'react'
import Integrations from './Integrations'
import Guilds from './Guilds'
import Login from './Login'
export default function App(){
return (
<div style={{padding:20,fontFamily:'system-ui, sans-serif'}}>
<h1>LifeRPG Modern</h1>
<p>Welcome frontend scaffold. Connect to backend at <code>/api/v1</code>.</p>
<Integrations />
<Login />
<Integrations />
<Guilds />
</div>
)
+9
View File
@@ -30,6 +30,14 @@ export default function Integrations(){
.finally(()=>setLoadingId(null))
}
function previewEvents(integrationId){
fetch(`/api/v1/integrations/${integrationId}/events_preview`, {credentials:'include'})
.then(r=>r.json()).then(d=>{
setEvents(d)
setMsg('Preview loaded')
}).catch(()=>setMsg('Preview failed'))
}
function removeIntegration(integrationId){
if(!confirm('Remove integration?')) return
setLoadingId(integrationId)
@@ -63,6 +71,7 @@ export default function Integrations(){
<strong>{i.provider}</strong> id: {i.id} user: {i.user_id}
<div style={{display:'inline-block', marginLeft:12}}>
<button onClick={()=>fetchEvents(i.id)} disabled={loadingId===i.id} style={{marginRight:6}}>Fetch Events</button>
<button onClick={()=>previewEvents(i.id)} disabled={loadingId===i.id} style={{marginRight:6}}>Preview</button>
<button onClick={()=>syncIntegration(i.id)} disabled={loadingId===i.id} style={{marginRight:6}}>Sync Habits</button>
<button onClick={()=>removeIntegration(i.id)} disabled={loadingId===i.id}>Remove</button>
</div>
+25
View File
@@ -0,0 +1,25 @@
import React, {useState} from 'react'
export default function Login(){
const [email,setEmail]=useState('')
const [pw,setPw]=useState('')
const [msg,setMsg]=useState(null)
function submit(e){
e.preventDefault()
fetch('/api/v1/auth/login', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({email, password: pw}), credentials:'include'})
.then(r=>r.json()).then(()=> setMsg('Logged in')).catch(()=> setMsg('Login failed'))
}
return (
<div style={{marginTop:20}}>
<h2>Login</h2>
<form onSubmit={submit}>
<div><input placeholder="email" value={email} onChange={e=>setEmail(e.target.value)} /></div>
<div><input placeholder="password" type="password" value={pw} onChange={e=>setPw(e.target.value)} /></div>
<button type="submit">Login</button>
</form>
{msg && <div style={{marginTop:8}}>{msg}</div>}
</div>
)
}