openlearn-next 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/assets/AdminDirectoryView-Cai0cQqi.js +1 -0
  2. package/dist/assets/BatchPickerModal-CKQyeY6R.js +1 -0
  3. package/dist/assets/ClassesView-Cxgfcrx1.js +19 -0
  4. package/dist/assets/CloudDriveModal-DgDurUBT.js +1 -0
  5. package/dist/assets/ComputerLabView-CUCO2VIV.js +1 -0
  6. package/dist/assets/CourseManagement-DSCOjuIC.js +1 -0
  7. package/dist/assets/CourseWizardModal-B3QnFxvj.js +3 -0
  8. package/dist/assets/CoursewareHubPanel-CAaf22Qm.js +1 -0
  9. package/dist/assets/Dashboard-BnF7YAQi.js +8 -0
  10. package/dist/assets/ExportWeightModal-BlS2auLs.js +1 -0
  11. package/dist/assets/HelpTour-ZgEkRnin.js +1 -0
  12. package/dist/assets/HelpView-BP581QYZ.js +204 -0
  13. package/dist/assets/ImportLessonsModal-BZZRDBRU.js +1 -0
  14. package/dist/assets/ImportModal-mkWuDoAN.js +1 -0
  15. package/dist/assets/InteractiveCoursewareViewer-EIRNulEo.js +1 -0
  16. package/dist/assets/InteractiveWhiteboard-D360IHbP.js +102 -0
  17. package/dist/assets/LazyCourseware-qE4CY67E.js +1 -0
  18. package/dist/assets/LazyWhiteboard-B5JmqHZ5.js +2 -0
  19. package/dist/assets/LessonEditorView-C0czhtmf.js +1 -0
  20. package/dist/assets/LiveClassroomView-CrTY3jhP.js +1 -0
  21. package/dist/assets/NotificationDetailModal-dndFrE7p.js +1 -0
  22. package/dist/assets/PluginView-QS2b6nSF.js +65 -0
  23. package/dist/assets/ProcessLogsModal-8mVp07ic.js +1 -0
  24. package/dist/assets/QuizGeneratorModal-DpTFYbVJ.js +1 -0
  25. package/dist/assets/StudentAssignmentView-YxVJ5wkl.js +1 -0
  26. package/dist/assets/StudentLessonView-D1gYdLM1.js +1 -0
  27. package/dist/assets/StudentPreviewModal-CG8bgUeI.js +1 -0
  28. package/dist/assets/StudentView-CmSL3cDw.js +1 -0
  29. package/dist/assets/SystemResourceLibraryModal-Dnh7F5Vm.js +1 -0
  30. package/dist/assets/TeacherView-BqXb0izg.js +2 -0
  31. package/dist/assets/TimetableView-zce3okQn.js +6 -0
  32. package/dist/assets/index-BrEBeWAQ.js +14 -0
  33. package/dist/assets/index-BxA9vp--.js +129 -0
  34. package/dist/assets/index-CATki2cp.css +1 -0
  35. package/dist/assets/index-Cq_aKTfc.js +1 -0
  36. package/dist/assets/{index.es-CF5dm42F.js → index.es-DZ6UeYE-.js} +2 -2
  37. package/dist/assets/vendor-charts-B7ViBL9w.js +71 -0
  38. package/dist/assets/vendor-icons-BvCtGbt1.js +8221 -0
  39. package/dist/assets/vendor-konva-CzxOmTv9.js +49 -0
  40. package/dist/assets/vendor-motion-Dz5URUo4.js +9 -0
  41. package/dist/assets/vendor-pdf-CVyNPGVr.js +191 -0
  42. package/dist/assets/{vendor-pptx-CJ3I-KT0.js → vendor-pptx-B0hlo0eh.js} +1 -1
  43. package/dist/assets/vendor-react-0Lg0vA-4.js +49 -0
  44. package/dist/assets/vendor-utils-4FcTwKPj.js +1 -0
  45. package/dist/index.html +2 -3
  46. package/dist/server.cjs +93 -43
  47. package/package.json +1 -1
  48. package/dist/assets/courseware-Cc-Yy0Ha.js +0 -1
  49. package/dist/assets/index-CsN5CIqI.css +0 -1
  50. package/dist/assets/index-D_zAVH7u.js +0 -682
  51. package/dist/assets/vendor-html2canvas-B0tyYwQk.js +0 -22
  52. package/dist/assets/vendor-konva-GivUq6dt.js +0 -89
  53. package/dist/assets/whiteboard-jgQrAUm7.js +0 -8343
  54. /package/dist/assets/{purify.es-V6uLfjnH.js → vendor-content-V6uLfjnH.js} +0 -0
@@ -0,0 +1 @@
1
+ import{R as O,g as A,c as re}from"./vendor-react-0Lg0vA-4.js";const ee=n=>{let r;const t=new Set,s=(u,e)=>{const o=typeof u=="function"?u(r):u;if(!Object.is(o,r)){const l=r;r=e??(typeof o!="object"||o===null)?o:Object.assign({},r,o),t.forEach(g=>g(r,l))}},i=()=>r,c={setState:s,getState:i,getInitialState:()=>y,subscribe:u=>(t.add(u),()=>t.delete(u))},y=r=n(s,i,c);return c},Xt=(n=>n?ee(n):ee),Jt=n=>n;function Qt(n,r=Jt){const t=O.useSyncExternalStore(n.subscribe,O.useCallback(()=>r(n.getState()),[n,r]),O.useCallback(()=>r(n.getInitialState()),[n,r]));return O.useDebugValue(t),t}const Yt=n=>{const r=Xt(n),t=s=>Qt(r,s);return Object.assign(t,r),t},li=(n=>Yt);function St(n){var r,t,s="";if(typeof n=="string"||typeof n=="number")s+=n;else if(typeof n=="object")if(Array.isArray(n)){var i=n.length;for(r=0;r<i;r++)n[r]&&(t=St(n[r]))&&(s&&(s+=" "),s+=t)}else for(t in n)n[t]&&(s&&(s+=" "),s+=t);return s}function gi(){for(var n,r,t=0,s="",i=arguments.length;t<i;t++)(n=arguments[t])&&(r=St(n))&&(s&&(s+=" "),s+=r);return s}var w={},x={},te;function vt(){if(te)return x;te=1;function n(r){return r==="__proto__"}return x.isUnsafeProperty=n,x}var j={},ne;function _(){if(ne)return j;ne=1;function n(r){switch(typeof r){case"number":case"symbol":return!1;case"string":return r.includes(".")||r.includes("[")||r.includes("]")}}return j.isDeepKey=n,j}var T={},ie;function S(){if(ie)return T;ie=1;function n(r){return typeof r=="string"||typeof r=="symbol"?r:Object.is(r?.valueOf?.(),-0)?"-0":String(r)}return T.toKey=n,T}var M={},L={},se;function Ct(){if(se)return L;se=1;function n(r){if(r==null)return"";if(typeof r=="string")return r;if(Array.isArray(r))return r.map(n).join(",");const t=String(r);return t==="0"&&Object.is(Number(r),-0)?"-0":t}return L.toString=n,L}var ue;function v(){if(ue)return M;ue=1;const n=S(),r=Ct();function t(s){if(Array.isArray(s))return s.map(n.toKey);if(typeof s=="symbol")return[s];s=r.toString(s);const i=[],a=s.length;if(a===0)return i;let f=0,c="",y="",u=!1;for(s.charCodeAt(0)===46&&(i.push(""),f++);f<a;){const e=s[f];y?e==="\\"&&f+1<a?(f++,c+=s[f]):e===y?y="":c+=e:u?e==='"'||e==="'"?y=e:e==="]"?(u=!1,i.push(c),c=""):c+=e:e==="["?(u=!0,c&&(i.push(c),c="")):e==="."?c&&(i.push(c),c=""):c+=e,f++}return c&&i.push(c),i}return M.toPath=t,M}var ae;function P(){if(ae)return w;ae=1;const n=vt(),r=_(),t=S(),s=v();function i(f,c,y){if(f==null)return y;switch(typeof c){case"string":{if(n.isUnsafeProperty(c))return y;const u=f[c];return u===void 0?r.isDeepKey(c)?i(f,s.toPath(c),y):y:u}case"number":case"symbol":{typeof c=="number"&&(c=t.toKey(c));const u=f[c];return u===void 0?y:u}default:{if(Array.isArray(c))return a(f,c,y);if(Object.is(c?.valueOf(),-0)?c="-0":c=String(c),n.isUnsafeProperty(c))return y;const u=f[c];return u===void 0?y:u}}}function a(f,c,y){if(c.length===0)return y;let u=f;for(let e=0;e<c.length;e++){if(u==null||n.isUnsafeProperty(c[e]))return y;u=u[c[e]]}return u===void 0?y:u}return w.get=i,w}var E,oe;function rn(){return oe||(oe=1,E=P().get),E}var en=rn();const qi=A(en);var W={},K={},fe;function tn(){if(fe)return K;fe=1;function n(r,t){const s=new Map;for(let i=0;i<r.length;i++){const a=r[i],f=t(a,i,r);s.has(f)||s.set(f,a)}return Array.from(s.values())}return K.uniqBy=n,K}var N={},ce;function nn(){if(ce)return N;ce=1;function n(r,t){return function(...s){return r.apply(this,s.slice(0,t))}}return N.ary=n,N}var U={},ye;function R(){if(ye)return U;ye=1;function n(r){return r}return U.identity=n,U}var k={},F={},le;function sn(){if(le)return F;le=1;const n=P();function r(t){return function(s){return n.get(s,t)}}return F.property=r,F}var G={},Z={},$={},V={},ge;function Pt(){if(ge)return V;ge=1;function n(r){return r==null||typeof r!="object"&&typeof r!="function"}return V.isPrimitive=n,V}var z={},qe;function Rt(){if(qe)return z;qe=1;function n(r){return ArrayBuffer.isView(r)&&!(r instanceof DataView)}return z.isTypedArray=n,z}var H={},he;function Dt(){if(he)return H;he=1;function n(r){return Object.getOwnPropertySymbols(r).filter(t=>Object.prototype.propertyIsEnumerable.call(r,t))}return H.getSymbols=n,H}var X={},me;function Cr(){if(me)return X;me=1;function n(r){return r==null?r===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(r)}return X.getTag=n,X}var p={},de;function wt(){if(de)return p;de=1;const n="[object RegExp]",r="[object String]",t="[object Number]",s="[object Boolean]",i="[object Arguments]",a="[object Symbol]",f="[object Date]",c="[object Map]",y="[object Set]",u="[object Array]",e="[object Function]",o="[object ArrayBuffer]",l="[object Object]",g="[object Error]",h="[object DataView]",m="[object Uint8Array]",q="[object Uint8ClampedArray]",d="[object Uint16Array]",b="[object Uint32Array]",I="[object BigUint64Array]",Ft="[object Int8Array]",Gt="[object Int16Array]",Zt="[object Int32Array]",Vt="[object BigInt64Array]",zt="[object Float32Array]",Ht="[object Float64Array]";return p.argumentsTag=i,p.arrayBufferTag=o,p.arrayTag=u,p.bigInt64ArrayTag=Vt,p.bigUint64ArrayTag=I,p.booleanTag=s,p.dataViewTag=h,p.dateTag=f,p.errorTag=g,p.float32ArrayTag=zt,p.float64ArrayTag=Ht,p.functionTag=e,p.int16ArrayTag=Gt,p.int32ArrayTag=Zt,p.int8ArrayTag=Ft,p.mapTag=c,p.numberTag=t,p.objectTag=l,p.regexpTag=n,p.setTag=y,p.stringTag=r,p.symbolTag=a,p.uint16ArrayTag=d,p.uint32ArrayTag=b,p.uint8ArrayTag=m,p.uint8ClampedArrayTag=q,p}var J={},Q={},pe;function un(){if(pe)return Q;pe=1;const n=typeof globalThis=="object"&&globalThis||typeof window=="object"&&window||typeof self=="object"&&self||typeof re=="object"&&re||(function(){return this})()||Function("return this")();return Q.globalThis_=n,Q}var be;function xt(){if(be)return J;be=1;const n=un();function r(t){return typeof n.globalThis_.Buffer<"u"&&n.globalThis_.Buffer.isBuffer(t)}return J.isBuffer=r,J}var Ae;function jt(){if(Ae)return $;Ae=1;const n=Pt(),r=Rt(),t=Dt(),s=Cr(),i=wt(),a=xt();function f(e,o){return c(e,void 0,e,new Map,o)}function c(e,o,l,g=new Map,h=void 0){const m=h?.(e,o,l,g);if(m!==void 0)return m;if(n.isPrimitive(e))return e;if(g.has(e))return g.get(e);if(Array.isArray(e)){const q=new Array(e.length);g.set(e,q);for(let d=0;d<e.length;d++)q[d]=c(e[d],d,l,g,h);return Object.hasOwn(e,"index")&&(q.index=e.index),Object.hasOwn(e,"input")&&(q.input=e.input),q}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp){const q=new RegExp(e.source,e.flags);return q.lastIndex=e.lastIndex,q}if(e instanceof Map){const q=new Map;g.set(e,q);for(const[d,b]of e)q.set(d,c(b,d,l,g,h));return q}if(e instanceof Set){const q=new Set;g.set(e,q);for(const d of e)q.add(c(d,void 0,l,g,h));return q}if(a.isBuffer(e))return e.subarray();if(r.isTypedArray(e)){const q=new(Object.getPrototypeOf(e)).constructor(e.length);g.set(e,q);for(let d=0;d<e.length;d++)q[d]=c(e[d],d,l,g,h);return q}if(e instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&e instanceof SharedArrayBuffer)return e.slice(0);if(e instanceof DataView){const q=new DataView(e.buffer.slice(0),e.byteOffset,e.byteLength);return g.set(e,q),y(q,e,l,g,h),q}if(typeof File<"u"&&e instanceof File){const q=new File([e],e.name,{type:e.type});return g.set(e,q),y(q,e,l,g,h),q}if(typeof Blob<"u"&&e instanceof Blob){const q=new Blob([e],{type:e.type});return g.set(e,q),y(q,e,l,g,h),q}if(e instanceof Error){const q=structuredClone(e);return g.set(e,q),q.message=e.message,q.name=e.name,q.stack=e.stack,q.cause=e.cause,q.constructor=e.constructor,y(q,e,l,g,h),q}if(e instanceof Boolean){const q=new Boolean(e.valueOf());return g.set(e,q),y(q,e,l,g,h),q}if(e instanceof Number){const q=new Number(e.valueOf());return g.set(e,q),y(q,e,l,g,h),q}if(e instanceof String){const q=new String(e.valueOf());return g.set(e,q),y(q,e,l,g,h),q}if(typeof e=="object"&&u(e)){const q=Object.create(Object.getPrototypeOf(e));return g.set(e,q),y(q,e,l,g,h),q}return e}function y(e,o,l=e,g,h){const m=[...Object.keys(o),...t.getSymbols(o)];for(let q=0;q<m.length;q++){const d=m[q],b=Object.getOwnPropertyDescriptor(e,d);(b==null||b.writable)&&(e[d]=c(o[d],d,l,g,h))}}function u(e){switch(s.getTag(e)){case i.argumentsTag:case i.arrayTag:case i.arrayBufferTag:case i.dataViewTag:case i.booleanTag:case i.dateTag:case i.float32ArrayTag:case i.float64ArrayTag:case i.int8ArrayTag:case i.int16ArrayTag:case i.int32ArrayTag:case i.mapTag:case i.numberTag:case i.objectTag:case i.regexpTag:case i.setTag:case i.stringTag:case i.symbolTag:case i.uint8ArrayTag:case i.uint8ClampedArrayTag:case i.uint16ArrayTag:case i.uint32ArrayTag:return!0;default:return!1}}return $.cloneDeepWith=f,$.cloneDeepWithImpl=c,$.copyProperties=y,$}var Ie;function an(){if(Ie)return Z;Ie=1;const n=jt();function r(t){return n.cloneDeepWithImpl(t,void 0,t,new Map,void 0)}return Z.cloneDeep=r,Z}var Y={},C={},rr={},$e;function Tt(){if($e)return rr;$e=1;function n(r,t){return r===t||Number.isNaN(r)&&Number.isNaN(t)}return rr.isEqualsSameValueZero=n,rr}var er={},Be;function Mt(){if(Be)return er;Be=1;function n(r){return r!==null&&(typeof r=="object"||typeof r=="function")}return er.isObject=n,er}var Oe;function on(){if(Oe)return C;Oe=1;const n=Pt(),r=Tt(),t=Mt();function s(u,e,o){return typeof o!="function"?s(u,e,()=>{}):i(u,e,function l(g,h,m,q,d,b){const I=o(g,h,m,q,d,b);return I!==void 0?!!I:i(g,h,l,b)},new Map)}function i(u,e,o,l){if(e===u)return!0;switch(typeof e){case"object":return a(u,e,o,l);case"function":return Object.keys(e).length>0?i(u,{...e},o,l):r.isEqualsSameValueZero(u,e);default:return t.isObject(u)?typeof e=="string"?e==="":!0:r.isEqualsSameValueZero(u,e)}}function a(u,e,o,l){if(e==null)return!0;if(Array.isArray(e))return c(u,e,o,l);if(e instanceof Map)return f(u,e,o,l);if(e instanceof Set)return y(u,e,o,l);const g=Object.keys(e);if(u==null||n.isPrimitive(u))return g.length===0;if(g.length===0)return!0;if(l?.has(e))return l.get(e)===u;l?.set(e,u);try{for(let h=0;h<g.length;h++){const m=g[h];if(!n.isPrimitive(u)&&!(m in u)||e[m]===void 0&&u[m]!==void 0||e[m]===null&&u[m]!==null||!o(u[m],e[m],m,u,e,l))return!1}return!0}finally{l?.delete(e)}}function f(u,e,o,l){if(e.size===0)return!0;if(!(u instanceof Map))return!1;for(const[g,h]of e.entries())if(o(u.get(g),h,g,u,e,l)===!1)return!1;return!0}function c(u,e,o,l){if(e.length===0)return!0;if(!Array.isArray(u))return!1;const g=new Set;for(let h=0;h<e.length;h++){const m=e[h];let q=!1;for(let d=0;d<u.length;d++){if(g.has(d))continue;const b=u[d];let I=!1;if(o(b,m,h,u,e,l)&&(I=!0),I){g.add(d),q=!0;break}}if(!q)return!1}return!0}function y(u,e,o,l){return e.size===0?!0:u instanceof Set?c([...u],[...e],o,l):!1}return C.isMatchWith=s,C}var _e;function Lt(){if(_e)return Y;_e=1;const n=on();function r(t,s){return n.isMatchWith(t,s,()=>{})}return Y.isMatch=r,Y}var Se;function fn(){if(Se)return G;Se=1;const n=an(),r=Lt();function t(s){return s=n.cloneDeep(s),i=>r.isMatch(i,s)}return G.matches=t,G}var tr={},nr={},ir={},ve;function Et(){if(ve)return ir;ve=1;const n=Cr(),r=wt(),t=jt();function s(i,a){return t.cloneDeepWith(i,(f,c,y,u)=>{const e=a?.(f,c,y,u);if(e!==void 0)return e;if(typeof i=="object"){if(n.getTag(i)==="[object Object]"&&typeof i.constructor!="function"){const o={};return u.set(i,o),t.copyProperties(o,i,y,u),o}switch(Object.prototype.toString.call(i)){case r.numberTag:case r.stringTag:case r.booleanTag:{const o=new i.constructor(i?.valueOf());return t.copyProperties(o,i),o}case r.argumentsTag:{const o={};return t.copyProperties(o,i),o.length=i.length,o[Symbol.iterator]=i[Symbol.iterator],o}default:return}}})}return ir.cloneDeepWith=s,ir}var Pe;function cn(){if(Pe)return nr;Pe=1;const n=Et();function r(t){return n.cloneDeepWith(t)}return nr.cloneDeep=r,nr}var sr={},ur={},Re;function Wt(){if(Re)return ur;Re=1;const n=/^(?:0|[1-9]\d*)$/;function r(t,s=Number.MAX_SAFE_INTEGER){switch(typeof t){case"number":return Number.isInteger(t)&&t>=0&&t<s;case"symbol":return!1;case"string":return n.test(t)}}return ur.isIndex=r,ur}var ar={},De;function yn(){if(De)return ar;De=1;const n=Cr();function r(t){return t!==null&&typeof t=="object"&&n.getTag(t)==="[object Arguments]"}return ar.isArguments=r,ar}var we;function ln(){if(we)return sr;we=1;const n=_(),r=v(),t=Wt(),s=yn();function i(a,f){let c;if(Array.isArray(f)?c=f:typeof f=="string"&&n.isDeepKey(f)&&a?.[f]==null?c=r.toPath(f):c=[f],c.length===0)return!1;let y=a;for(let u=0;u<c.length;u++){const e=c[u];if((y==null||!Object.hasOwn(y,e))&&!((Array.isArray(y)||s.isArguments(y))&&t.isIndex(e)&&e<y.length))return!1;y=y[e]}return!0}return sr.has=i,sr}var xe;function gn(){if(xe)return tr;xe=1;const n=S(),r=P(),t=Lt(),s=cn(),i=ln();function a(f,c){switch(typeof f){case"object":Object.is(f?.valueOf(),-0)&&(f="-0");break;case"number":f=n.toKey(f);break}return c=s.cloneDeep(c),function(y){const u=r.get(y,f);return u===void 0?i.has(y,f):c===void 0?u===void 0:t.isMatch(u,c)}}return tr.matchesProperty=a,tr}var je;function D(){if(je)return k;je=1;const n=R(),r=sn(),t=fn(),s=gn();function i(a){if(a==null)return n.identity;switch(typeof a){case"function":return a;case"object":return Array.isArray(a)&&a.length===2?s.matchesProperty(a[0],a[1]):t.matches(a);case"string":case"symbol":case"number":return r.property(a)}}return k.iteratee=i,k}var or={},fr={},cr={},Te;function qn(){if(Te)return cr;Te=1;function n(r){return Number.isSafeInteger(r)&&r>=0}return cr.isLength=n,cr}var Me;function B(){if(Me)return fr;Me=1;const n=qn();function r(t){return t!=null&&typeof t!="function"&&n.isLength(t.length)}return fr.isArrayLike=r,fr}var yr={},Le;function hn(){if(Le)return yr;Le=1;function n(r){return typeof r=="object"&&r!==null}return yr.isObjectLike=n,yr}var Ee;function mn(){if(Ee)return or;Ee=1;const n=B(),r=hn();function t(s){return r.isObjectLike(s)&&n.isArrayLike(s)}return or.isArrayLikeObject=t,or}var We;function dn(){if(We)return W;We=1;const n=tn(),r=nn(),t=R(),s=D(),i=mn();function a(f,c=t.identity){return i.isArrayLikeObject(f)?n.uniqBy(Array.from(f),r.ary(s.iteratee(c),1)):[]}return W.uniqBy=a,W}var lr,Ke;function pn(){return Ke||(Ke=1,lr=dn().uniqBy),lr}var bn=pn();const hi=A(bn);var gr={},qr={},Ne;function An(){if(Ne)return qr;Ne=1;function n(r,t=1){const s=[],i=Math.floor(t),a=(f,c)=>{for(let y=0;y<f.length;y++){const u=f[y];Array.isArray(u)&&c<i?a(u,c+1):s.push(u)}};return a(r,0),s}return qr.flatten=n,qr}var hr={},Ue;function Kt(){if(Ue)return hr;Ue=1;const n=Tt(),r=B(),t=Mt(),s=Wt();function i(a,f,c){return t.isObject(c)&&(typeof f=="number"&&r.isArrayLike(c)&&s.isIndex(f)&&f<c.length||typeof f=="string"&&f in c)?n.isEqualsSameValueZero(c[f],a):!1}return hr.isIterateeCall=i,hr}var mr={},dr={},ke;function In(){if(ke)return dr;ke=1;function n(t){return typeof t=="symbol"?1:t===null?2:t===void 0?3:t!==t?4:0}const r=(t,s,i)=>{if(t!==s){const a=n(t),f=n(s);if(a===f&&a===0){if(t<s)return i==="desc"?1:-1;if(t>s)return i==="desc"?-1:1}return i==="desc"?f-a:a-f}return 0};return dr.compareValues=r,dr}var pr={},br={},Fe;function Nt(){if(Fe)return br;Fe=1;function n(r){return typeof r=="symbol"||r instanceof Symbol}return br.isSymbol=n,br}var Ge;function $n(){if(Ge)return pr;Ge=1;const n=Nt(),r=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,t=/^\w*$/;function s(i,a){return Array.isArray(i)?!1:typeof i=="number"||typeof i=="boolean"||i==null||n.isSymbol(i)?!0:typeof i=="string"&&(t.test(i)||!r.test(i))||a!=null&&Object.hasOwn(a,i)}return pr.isKey=s,pr}var Ze;function Bn(){if(Ze)return mr;Ze=1;const n=v(),r=In(),t=$n();function s(i,a,f,c){if(i==null)return[];f=c?void 0:f,Array.isArray(i)||(i=Object.values(i)),Array.isArray(a)||(a=a==null?[null]:[a]),a.length===0&&(a=[null]),Array.isArray(f)||(f=f==null?[]:[f]),f=f.map(o=>String(o));const y=(o,l)=>{let g=o;for(let h=0;h<l.length&&g!=null;++h)g=g[l[h]];return g},u=(o,l)=>l==null||o==null?l:typeof o=="object"&&"key"in o?Object.hasOwn(l,o.key)?l[o.key]:y(l,o.path):typeof o=="function"?o(l):Array.isArray(o)?y(l,o):typeof l=="object"?l[o]:l,e=a.map(o=>(Array.isArray(o)&&o.length===1&&(o=o[0]),o==null||typeof o=="function"||Array.isArray(o)||t.isKey(o)?o:{key:o,path:n.toPath(o)}));return i.map(o=>({original:o,criteria:e.map(l=>u(l,o))})).slice().sort((o,l)=>{for(let g=0;g<e.length;g++){const h=r.compareValues(o.criteria[g],l.criteria[g],f[g]);if(h!==0)return h}return 0}).map(o=>o.original)}return mr.orderBy=s,mr}var Ve;function On(){if(Ve)return gr;Ve=1;const n=An(),r=Kt(),t=Bn();function s(i,...a){const f=a.length;return f>1&&r.isIterateeCall(i,a[0],a[1])?a=[]:f>2&&r.isIterateeCall(a[0],a[1],a[2])&&(a=[a[0]]),t.orderBy(i,n.flatten(a),["asc"])}return gr.sortBy=s,gr}var Ar,ze;function _n(){return ze||(ze=1,Ar=On().sortBy),Ar}var Sn=_n();const mi=A(Sn);var Ir={},$r={},Br={},He;function vn(){if(He)return Br;He=1;function n(r,t,{signal:s,edges:i}={}){let a,f=null;const c=i!=null&&i.includes("leading"),y=i==null||i.includes("trailing"),u=()=>{f!==null&&(r.apply(a,f),a=void 0,f=null)},e=()=>{y&&u(),h()};let o=null;const l=()=>{o!=null&&clearTimeout(o),o=setTimeout(()=>{o=null,e()},t)},g=()=>{o!==null&&(clearTimeout(o),o=null)},h=()=>{g(),a=void 0,f=null},m=()=>{u()},q=function(...d){if(s?.aborted)return;a=this,f=d;const b=o==null;l(),c&&b&&u()};return q.schedule=l,q.cancel=h,q.flush=m,s?.addEventListener("abort",h,{once:!0}),q}return Br.debounce=n,Br}var Xe;function Pn(){if(Xe)return $r;Xe=1;const n=vn();function r(t,s=0,i={}){typeof i!="object"&&(i={});const{leading:a=!1,trailing:f=!0,maxWait:c}=i,y=Array(2);a&&(y[0]="leading"),f&&(y[1]="trailing");let u,e=null;const o=n.debounce(function(...h){u=t.apply(this,h),e=null},s,{edges:y}),l=function(...h){return c!=null&&(e===null&&(e=Date.now()),Date.now()-e>=c)?(u=t.apply(this,h),e=Date.now(),o.cancel(),o.schedule(),u):(o.apply(this,h),u)},g=()=>(o.flush(),u);return l.cancel=o.cancel,l.flush=g,l}return $r.debounce=r,$r}var Je;function Rn(){if(Je)return Ir;Je=1;const n=Pn();function r(t,s=0,i={}){const{leading:a=!0,trailing:f=!0}=i;return n.debounce(t,s,{leading:a,maxWait:s,trailing:f})}return Ir.throttle=r,Ir}var Or,Qe;function Dn(){return Qe||(Qe=1,Or=Rn().throttle),Or}var wn=Dn();const di=A(wn);var _r={},Sr={},vr={},Ye;function xn(){if(Ye)return vr;Ye=1;const n=Nt();function r(t){return n.isSymbol(t)?NaN:Number(t)}return vr.toNumber=r,vr}var Ce;function Ut(){if(Ce)return Sr;Ce=1;const n=xn();function r(t){return t?(t=n.toNumber(t),t===1/0||t===-1/0?(t<0?-1:1)*Number.MAX_VALUE:t===t?t:0):t===0?t:0}return Sr.toFinite=r,Sr}var rt;function jn(){if(rt)return _r;rt=1;const n=Ut(),r=Kt();function t(s,i,a){a&&typeof a!="number"&&r.isIterateeCall(s,i,a)&&(i=a=void 0),s=n.toFinite(s),i===void 0?(i=s,s=0):i=n.toFinite(i),a=a===void 0?s<i?1:-1:n.toFinite(a);const f=Math.max(Math.ceil((i-s)/(a||1)),0),c=new Array(f);for(let y=0;y<f;y++)c[y]=s,s+=a;return c}return _r.range=t,_r}var Pr,et;function Tn(){return et||(et=1,Pr=jn().range),Pr}var Mn=Tn();const pi=A(Mn);var Rr={},Dr={},tt;function Ln(){if(tt)return Dr;tt=1;function n(r,t){if(r.length===0)return;let s=r[0],i=t(s,0,r);for(let a=1;a<r.length;a++){const f=r[a],c=t(f,a,r);c>i&&(i=c,s=f)}return s}return Dr.maxBy=n,Dr}var nt;function En(){if(nt)return Rr;nt=1;const n=Ln(),r=R(),t=D();function s(i,a){if(i!=null)return n.maxBy(Array.from(i),t.iteratee(a??r.identity))}return Rr.maxBy=s,Rr}var wr,it;function Wn(){return it||(it=1,wr=En().maxBy),wr}var Kn=Wn();const bi=A(Kn);var xr={},jr={},st;function Nn(){if(st)return jr;st=1;function n(r,t){if(r.length===0)return;let s=r[0],i=t(s,0,r);for(let a=1;a<r.length;a++){const f=r[a],c=t(f,a,r);c<i&&(i=c,s=f)}return s}return jr.minBy=n,jr}var ut;function Un(){if(ut)return xr;ut=1;const n=Nn(),r=R(),t=D();function s(i,a){if(i!=null)return n.minBy(Array.from(i),t.iteratee(a??r.identity))}return xr.minBy=s,xr}var Tr,at;function kn(){return at||(at=1,Tr=Un().minBy),Tr}var Fn=kn();const Ai=A(Fn);var Mr={},ot;function kt(){if(ot)return Mr;ot=1;function n(r){if(typeof r!="object"||r==null)return!1;if(Object.getPrototypeOf(r)===null)return!0;if(Object.prototype.toString.call(r)!=="[object Object]"){const s=r[Symbol.toStringTag];return s==null||!Object.getOwnPropertyDescriptor(r,Symbol.toStringTag)?.writable?!1:r.toString()===`[object ${s}]`}let t=r;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(r)===t}return Mr.isPlainObject=n,Mr}var Lr,ft;function Gn(){return ft||(ft=1,Lr=kt().isPlainObject),Lr}var Zn=Gn();const Ii=A(Zn);var Er={},Wr={},ct;function Vn(){if(ct)return Wr;ct=1;function n(r){return r[r.length-1]}return Wr.last=n,Wr}var Kr={},yt;function zn(){if(yt)return Kr;yt=1;function n(r){return Array.isArray(r)?r:Array.from(r)}return Kr.toArray=n,Kr}var lt;function Hn(){if(lt)return Er;lt=1;const n=Vn(),r=zn(),t=B();function s(i){if(t.isArrayLike(i))return n.last(r.toArray(i))}return Er.last=s,Er}var Nr,gt;function Xn(){return gt||(gt=1,Nr=Hn().last),Nr}var Jn=Xn();const $i=A(Jn);var Ur={},kr={},qt;function Qn(){if(qt)return kr;qt=1;const n=B();function r(t,s=1){const i=[],a=Math.floor(s);if(!n.isArrayLike(t))return i;const f=(c,y)=>{for(let u=0;u<c.length;u++){const e=c[u];y<a&&(Array.isArray(e)||e?.[Symbol.isConcatSpreadable]||e!==null&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Arguments]")?Array.isArray(e)?f(e,y+1):f(Array.from(e),y+1):i.push(e)}};return f(Array.from(t),0),i}return kr.flatten=r,kr}var Fr={},ht;function Yn(){if(ht)return Fr;ht=1;const n=vt(),r=_(),t=S(),s=v(),i=P();function a(c,y){if(c==null)return!0;switch(typeof y){case"symbol":case"number":case"object":if(Array.isArray(y))return f(c,y);if(typeof y=="number"?y=t.toKey(y):typeof y=="object"&&(Object.is(y?.valueOf(),-0)?y="-0":y=String(y)),n.isUnsafeProperty(y))return!1;if(c?.[y]===void 0)return!0;try{return delete c[y],!0}catch{return!1}case"string":if(c?.[y]===void 0&&r.isDeepKey(y))return f(c,s.toPath(y));if(n.isUnsafeProperty(y))return!1;try{return delete c[y],!0}catch{return!1}}}function f(c,y){const u=y.length===1?c:i.get(c,y.slice(0,-1)),e=y[y.length-1];if(u?.[e]===void 0)return!0;if(n.isUnsafeProperty(e))return!1;try{return delete u[e],!0}catch{return!1}}return Fr.unset=a,Fr}var Gr={},Zr={},mt;function Cn(){if(mt)return Zr;mt=1;function n(r){const t=r?.constructor;return r===(typeof t=="function"?t.prototype:Object.prototype)}return Zr.isPrototype=n,Zr}var Vr={},dt;function ri(){if(dt)return Vr;dt=1;const n=Rt();function r(t){return n.isTypedArray(t)}return Vr.isTypedArray=r,Vr}var zr={},Hr={},pt;function ei(){if(pt)return Hr;pt=1;const n=Ut();function r(t){const s=n.toFinite(t),i=s%1;return i?s-i:s}return Hr.toInteger=r,Hr}var bt;function ti(){if(bt)return zr;bt=1;const n=ei();function r(t,s){if(t=n.toInteger(t),t<1||!Number.isSafeInteger(t))return[];const i=new Array(t);for(let a=0;a<t;a++)i[a]=typeof s=="function"?s(a):a;return i}return zr.times=r,zr}var At;function ni(){if(At)return Gr;At=1;const n=xt(),r=B(),t=Cn(),s=ri(),i=ti();function a(u){if(u==null)return[];switch(typeof u){case"object":case"function":return r.isArrayLike(u)?y(u):t.isPrototype(u)?c(u):f(u);default:return f(Object(u))}}function f(u){const e=[];for(const o in u)e.push(o);return e}function c(u){return f(u).filter(e=>e!=="constructor")}function y(u){const e=i.times(u.length,g=>`${g}`),o=new Set(e);n.isBuffer(u)&&(o.add("offset"),o.add("parent")),s.isTypedArray(u)&&(o.add("buffer"),o.add("byteLength"),o.add("byteOffset"));const l=f(u).filter(g=>!o.has(g));return Array.isArray(u)?[...e,...l]:[...e.filter(g=>Object.hasOwn(u,g)),...l]}return Gr.keysIn=a,Gr}var Xr={},It;function ii(){if(It)return Xr;It=1;const n=Dt();function r(t){const s=[];for(;t;)s.push(...n.getSymbols(t)),t=Object.getPrototypeOf(t);return s}return Xr.getSymbolsIn=r,Xr}var $t;function si(){if($t)return Ur;$t=1;const n=kt(),r=_(),t=Et(),s=Qn(),i=Yn(),a=ni(),f=ii();function c(o,...l){if(o==null)return{};l=s.flatten(l);const g=y(o,l);for(let h=0;h<l.length;h++){let m=l[h];switch(typeof m){case"object":Array.isArray(m)||(m=Array.from(m));for(let q=0;q<m.length;q++){const d=m[q];i.unset(g,d)}break;case"string":case"symbol":case"number":i.unset(g,m);break}}return g}function y(o,l){return l.some(g=>Array.isArray(g)||r.isDeepKey(g))?e(o):u(o)}function u(o){const l={},g=[...a.keysIn(o),...f.getSymbolsIn(o)];for(let h=0;h<g.length;h++){const m=g[h];l[m]=o[m]}return l}function e(o){const l={},g=[...a.keysIn(o),...f.getSymbolsIn(o)];for(let h=0;h<g.length;h++){const m=g[h];l[m]=t.cloneDeepWith(o[m],q=>{if(!n.isPlainObject(q))return q})}return l}return Ur.omit=c,Ur}var Jr,Bt;function ui(){return Bt||(Bt=1,Jr=si().omit),Jr}var ai=ui();const Bi=A(ai);var Qr={},Ot;function oi(){if(Ot)return Qr;Ot=1;const n=D();function r(t,s){if(!t||!t.length)return 0;s!=null&&(s=n.iteratee(s));let i;for(let a=0;a<t.length;a++){const f=s?s(t[a]):t[a];f!==void 0&&(i===void 0?i=f:i+=f)}return i}return Qr.sumBy=r,Qr}var Yr,_t;function fi(){return _t||(_t=1,Yr=oi().sumBy),Yr}var ci=fi();const Oi=A(ci);export{Ai as a,Oi as b,gi as c,Xt as d,Qt as e,li as f,qi as g,Ii as i,$i as l,bi as m,Bi as o,pi as r,mi as s,di as t,hi as u};
package/dist/index.html CHANGED
@@ -15,9 +15,8 @@
15
15
  }
16
16
  }
17
17
  </script>
18
- <script type="module" crossorigin src="/assets/index-D_zAVH7u.js"></script>
19
- <link rel="stylesheet" crossorigin href="/assets/vendor-reveal-DcQQzuI9.css">
20
- <link rel="stylesheet" crossorigin href="/assets/index-CsN5CIqI.css">
18
+ <script type="module" crossorigin src="/assets/index-BxA9vp--.js"></script>
19
+ <link rel="stylesheet" crossorigin href="/assets/index-CATki2cp.css">
21
20
  </head>
22
21
  <body>
23
22
  <div id="root"></div>
package/dist/server.cjs CHANGED
@@ -973,8 +973,8 @@ function wrapCommandBus(commandBus, tracker, pluginId, manifestId) {
973
973
  throw e;
974
974
  }
975
975
  }),
976
- setInterceptor: createSafeFunction((interceptor) => {
977
- return commandBus.setInterceptor(interceptor);
976
+ setInterceptor: createSafeFunction((_interceptor) => {
977
+ throw new Error("[Security] setInterceptor cannot be configured from PluginContext");
978
978
  }),
979
979
  unregisterHandler: createSafeFunction((commandType) => {
980
980
  return commandBus.unregisterHandler(resolveType(commandType));
@@ -2506,8 +2506,8 @@ parentPort.on('message', async function(msg) {
2506
2506
  createCommand: function(type, payload, actorId, metadata) {
2507
2507
  return rawCommandBus.createCommand(type, payload, actorId, metadata);
2508
2508
  },
2509
- setInterceptor: function(interceptor) {
2510
- return rawCommandBus.setInterceptor(interceptor);
2509
+ setInterceptor: function(_interceptor) {
2510
+ throw new Error('[Security] setInterceptor cannot be configured from Worker PluginContext');
2511
2511
  }
2512
2512
  } : undefined;
2513
2513
 
@@ -8057,7 +8057,7 @@ var PluginRuntimeComposition = class {
8057
8057
  this.workerManager = workerManager;
8058
8058
  this.id = "srv_plugin_runtime_composition";
8059
8059
  this.name = "PluginRuntimeComposition";
8060
- this.version = "2.5.0";
8060
+ this.version = "0.2.3";
8061
8061
  this._isStarted = false;
8062
8062
  }
8063
8063
  get isStarted() {
@@ -8111,7 +8111,7 @@ var PluginLifecycleManager = class {
8111
8111
  this.pluginHost = pluginHost;
8112
8112
  this.id = "srv_plugin_lifecycle_manager";
8113
8113
  this.name = "PluginLifecycleManager";
8114
- this.version = "2.5.0";
8114
+ this.version = "0.2.3";
8115
8115
  }
8116
8116
  getPluginState(pluginId) {
8117
8117
  return this.pluginHost.getPluginState(pluginId);
@@ -8158,7 +8158,7 @@ var PluginCapabilityGateway = class {
8158
8158
  this.capabilityRegistry = capabilityRegistry;
8159
8159
  this.id = "srv_plugin_capability_gateway";
8160
8160
  this.name = "PluginCapabilityGateway";
8161
- this.version = "2.5.0";
8161
+ this.version = "0.2.3";
8162
8162
  }
8163
8163
  listCapabilities() {
8164
8164
  const rawCaps = this.capabilityRegistry.listCapabilities();
@@ -8212,7 +8212,7 @@ var UnifiedExtensionRegistry = class {
8212
8212
  constructor() {
8213
8213
  this.id = "srv_unified_extension_registry";
8214
8214
  this.name = "UnifiedExtensionRegistry";
8215
- this.version = "2.5.0";
8215
+ this.version = "0.2.3";
8216
8216
  this._extensions = /* @__PURE__ */ new Map();
8217
8217
  }
8218
8218
  registerExtension(category, id, impl, meta) {
@@ -8317,7 +8317,7 @@ var PluginDistributionManager = class {
8317
8317
  this.pluginHost = pluginHost;
8318
8318
  this.id = "srv_plugin_distribution_manager";
8319
8319
  this.name = "PluginDistributionManager";
8320
- this.version = "2.5.0";
8320
+ this.version = "0.2.3";
8321
8321
  this._repositories = /* @__PURE__ */ new Map();
8322
8322
  }
8323
8323
  registerRepository(repo) {
@@ -8406,7 +8406,7 @@ function validatePluginStateTransition(currentState, nextState, pluginId) {
8406
8406
  }
8407
8407
  var ACTIVATION_TIMEOUT_MS = 5e3;
8408
8408
  var DEACTIVATION_TIMEOUT_MS = 5e3;
8409
- var OPENLEARN_VERSION = "2.5.0";
8409
+ var OPENLEARN_VERSION = "0.2.3";
8410
8410
  var PluginHost = class {
8411
8411
  constructor(serviceRegistry, esmLoader, db2, pluginsDir) {
8412
8412
  this.serviceRegistry = serviceRegistry;
@@ -16020,7 +16020,7 @@ var StartupTimeoutError = class extends PlatformBootstrapError {
16020
16020
  this.name = "StartupTimeoutError";
16021
16021
  }
16022
16022
  };
16023
- var PLATFORM_VERSION = "2.5.0";
16023
+ var PLATFORM_VERSION = "0.2.3";
16024
16024
  var BOOTSTRAP_STAGE_NAMES = Object.freeze([
16025
16025
  "Created" /* Created */,
16026
16026
  "Configuring" /* Configuring */,
@@ -18383,6 +18383,26 @@ function getActorId(req) {
18383
18383
  return "user-frontend";
18384
18384
  }
18385
18385
  }
18386
+ function requireAuth(...roles) {
18387
+ return (req, res, next) => {
18388
+ const token = getCookieToken(req);
18389
+ if (!token) return res.status(401).json({ success: false, error: "Authentication required" });
18390
+ const session = getValidSession(token);
18391
+ if (!session) return res.status(401).json({ success: false, error: "Session expired or invalid" });
18392
+ if (roles.length > 0) {
18393
+ let userRole = session.role;
18394
+ if (session.username === "admin" || session.userId === "usr_admin" || userRole === "admin") {
18395
+ userRole = "administrator";
18396
+ }
18397
+ const effectiveRoles = roles.map((r) => r === "admin" ? "administrator" : r);
18398
+ if (!effectiveRoles.includes(userRole)) {
18399
+ return res.status(403).json({ success: false, error: `Role ${session.role} not allowed. Required: ${roles.join(", ")}` });
18400
+ }
18401
+ }
18402
+ req.session = session;
18403
+ next();
18404
+ };
18405
+ }
18386
18406
  function checkIsTeacherOrAdmin(req) {
18387
18407
  const token = getCookieToken(req);
18388
18408
  if (!token) return false;
@@ -20860,7 +20880,7 @@ function registerAdminRoutes(ctx) {
20860
20880
  runGeminiAgentChat: runGeminiAgentChat2,
20861
20881
  runOpenAIAgentChat: runOpenAIAgentChat2
20862
20882
  } = ctx;
20863
- app.post("/api/admin/seed-demo", (req, res) => {
20883
+ app.post("/api/admin/seed-demo", requireAuth("administrator"), (req, res) => {
20864
20884
  try {
20865
20885
  const db2 = kernelContainer.db;
20866
20886
  const DEMO_CLASS_ID = "demo-class";
@@ -20876,7 +20896,7 @@ function registerAdminRoutes(ctx) {
20876
20896
  db2.prepare("INSERT INTO classes (id, name, description, created_at) VALUES (?, ?, ?, ?)").run(
20877
20897
  DEMO_CLASS_ID,
20878
20898
  "\u4EBA\u5DE5\u667A\u80FD\u4E0E\u521B\u610F\u7F16\u7A0B\u793A\u8303\u73ED",
20879
- "\u8FD9\u662F\u7CFB\u7EDF\u521D\u59CB\u5316\u7684\u793A\u4F8B\u8BFE\u7A0B\u73ED\u7EA7\uFF0C\u7528\u4E8E\u6559\u5B66\u4F53\u9A8C\uFFFD?",
20899
+ "\u8FD9\u662F\u7CFB\u7EDF\u521D\u59CB\u5316\u7684\u793A\u4F8B\u8BFE\u7A0B\u73ED\u7EA7\uFF0C\u7528\u4E8E\u6559\u5B66\u4F53\u9A8C?",
20880
20900
  Date.now()
20881
20901
  );
20882
20902
  }
@@ -20904,7 +20924,7 @@ function registerAdminRoutes(ctx) {
20904
20924
  lessonId = "demo-lesson";
20905
20925
  db2.prepare("INSERT INTO lessons (id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)").run(
20906
20926
  lessonId,
20907
- "\u521D\u8BC6 Python\uFF1A\u667A\u80FD\u767D\u677F\u521B\u610F\u7F16\uFFFD?",
20927
+ "\u521D\u8BC6 Python\uFF1A\u667A\u80FD\u767D\u677F\u521B\u610F\u7F16?",
20908
20928
  JSON.stringify({ elements: [] }),
20909
20929
  Date.now(),
20910
20930
  Date.now()
@@ -20926,7 +20946,7 @@ function registerAdminRoutes(ctx) {
20926
20946
  res.status(500).json({ error: e.message });
20927
20947
  }
20928
20948
  });
20929
- app.post("/api/classes/import", (req, res) => {
20949
+ app.post("/api/classes/import", requireAuth("teacher", "administrator"), (req, res) => {
20930
20950
  try {
20931
20951
  const { classes } = req.body;
20932
20952
  if (!classes || !Array.isArray(classes)) {
@@ -20976,7 +20996,7 @@ function registerAdminRoutes(ctx) {
20976
20996
  res.status(500).json({ error: e.message });
20977
20997
  }
20978
20998
  });
20979
- app.post("/api/students/import", (req, res) => {
20999
+ app.post("/api/students/import", requireAuth("teacher", "administrator"), (req, res) => {
20980
21000
  try {
20981
21001
  const { students } = req.body;
20982
21002
  if (!students || !Array.isArray(students)) {
@@ -21575,16 +21595,16 @@ function registerRosterRoutes(ctx) {
21575
21595
  res.status(550).json({ error: e.message });
21576
21596
  }
21577
21597
  });
21578
- app.get("/api/users", async (req, res) => {
21598
+ app.get("/api/users", requireAuth("administrator"), async (req, res) => {
21579
21599
  try {
21580
- const cmd = kernelContainer.commandBus.createCommand("user.list", {}, "user-demo");
21600
+ const cmd = kernelContainer.commandBus.createCommand("user.list", {}, getActorId(req));
21581
21601
  const users = await kernelContainer.commandBus.execute(cmd);
21582
21602
  res.json(users);
21583
21603
  } catch (e) {
21584
21604
  res.status(550).json({ error: e.message });
21585
21605
  }
21586
21606
  });
21587
- app.post("/api/users", async (req, res) => {
21607
+ app.post("/api/users", requireAuth("administrator"), async (req, res) => {
21588
21608
  try {
21589
21609
  const { username, password, role, name, status = "active" } = req.body;
21590
21610
  const cmd = kernelContainer.commandBus.createCommand("user.create", {
@@ -21593,14 +21613,14 @@ function registerRosterRoutes(ctx) {
21593
21613
  role,
21594
21614
  name,
21595
21615
  status
21596
- }, "user-demo");
21616
+ }, getActorId(req));
21597
21617
  const result = await kernelContainer.commandBus.execute(cmd);
21598
21618
  res.json(result);
21599
21619
  } catch (e) {
21600
21620
  res.status(550).json({ error: e.message });
21601
21621
  }
21602
21622
  });
21603
- app.put("/api/users/:id", async (req, res) => {
21623
+ app.put("/api/users/:id", requireAuth("administrator"), async (req, res) => {
21604
21624
  try {
21605
21625
  const { username, role, name, password, status } = req.body;
21606
21626
  const cmd = kernelContainer.commandBus.createCommand("user.update", {
@@ -21610,18 +21630,18 @@ function registerRosterRoutes(ctx) {
21610
21630
  name,
21611
21631
  password,
21612
21632
  status
21613
- }, "user-demo");
21633
+ }, getActorId(req));
21614
21634
  const result = await kernelContainer.commandBus.execute(cmd);
21615
21635
  res.json(result);
21616
21636
  } catch (e) {
21617
21637
  res.status(550).json({ error: e.message });
21618
21638
  }
21619
21639
  });
21620
- app.delete("/api/users/:id", async (req, res) => {
21640
+ app.delete("/api/users/:id", requireAuth("administrator"), async (req, res) => {
21621
21641
  try {
21622
21642
  const cmd = kernelContainer.commandBus.createCommand("user.delete", {
21623
21643
  userId: req.params.id
21624
- }, "user-demo");
21644
+ }, getActorId(req));
21625
21645
  const result = await kernelContainer.commandBus.execute(cmd);
21626
21646
  res.json(result);
21627
21647
  } catch (e) {
@@ -21636,7 +21656,7 @@ function registerRosterRoutes(ctx) {
21636
21656
  res.status(500).json({ error: e.message });
21637
21657
  }
21638
21658
  });
21639
- app.post("/api/labs", (req, res) => {
21659
+ app.post("/api/labs", requireAuth("teacher", "administrator"), (req, res) => {
21640
21660
  try {
21641
21661
  const { room_number, rows, cols } = req.body;
21642
21662
  const id = "lab_" + Math.random().toString(36).slice(2, 10);
@@ -21648,7 +21668,7 @@ function registerRosterRoutes(ctx) {
21648
21668
  res.status(500).json({ error: e.message });
21649
21669
  }
21650
21670
  });
21651
- app.put("/api/labs/:id", (req, res) => {
21671
+ app.put("/api/labs/:id", requireAuth("teacher", "administrator"), (req, res) => {
21652
21672
  try {
21653
21673
  const { room_number, rows, cols } = req.body;
21654
21674
  kernelContainer.db.prepare(
@@ -21659,7 +21679,7 @@ function registerRosterRoutes(ctx) {
21659
21679
  res.status(500).json({ error: e.message });
21660
21680
  }
21661
21681
  });
21662
- app.delete("/api/labs/:id", (req, res) => {
21682
+ app.delete("/api/labs/:id", requireAuth("teacher", "administrator"), (req, res) => {
21663
21683
  try {
21664
21684
  kernelContainer.db.prepare("DELETE FROM computer_labs WHERE id = ?").run(req.params.id);
21665
21685
  kernelContainer.db.prepare("DELETE FROM student_seats WHERE lab_id = ?").run(req.params.id);
@@ -21678,7 +21698,7 @@ function registerRosterRoutes(ctx) {
21678
21698
  res.status(500).json({ error: e.message });
21679
21699
  }
21680
21700
  });
21681
- app.post("/api/classes/:classId/seats", (req, res) => {
21701
+ app.post("/api/classes/:classId/seats", requireAuth("teacher", "administrator"), (req, res) => {
21682
21702
  try {
21683
21703
  const { lab_id, seats } = req.body;
21684
21704
  kernelContainer.db.prepare("UPDATE classes SET lab_id = ? WHERE id = ?").run(lab_id || null, req.params.classId);
@@ -21876,7 +21896,7 @@ function registerRosterRoutes(ctx) {
21876
21896
  res.status(500).json({ error: e.message });
21877
21897
  }
21878
21898
  });
21879
- app.post("/api/classes/:id/students/bulk-enroll", (req, res) => {
21899
+ app.post("/api/classes/:id/students/bulk-enroll", requireAuth("teacher", "administrator"), (req, res) => {
21880
21900
  try {
21881
21901
  const { students } = req.body;
21882
21902
  const classId = req.params.id;
@@ -23421,6 +23441,28 @@ async function checkVersion(source, installedVersion) {
23421
23441
  }
23422
23442
 
23423
23443
  // server/routes/plugins.ts
23444
+ function isSafeExternalUrl(urlStr) {
23445
+ try {
23446
+ const parsed = new URL(urlStr);
23447
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
23448
+ return { safe: false, reason: "Only HTTP and HTTPS protocols are allowed" };
23449
+ }
23450
+ const hostname = parsed.hostname.toLowerCase();
23451
+ if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local") || hostname === "0.0.0.0" || hostname === "::1" || hostname === "[::1]") {
23452
+ return { safe: false, reason: "Access to loopback/local addresses is forbidden" };
23453
+ }
23454
+ const ipv4Match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
23455
+ if (ipv4Match) {
23456
+ const octets = ipv4Match.slice(1).map(Number);
23457
+ if (octets[0] === 127 || octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168 || octets[0] === 169 && octets[1] === 254 || octets[0] === 0 || octets[0] >= 224) {
23458
+ return { safe: false, reason: "Access to private or link-local IP addresses is forbidden" };
23459
+ }
23460
+ }
23461
+ return { safe: true };
23462
+ } catch (e) {
23463
+ return { safe: false, reason: `Invalid URL format: ${e.message}` };
23464
+ }
23465
+ }
23424
23466
  function registerPluginsRoutes(ctx) {
23425
23467
  const {
23426
23468
  app,
@@ -23568,12 +23610,19 @@ function registerPluginsRoutes(ctx) {
23568
23610
  res.status(500).json({ success: false, error: e.message });
23569
23611
  }
23570
23612
  });
23571
- app.post("/api/plugins/:id(*)/one-click-update", async (req, res) => {
23613
+ app.post("/api/plugins/:id(*)/one-click-update", requireAuth("administrator"), async (req, res) => {
23572
23614
  try {
23573
23615
  const targetPluginId = decodeURIComponent(req.params.id);
23574
23616
  const { downloadUrl } = req.body || {};
23575
23617
  let zipBuffer;
23576
23618
  if (downloadUrl) {
23619
+ const urlCheck = isSafeExternalUrl(downloadUrl);
23620
+ if (!urlCheck.safe) {
23621
+ return res.status(400).json({
23622
+ success: false,
23623
+ error: `\u5B89\u5168\u62E6\u622A: \u975E\u6CD5\u4E0B\u8F7D\u5730\u5740 (${urlCheck.reason})`
23624
+ });
23625
+ }
23577
23626
  try {
23578
23627
  const resp = await fetch(downloadUrl, {
23579
23628
  headers: { "User-Agent": "OpenLearnV2-PluginUpdater/1.0" },
@@ -23651,7 +23700,7 @@ function registerPluginsRoutes(ctx) {
23651
23700
  res.status(500).json({ success: false, error: e.message });
23652
23701
  }
23653
23702
  });
23654
- app.post("/api/plugins/:id(*)/config", (req, res) => {
23703
+ app.post("/api/plugins/:id(*)/config", requireAuth("administrator"), (req, res) => {
23655
23704
  try {
23656
23705
  const rawId = decodeURIComponent(req.params.id);
23657
23706
  const pluginId = kernelContainer.pluginHost.resolvePluginUuid(rawId);
@@ -23670,7 +23719,7 @@ function registerPluginsRoutes(ctx) {
23670
23719
  res.status(500).json({ success: false, error: e.message });
23671
23720
  }
23672
23721
  });
23673
- app.post("/api/plugins/:id(*)/toggle", async (req, res) => {
23722
+ app.post("/api/plugins/:id(*)/toggle", requireAuth("administrator"), async (req, res) => {
23674
23723
  try {
23675
23724
  const rawId = decodeURIComponent(req.params.id);
23676
23725
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23684,7 +23733,7 @@ function registerPluginsRoutes(ctx) {
23684
23733
  res.status(500).json({ success: false, error: err.message });
23685
23734
  }
23686
23735
  });
23687
- app.delete("/api/plugins/:id(*)", async (req, res) => {
23736
+ app.delete("/api/plugins/:id(*)", requireAuth("administrator"), async (req, res) => {
23688
23737
  try {
23689
23738
  const rawId = decodeURIComponent(req.params.id);
23690
23739
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23712,7 +23761,7 @@ function registerPluginsRoutes(ctx) {
23712
23761
  res.status(404).json({ success: false, error: err.message });
23713
23762
  }
23714
23763
  });
23715
- app.post("/api/plugins", async (req, res) => {
23764
+ app.post("/api/plugins", requireAuth("administrator"), async (req, res) => {
23716
23765
  try {
23717
23766
  const { sourceCode } = req.body;
23718
23767
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23727,7 +23776,7 @@ function registerPluginsRoutes(ctx) {
23727
23776
  res.status(500).json({ success: false, error: err.message });
23728
23777
  }
23729
23778
  });
23730
- app.post("/api/plugins/upload-zip", async (req, res) => {
23779
+ app.post("/api/plugins/upload-zip", requireAuth("administrator"), async (req, res) => {
23731
23780
  try {
23732
23781
  const { base64Data, filename, executionMode } = req.body;
23733
23782
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23742,7 +23791,7 @@ function registerPluginsRoutes(ctx) {
23742
23791
  res.status(500).json({ success: false, error: err.message });
23743
23792
  }
23744
23793
  });
23745
- app.post("/api/plugins/upload-zip-raw", import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }), async (req, res) => {
23794
+ app.post("/api/plugins/upload-zip-raw", requireAuth("administrator"), import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }), async (req, res) => {
23746
23795
  try {
23747
23796
  const zipBuffer = req.body;
23748
23797
  const filename = req.headers["x-filename"] ? decodeURIComponent(req.headers["x-filename"]) : "plugin.zip";
@@ -23786,6 +23835,7 @@ function registerPluginsRoutes(ctx) {
23786
23835
  });
23787
23836
  app.post(
23788
23837
  "/api/plugins/:id(*)/update-zip-raw",
23838
+ requireAuth("administrator"),
23789
23839
  import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }),
23790
23840
  async (req, res) => {
23791
23841
  try {
@@ -23872,7 +23922,7 @@ function registerPluginsRoutes(ctx) {
23872
23922
  res.status(500).json({ error: e.message });
23873
23923
  }
23874
23924
  });
23875
- app.post("/api/ai-providers", (req, res) => {
23925
+ app.post("/api/ai-providers", requireAuth("administrator"), (req, res) => {
23876
23926
  try {
23877
23927
  const { name, api_url, api_key, model_name } = req.body;
23878
23928
  if (!name || !api_url || !model_name) {
@@ -23887,7 +23937,7 @@ function registerPluginsRoutes(ctx) {
23887
23937
  res.status(500).json({ error: e.message });
23888
23938
  }
23889
23939
  });
23890
- app.put("/api/ai-providers/:id", (req, res) => {
23940
+ app.put("/api/ai-providers/:id", requireAuth("administrator"), (req, res) => {
23891
23941
  try {
23892
23942
  const { name, api_url, api_key, model_name } = req.body;
23893
23943
  if (!name || !api_url || !model_name) {
@@ -23907,7 +23957,7 @@ function registerPluginsRoutes(ctx) {
23907
23957
  res.status(500).json({ error: e.message });
23908
23958
  }
23909
23959
  });
23910
- app.delete("/api/ai-providers/:id", (req, res) => {
23960
+ app.delete("/api/ai-providers/:id", requireAuth("administrator"), (req, res) => {
23911
23961
  try {
23912
23962
  kernelContainer.db.prepare("DELETE FROM ai_providers WHERE id = ?").run(req.params.id);
23913
23963
  res.json({ success: true });
@@ -23927,7 +23977,7 @@ function registerPluginsRoutes(ctx) {
23927
23977
  res.status(500).json({ error: e.message });
23928
23978
  }
23929
23979
  });
23930
- app.put("/api/site-settings", (req, res) => {
23980
+ app.put("/api/site-settings", requireAuth("administrator"), (req, res) => {
23931
23981
  try {
23932
23982
  const { siteName, slogan, logoUrl } = req.body || {};
23933
23983
  kernelContainer.db.prepare(
@@ -23942,7 +23992,7 @@ function registerPluginsRoutes(ctx) {
23942
23992
  res.status(500).json({ error: e.message });
23943
23993
  }
23944
23994
  });
23945
- app.post("/api/ai-providers/test", async (req, res) => {
23995
+ app.post("/api/ai-providers/test", requireAuth("administrator"), async (req, res) => {
23946
23996
  try {
23947
23997
  const { api_url, api_key: providedKey, model_name } = req.body;
23948
23998
  if (!api_url || !model_name) {
@@ -24043,8 +24093,8 @@ async function startServer() {
24043
24093
  standardHeaders: true,
24044
24094
  legacyHeaders: false
24045
24095
  });
24046
- app.use(import_express3.default.json({ limit: "400mb" }));
24047
- app.use(import_express3.default.urlencoded({ limit: "400mb", extended: true }));
24096
+ app.use(import_express3.default.json({ limit: "10mb" }));
24097
+ app.use(import_express3.default.urlencoded({ limit: "10mb", extended: true }));
24048
24098
  app.use("/uploads", import_express3.default.static(import_path14.default.join(process.cwd(), "uploads")));
24049
24099
  app.use("/plugins", import_express3.default.static(import_path14.default.join(process.cwd(), "plugins")));
24050
24100
  app.use((req, res, next) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openlearn-next",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "private": false,
5
5
  "description": "A plugin-driven Educational OS / LMS platform with AI agent teaching assistant",
6
6
  "keywords": [
@@ -1 +0,0 @@
1
- import{r as m}from"./vendor-konva-GivUq6dt.js";import{j as e,G as h,M as w,a as v,X as y}from"./whiteboard-jgQrAUm7.js";const j=(function(){const l=typeof document<"u"&&document.createElement("link").relList;return l&&l.supports&&l.supports("modulepreload")?"modulepreload":"preload"})(),E=function(n){return"/"+n},g={},N=function(l,c,f){let i=Promise.resolve();if(c&&c.length>0){let t=function(r){return Promise.all(r.map(a=>Promise.resolve(a).then(u=>({status:"fulfilled",value:u}),u=>({status:"rejected",reason:u}))))};document.getElementsByTagName("link");const s=document.querySelector("meta[property=csp-nonce]"),x=s?.nonce||s?.getAttribute("nonce");i=t(c.map(r=>{if(r=E(r),r in g)return;g[r]=!0;const a=r.endsWith(".css"),u=a?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${r}"]${u}`))return;const o=document.createElement("link");if(o.rel=a?"stylesheet":j,a||(o.as="script"),o.crossOrigin="",o.href=r,x&&o.setAttribute("nonce",x),document.head.appendChild(o),a)return new Promise((p,b)=>{o.addEventListener("load",p),o.addEventListener("error",()=>b(new Error(`Unable to preload CSS for ${r}`)))})}))}function d(t){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=t,window.dispatchEvent(s),!s.defaultPrevented)throw t}return i.then(t=>{for(const s of t||[])s.status==="rejected"&&d(s.reason);return l().catch(d)})},_=m.lazy(()=>N(()=>Promise.resolve().then(()=>F),void 0).then(n=>({default:n.InteractiveCoursewareViewer}))),P=Object.freeze(Object.defineProperty({__proto__:null,CoursewareViewer:_},Symbol.toStringTag,{value:"Module"}));function S({coursewareId:n,onClose:l}){const[c,f]=m.useState(!1),i=m.useRef(null);m.useEffect(()=>{const t=()=>{f(!!document.fullscreenElement&&document.fullscreenElement===i.current)};return document.addEventListener("fullscreenchange",t),()=>{document.removeEventListener("fullscreenchange",t)}},[]);const d=()=>{const t=i.current;t&&(document.fullscreenElement?document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen&&document.webkitExitFullscreen():t.requestFullscreen?t.requestFullscreen():t.webkitRequestFullscreen&&t.webkitRequestFullscreen())};return n?e.jsxs("div",{ref:i,className:"flex flex-col h-full bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden relative",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 bg-gray-100 border-b border-gray-200 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 select-none",children:[e.jsx(h,{size:16,className:"text-indigo-500"}),e.jsx("span",{className:"font-semibold text-sm text-gray-700",children:"Interactive Courseware"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:d,className:"p-1 hover:bg-gray-200 rounded-lg text-gray-500 transition-colors cursor-pointer",title:c?"退出全屏":"全屏播放",children:c?e.jsx(w,{size:16}):e.jsx(v,{size:16})}),l&&e.jsx("button",{onClick:l,className:"p-1 hover:bg-gray-200 rounded-lg text-gray-500 transition-colors cursor-pointer",children:e.jsx(y,{size:16})})]})]}),e.jsx("div",{className:"flex-1 relative bg-white",children:e.jsx("iframe",{src:`/api/courseware/${n}`,sandbox:"allow-scripts allow-same-origin allow-downloads allow-forms",allowFullScreen:!0,className:"w-full h-full border-none",title:"Interactive Courseware"})})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-gray-400 bg-gray-50 rounded-xl border border-dashed border-gray-300",children:[e.jsx(h,{size:48,className:"mb-4 text-gray-300 opacity-50"}),e.jsx("h3",{className:"text-lg font-medium text-gray-700",children:"No Courseware Selected"}),e.jsx("p",{className:"mt-2 text-sm text-center",children:"Please select a courseware from the list to view it interactively."})]})}const F=Object.freeze(Object.defineProperty({__proto__:null,InteractiveCoursewareViewer:S},Symbol.toStringTag,{value:"Module"}));export{N as _,P as i};