1import{j as s}from"./vendor-query-BlmcqGn-.js";import{r as m}from"./vendor-react-pbBcp6-R.js";import{w as L,u as O,i as z,s as r,l as i,d as F,e as H,o as d,B as x,g as Q,h as X}from"./index-iIjFPxNK.js";import{B as G,C as J}from"./badge-Cm2ZJAcQ.js";import{T as K,a as W,b as j,c as p}from"./tabs-DJhC1J3G.js";import{U as w}from"./users-Bs1muW6N.js";import{S as k}from"./school-cps7hrwt.js";import{C as Y}from"./circle-x-y-FSagdE.js";import"./vendor-pdf-D7HrI6pR.js";import"./vendor-ui-CywTfEbH.js";import"./vendor-recharts-BiZDrFaJ.js";import"./vendor-supabase-DY6Dg61Y.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const Z=L("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]),ss=()=>{const{user:l,profile:a,signOut:es}=O();z();const[S,u]=m.useState([]),[b,N]=m.useState(null),[ts,y]=m.useState({}),[v,D]=m.useState([]),[h,E]=m.useState({}),f=[{id:"database-connectivity",name:"Database Connectivity Test",status:"pending"},{id:"user-profile-access",name:"User Profile Access Test",status:"pending"},{id:"school-data-access",name:"School Data Access Test",status:"pending"},{id:"role-permissions",name:"Role-Based Permissions Test",status:"pending"},{id:"data-visibility",name:"Data Visibility Test",status:"pending"},{id:"school-isolation",name:"School Data Isolation Test",status:"pending"},{id:"realtime-connection",name:"Real-time Connection Test",status:"pending"}];m.useEffect(()=>{u(f),U(),T()},[]);const U=async()=>{try{const{data:e}=await r.from("profiles").select("email, role, school_name").limit(10);if(e){const t=e.map(o=>({email:o.email||"Unknown",role:o.role||"Unknown",school:o.school_name||"Unknown School",description:`${o.role} - ${o.school_name||"Unknown School"}`,exists:!0}));D(t)}}catch(e){console.error("Error loading users:",e)}},T=async()=>{try{const[e,t,o,n]=await Promise.all([r.from("schools").select("*",{count:"exact",head:!0}),r.from("profiles").select("*",{count:"exact",head:!0}),r.from("students_new").select("*",{count:"exact",head:!0}),r.from("classrooms").select("*",{count:"exact",head:!0})]);E({schools:e.count||0,profiles:t.count||0,students:o.count||0,classrooms:n.count||0})}catch(e){console.error("Error loading data stats:",e)}},g=(e,t,o)=>{u(n=>n.map(c=>c.id===e?{...c,status:t,details:o,timestamp:new Date().toISOString()}:c))},C=async e=>{N(e),g(e,"running");try{switch(e){case"database-connectivity":await _();break;case"user-profile-access":await R();break;case"school-data-access":await A();break;case"role-permissions":await P();break;case"data-visibility":await $();break;case"school-isolation":await B();break;case"realtime-connection":await I();break;default:throw new Error("Unknown test")}g(e,"passed","Test completed successfully")}catch(t){console.error(`Test ${e} failed:`,t),g(e,"failed",t instanceof Error?t.message:"Unknown error")}finally{N(null)}},_=async()=>{const{data:e,error:t}=await r.from("profiles").select("count").limit(1);if(t)throw new Error(`Database connection failed: ${t.message}`);const o=["schools","profiles","students_new","classrooms"];for(const n of o){const{error:c}=await r.from(n).select("*").limit(1);if(c)throw new Error(`Table ${n} not accessible: ${c.message}`)}},R=async()=>{if(!l)throw new Error("No user logged in");const{data:e,error:t}=await r.from("profiles").select("*").eq("id",l.id).single();if(t)throw new Error(`Profile access failed: ${t.message}`);if(!e)throw new Error("User profile not found");y(o=>({...o,userProfile:e}))},A=async()=>{if(!(a!=null&&a.school_id))throw new Error(`No school ID in profile. Current school_name: "${a==null?void 0:a.school_name}"`);const{data:e,error:t}=await r.from("schools").select("*").eq("id",a.school_id).single();if(t)throw new Error(`School data access failed: ${t.message}`);if(!e)throw new Error("School data not found");console.log("School data successfully accessed:",e),y(o=>({...o,schoolData:e}))},P=async()=>{const e=a==null?void 0:a.role;if(!e)throw new Error("No user role found");let t;switch(e){case"parent":t=r.from("parent_student_link").select("*").eq("parent_id",l==null?void 0:l.id);break;case"teacher":t=r.from("classrooms").select("*").eq("teacher_id",l==null?void 0:l.id);break;case"admin":case"controller":t=r.from("schools").select("*");break;default:throw new Error(`Unknown role: ${e}`)}const{error:o}=await t;if(o)throw new Error(`Role permission test failed: ${o.message}`)},$=async()=>{const e=a==null?void 0:a.role,t=a==null?void 0:a.school_id,o=a==null?void 0:a.school_name;if(!e)throw new Error("Missing user role");
6if(!t&&!o)throw new Error("Missing both school ID and school name");console.log("Testing data visibility with:",{userRole:e,schoolId:t,schoolName:o});const{data:n,error:c}=await r.from("students_new").select("*").eq("school_uuid",t||"").limit(5);if(c)throw new Error(`Own school data access failed: ${c.message}`);console.log("Data visibility test passed. Accessible students:",(n==null?void 0:n.length)||0)},B=async()=>{const{data:e,error:t}=await r.from("schools").select("id, name").limit(5);if(t)throw new Error(`Failed to fetch schools: ${t.message}`);console.log("School isolation test - available schools:",(e==null?void 0:e.length)||0)},I=async()=>{const e=r.channel("test-realtime").on("postgres_changes",{event:"*",schema:"public",table:"profiles"},t=>{console.log("Realtime test - received:",t)}).subscribe();if(await new Promise(t=>setTimeout(t,2e3)),e.state!=="joined")throw await r.removeChannel(e),new Error("Failed to establish realtime connection");await r.removeChannel(e)},V=async()=>{for(const e of f)e.status!=="passed"&&(await C(e.id),await new Promise(t=>setTimeout(t,500)))},q=e=>{switch(e){case"passed":return s.jsx(X,{className:"h-4 w-4 text-green-600"});case"failed":return s.jsx(Y,{className:"h-4 w-4 text-red-600"});case"running":return s.jsx(J,{className:"h-4 w-4 text-blue-600 animate-spin"});default:return s.jsx(Q,{className:"h-4 w-4 text-gray-400"})}},M=e=>{switch(e){case"passed":return"bg-green-100 text-green-800";case"failed":return"bg-red-100 text-red-800";case"running":return"bg-blue-100 text-blue-800";default:return"bg-gray-100 text-gray-800"}};return s.jsx("div",{className:"max-w-6xl mx-auto p-6 space-y-6",children:s.jsxs(i,{children:[s.jsxs(F,{children:[s.jsxs(H,{className:"flex items-center gap-2",children:[s.jsx(Z,{className:"h-5 w-5"}),"RBAC & Database Testing Dashboard"]}),s.jsx("p",{className:"text-muted-foreground",children:"Test role-based access control, database connectivity, and data visibility with real user data"})]}),s.jsxs(d,{children:[s.jsxs("div",{className:"flex gap-4 mb-6",children:[s.jsx(x,{onClick:V,disabled:b!==null,children:"Run All Tests"}),s.jsx(x,{variant:"outline",onClick:()=>u(f.map(e=>({...e,status:"pending"}))),children:"Reset Tests"}),s.jsx(x,{variant:"outline",onClick:T,children:"Refresh Data"})]}),s.jsxs(K,{defaultValue:"test-results",className:"w-full",children:[s.jsxs(W,{children:[s.jsx(j,{value:"test-results",children:"Test Results"}),s.jsx(j,{value:"current-user",children:"Current User"}),s.jsx(j,{value:"database-stats",children:"Database Stats"})]}),s.jsx(p,{value:"test-results",className:"space-y-4",children:S.map(e=>s.jsx(i,{children:s.jsxs(d,{className:"flex items-center justify-between p-4",children:[s.jsxs("div",{className:"flex items-center gap-3",children:[q(e.status),s.jsxs("div",{children:[s.jsx("h3",{className:"font-medium",children:e.name}),e.details&&s.jsx("p",{className:"text-sm text-muted-foreground",children:e.details}),e.timestamp&&s.jsx("p",{className:"text-xs text-muted-foreground",children:new Date(e.timestamp).toLocaleTimeString()})]})]}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(G,{className:M(e.status),children:e.status}),s.jsx(x,{size:"sm",variant:"outline",onClick:()=>C(e.id),disabled:b!==null,children:"Run Test"})]})]})},e.id))}),s.jsxs(p,{value:"current-user",className:"space-y-4",children:[s.jsx(i,{children:s.jsxs(d,{className:"p-6",children:[s.jsxs("h3",{className:"font-bold mb-4 flex items-center gap-2",children:[s.jsx(w,{className:"h-4 w-4"}),"Current User Information"]}),s.jsxs("div",{className:"space-y-2",children:[s.jsxs("p",{children:[s.jsx("strong",{children:"Email:"})," ",(l==null?void 0:l.email)||"Not logged in"]}),s.jsxs("p",{children:[s.jsx("strong",{children:"Role:"})," ",(a==null?void 0:a.role)||"Unknown"]}),s.jsxs("p",{children:[s.jsx("strong",{children:"School Name:"})," ",(a==null?void 0:a.school_name)||"Unknown"]}),s.jsxs("p",{children:[s.jsx("strong",{children:"School ID:"})," ",(a==null?void 0:a.school_id)||"Not set"]}),s.jsxs("p",{children:[s.jsx("strong",{children:"User ID:"})," ",(l==null?void 0:l.id)||"Unknown"]}),a!=null&&a.school_id?s.jsxs("div",{className:"mt-4 p-3 bg-green-50 border border-green-200 rounded-lg",children:[s.jsx("p",{className:"text-green-700 font-medium",children:"â
Profile Status: Complete"}),s.jsx("p",{className:"text-green-600 text-sm",children:"Profile has both school_name and school_id properly set. All tests should pass now."})]}):s.jsxs("div",{className:"mt-4 p-3 bg-yellow-50 border border-yellow-200 rounded-lg",children:[s.jsx("p",{className:"text-yellow-700 font-medium",children:"â ï¸ Profile Issue Detected:"}),s.jsx("p",{className:"text-yellow-600 text-sm",children:"Profile is missing school_id. This may cause some test failures. Try refreshing the page or re-logging in to update your profile."})]})]})]})}),s.jsx(i,{children:s.jsxs(d,{className:"p-6",children:[s.jsx("h3",{className:"font-bold mb-4",children:"Available Test Users"}),s.jsx("div",{className:"space-y-2 max-h-60 overflow-y-auto",children:v.length>0?v.map((e,t)=>s.jsxs("div",{className:"p-3 border rounded-lg",children:[s.jsx("p",{className:"font-medium",children:e.description}),s.jsxs("p",{className:"text-sm text-muted-foreground",children:["Email: ",e.email]}),s.jsxs("p",{className:"text-sm text-muted-foreground",children:["Role: ",e.role]})]},t)):s.jsx("p",{className:"text-muted-foreground",children:"No users loaded yet"})})]})})]}),s.jsxs(p,{value:"database-stats",className:"space-y-4",children:[s.jsxs("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-4",children:[s.jsx(i,{children:s.jsxs(d,{className:"p-4",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(k,{className:"h-4 w-4 text-blue-600"}),s.jsx("h3",{className:"font-semibold",children:"Schools"})]}),s.jsx("p",{className:"text-2xl font-bold",children:h.schools||0})]})}),s.jsx(i,{children:s.jsxs(d,{className:"p-4",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(w,{className:"h-4 w-4 text-green-600"}),s.jsx("h3",{className:"font-semibold",children:"Users"})]}),s.jsx("p",{className:"text-2xl font-bold",children:h.profiles||0})]})}),s.jsx(i,{children:s.jsxs(d,{className:"p-4",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(w,{className:"h-4 w-4 text-purple-600"}),s.jsx("h3",{className:"font-semibold",children:"Students"})]}),s.jsx("p",{className:"text-2xl font-bold",children:h.students||0})]})}),s.jsx(i,{children:s.jsxs(d,{className:"p-4",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(k,{className:"h-4 w-4 text-orange-600"}),s.jsx("h3",{className:"font-semibold",children:"Classrooms"})]}),s.jsx("p",{className:"text-2xl font-bold",children:h.classrooms||0})]})})]}),s.jsx(i,{children:s.jsxs(d,{className:"p-6",children:[s.jsx("h3",{className:"font-bold mb-4",children:"Testing Instructions"}),s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{children:[s.jsx("h4",{className:"font-semibold text-blue-600 mb-2",children:"Automated Tests"}),s.jsx("p",{className:"text-sm text-muted-foreground mb-2",children:"These tests use your current login session and real database data:"}),s.jsxs("ul",{className:"list-disc list-inside space-y-1 text-sm",children:[s.jsx("li",{children:"Database connectivity and table access"}),s.jsx("li",{children:"User profile and role permissions"}),s.jsx("li",{children:"School data access and isolation"}),s.jsx("li",{children:"Real-time connection testing"})]})]}),s.jsxs("div",{children:[s.jsx("h4",{className:"font-semibold text-green-600 mb-2",children:"Manual Verification"}),s.jsxs("ul",{className:"list-disc list-inside space-y-1 text-sm",children:[s.jsx("li",{children:"Check the Current User tab to verify your role and permissions"}),s.jsx("li",{children:"Compare Database Stats with expected data in your system"}),s.jsx("li",{children:"Test different user roles by logging in with different accounts"}),s.jsx("li",{children:"Verify that school isolation prevents cross-school data access"})]})]})]})]})})]})]})]})]})})},fs=()=>s.jsx("div",{className:"min-h-screen bg-gray-50",children:s.jsx(ss,{})});
6export{fs as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.