Files
drivetimeplaner/www/fahrschuldesk.de/dist/assets/Login-fU5wXJUp.js
Hermes Agent 5d87e4975c Add HttpOnly cookie auth for cross-domain SPA login
Problem: Frontend JS bundle used credentials:'same-origin' which
dropped cookies on cross-domain requests. Login worked (200) but
the subsequent /auth/me check returned 401, leaving the user stuck
on the login screen.

Fix:
- AuthController now sets a dtp_jwt HttpOnly cookie on login/refresh
- Cookie uses Domain=.fahrschultermin.de (shared between frontend
  and api subdomain), Secure, SameSite=Lax, Max-Age=8h
- JwtMiddleware reads JWT from Authorization header OR cookie
- Added AuthController::me() endpoint (was missing, caused 500)
- Logout endpoint clears the cookie
- Frontend index.php patches fetch() to use credentials:'include'
  for all /api/v1/* calls
2026-06-04 20:33:31 +02:00

2 lines
5.2 KiB
JavaScript
Executable File

import{p as V,f as o,b as t,g as C,B as j,A as h,y as B,n as w,t as p,e as f,w as A,h as n,i as x,z as v,r as g,k as b,m as z,s as N,q as S,j as r}from"./index-CeMVzSB6.js";const D={class:"min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-100 to-slate-200 px-4"},E={class:"w-full max-w-md"},L={class:"bg-white rounded-2xl shadow-xl p-8"},P=["disabled"],R={key:0,class:"mt-1 text-sm text-red-500"},q={class:"relative"},F=["type","disabled"],T={key:0,class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},U={key:1,class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},H={key:0,class:"mt-1 text-sm text-red-500"},J={key:0,class:"p-3 rounded-lg bg-red-50 text-red-600 text-sm"},K=["disabled"],O={key:0,class:"flex items-center justify-center gap-2"},$={key:1},G={class:"mt-6 flex items-center justify-between text-sm"},I={class:"text-center text-slate-400 text-sm mt-6"},X={__name:"Login",setup(Q){const y=N(),k=S(),_=V(),l=g({email:"",password:""}),s=g({}),i=b(""),a=b(!1),d=b(!1);async function M(){i.value="",Object.keys(s).forEach(e=>delete s[e]),a.value=!0;const m=await _.login(l.email,l.password);if(a.value=!1,m.success){const e=k.query.redirect||"/dashboard";y.push(e)}else i.value=m.message}return(m,e)=>{const c=z("router-link");return r(),o("div",D,[t("div",E,[e[13]||(e[13]=C('<div class="text-center mb-8"><div class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary mb-4"><svg class="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7"></path></svg></div><h1 class="text-2xl font-bold text-slate-800">fahrschuldesk</h1><p class="text-slate-500 mt-1">Verwaltung für Fahrschulen</p></div>',1)),t("div",L,[e[10]||(e[10]=t("h2",{class:"text-xl font-semibold text-slate-800 mb-6"},"Anmelden",-1)),t("form",{onSubmit:j(M,["prevent"]),class:"space-y-5"},[t("div",null,[e[3]||(e[3]=t("label",{class:"block text-sm font-medium text-slate-700 mb-1.5"},"E-Mail",-1)),h(t("input",{"onUpdate:modelValue":e[0]||(e[0]=u=>l.email=u),type:"email",placeholder:"ihre@email.de",class:w(["w-full px-4 py-2.5 rounded-lg border border-slate-300 focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all",{"border-red-400 focus:ring-red-200":s.email}]),disabled:a.value},null,10,P),[[B,l.email]]),s.email?(r(),o("p",R,p(s.email[0]),1)):f("",!0)]),t("div",null,[e[6]||(e[6]=t("label",{class:"block text-sm font-medium text-slate-700 mb-1.5"},"Passwort",-1)),t("div",q,[h(t("input",{"onUpdate:modelValue":e[1]||(e[1]=u=>l.password=u),type:d.value?"text":"password",placeholder:"••••••••",class:w(["w-full px-4 py-2.5 rounded-lg border border-slate-300 focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all pr-12",{"border-red-400 focus:ring-red-200":s.password}]),disabled:a.value},null,10,F),[[A,l.password]]),t("button",{type:"button",onClick:e[2]||(e[2]=u=>d.value=!d.value),class:"absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600"},[d.value?(r(),o("svg",T,[...e[4]||(e[4]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"},null,-1)])])):(r(),o("svg",U,[...e[5]||(e[5]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"},null,-1),t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"},null,-1)])]))])]),s.password?(r(),o("p",H,p(s.password[0]),1)):f("",!0)]),i.value?(r(),o("div",J,p(i.value),1)):f("",!0),t("button",{type:"submit",disabled:a.value,class:"w-full py-3 px-4 bg-primary text-white font-medium rounded-lg hover:bg-primary-600 focus:ring-4 focus:ring-primary-200 transition-all disabled:opacity-50 disabled:cursor-not-allowed"},[a.value?(r(),o("span",O,[...e[7]||(e[7]=[t("svg",{class:"animate-spin h-5 w-5",viewBox:"0 0 24 24"},[t("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4",fill:"none"}),t("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})],-1),n(" Anmelden... ",-1)])])):(r(),o("span",$,"Anmelden"))],8,K)],32),t("div",G,[x(c,{to:"/forgot-password",class:"text-primary hover:underline"},{default:v(()=>[...e[8]||(e[8]=[n(" Passwort vergessen? ",-1)])]),_:1}),x(c,{to:"/register",class:"text-slate-500 hover:text-slate-700"},{default:v(()=>[...e[9]||(e[9]=[n(" Registrieren → ",-1)])]),_:1})])]),t("p",I,[e[12]||(e[12]=n(" Noch kein Konto? ",-1)),x(c,{to:"/register",class:"text-primary hover:underline"},{default:v(()=>[...e[11]||(e[11]=[n("Jetzt Fahrschule registrieren",-1)])]),_:1})])])])}}};export{X as default};