/trunk/doc/developer_notes/class_diagram.drawio |
---|
1,6 → 1,6 |
<mxfile host="app.diagrams.net" modified="2023-05-31T21:45:09.782Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" etag="5xBcap5hzl0EHfQwSl1m" version="21.2.3" type="device"> |
<mxfile host="app.diagrams.net" modified="2023-04-13T00:20:45.176Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36" etag="9d4FhrGIPdhHJ0zPX6wc" version="21.1.5" type="device"> |
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1"> |
<mxGraphModel dx="4921" dy="1255" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> |
<mxGraphModel dx="4871" dy="1273" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> |
<root> |
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" /> |
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" /> |
27,13 → 27,13 |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-4" value="<div>OIDplusConfig</div>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="384" y="235" width="120" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-5" target="xnW6IEu4I55F3u-ZmjsQ-0" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-5" target="xnW6IEu4I55F3u-ZmjsQ-0"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-5" value="<div>OIDplusConfigInitializationException</div>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="887" y="1000" width="240" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-6" target="HaJfKRJEYKdRmyHm2M7B-27" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-6" target="HaJfKRJEYKdRmyHm2M7B-27"> |
<mxGeometry relative="1" as="geometry"> |
<Array as="points"> |
<mxPoint x="840" y="820" /> |
114,6 → 114,9 |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-15" value="<div>OIDplusRA</div>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1060" y="505" width="120" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-16" value="<div>OIDplusSessionHandler</div>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1340" y="235" width="140" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-17" value="<div>OIDplusMenuUtils</div>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="516" y="235" width="120" height="40" as="geometry" /> |
</mxCell> |
132,7 → 135,7 |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-23" value="(Plugins found in plugin folder)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="424" y="845" width="140" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-27" target="qhEKmyDmoYopIHslgWnM-0" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-27" target="qhEKmyDmoYopIHslgWnM-0"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="HaJfKRJEYKdRmyHm2M7B-27" value="OIDplusException" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
215,7 → 218,7 |
<mxPoint x="-170" y="790" as="targetPoint" /> |
</mxGeometry> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qhEKmyDmoYopIHslgWnM-6" target="HaJfKRJEYKdRmyHm2M7B-27" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qhEKmyDmoYopIHslgWnM-6" target="HaJfKRJEYKdRmyHm2M7B-27"> |
<mxGeometry relative="1" as="geometry"> |
<Array as="points"> |
<mxPoint x="1200" y="820" /> |
493,14 → 496,20 |
</mxGeometry> |
</mxCell> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-0" value="OIDplusAuthContentStore" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontStyle=2" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1560" y="441" width="200" height="40" as="geometry" /> |
<mxGeometry x="1574" y="441" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="Byxuzqwyhnfv62GrUFNm-1" target="Byxuzqwyhnfv62GrUFNm-0" edge="1"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-1" value="OIDplusAuthContentStoreJWT" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1670" y="545" width="200" height="40" as="geometry" /> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-1" value="OIDplusAuthContentStoreDummy" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1700" y="546" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="Byxuzqwyhnfv62GrUFNm-2" target="Byxuzqwyhnfv62GrUFNm-1" edge="1"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-2" value="OIDplusAuthContentStoreJWT" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1700" y="631" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="Byxuzqwyhnfv62GrUFNm-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="Byxuzqwyhnfv62GrUFNm-3" target="Byxuzqwyhnfv62GrUFNm-0" edge="1"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
514,16 → 523,29 |
<mxPoint as="offset" /> |
</mxGeometry> |
</mxCell> |
<mxCell id="L80APtfHvu4QAkl1HBHO-0" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.75;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;edgeStyle=orthogonalEdgeStyle;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-16" target="ZfX25L6vCK6xiF5fLbg_-2" edge="1"> |
<mxGeometry relative="1" as="geometry"> |
<mxPoint x="450" y="180" as="sourcePoint" /> |
<mxPoint x="300.49999999999955" y="190" as="targetPoint" /> |
</mxGeometry> |
</mxCell> |
<mxCell id="L80APtfHvu4QAkl1HBHO-1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.894;entryY=0.988;entryDx=0;entryDy=0;endArrow=block;endFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;jumpStyle=none;edgeStyle=orthogonalEdgeStyle;entryPerimeter=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="Byxuzqwyhnfv62GrUFNm-0" target="ZfX25L6vCK6xiF5fLbg_-2" edge="1"> |
<mxGeometry relative="1" as="geometry"> |
<mxPoint x="840" y="141" as="sourcePoint" /> |
<mxPoint x="303.424" y="141.27999999999997" as="targetPoint" /> |
<Array as="points"> |
<mxPoint x="1660" y="160" /> |
<mxPoint x="1674" y="160" /> |
<mxPoint x="528" y="160" /> |
</Array> |
</mxGeometry> |
</mxCell> |
<mxCell id="L80APtfHvu4QAkl1HBHO-2" value="&lt;&lt;uses&gt;&gt;" style="endArrow=open;dashed=1;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;endFill=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="Byxuzqwyhnfv62GrUFNm-3" target="HaJfKRJEYKdRmyHm2M7B-16" edge="1"> |
<mxGeometry x="0.6679" width="50" height="50" relative="1" as="geometry"> |
<mxPoint x="1160" y="285" as="sourcePoint" /> |
<mxPoint x="1400" y="510" as="targetPoint" /> |
<mxPoint as="offset" /> |
</mxGeometry> |
</mxCell> |
<mxCell id="FpbcvbkZNCeurcATEcsh-0" value="<div>OIDplusCaptchaPlugin</div>" style="rounded=0;whiteSpace=wrap;html=1;fontStyle=2;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="-500" y="580" width="146" height="40" as="geometry" /> |
</mxCell> |
540,38 → 562,38 |
<mxPoint as="offset" /> |
</mxGeometry> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-0" target="HaJfKRJEYKdRmyHm2M7B-27" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-0" target="HaJfKRJEYKdRmyHm2M7B-27"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-0" value="OIDplusHtmlException" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-0" value="OIDplusHtmlException" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> |
<mxGeometry x="887" y="885" width="240" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-7" value="OIDplusLogTarget" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1560" y="900" width="200" height="40" as="geometry" /> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-7" value="OIDplusLogTarget" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> |
<mxGeometry x="1590" y="900" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-8" value="OIDplusLogEvent" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1560" y="805" width="200" height="40" as="geometry" /> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-8" value="OIDplusLogEvent" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> |
<mxGeometry x="1590" y="805" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-9" target="xnW6IEu4I55F3u-ZmjsQ-7" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-9" target="xnW6IEu4I55F3u-ZmjsQ-7"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-9" value="OIDplusLogTargetUser" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1440" y="1000" width="200" height="40" as="geometry" /> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-9" value="OIDplusLogTargetUser" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> |
<mxGeometry x="1470" y="1000" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-10" target="xnW6IEu4I55F3u-ZmjsQ-7" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-10" target="xnW6IEu4I55F3u-ZmjsQ-7"> |
<mxGeometry relative="1" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-10" value="OIDplusLogTargetObject" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> |
<mxGeometry x="1670" y="1000" width="200" height="40" as="geometry" /> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-10" value="OIDplusLogTargetObject" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> |
<mxGeometry x="1700" y="1000" width="200" height="40" as="geometry" /> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-13" value="&lt;&lt;contains list of&gt;&gt;" style="endArrow=open;dashed=1;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-8" target="xnW6IEu4I55F3u-ZmjsQ-7" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-13" value="&lt;&lt;contains list of&gt;&gt;" style="endArrow=open;dashed=1;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;endFill=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="xnW6IEu4I55F3u-ZmjsQ-8" target="xnW6IEu4I55F3u-ZmjsQ-7"> |
<mxGeometry x="0.1461" y="3" width="50" height="50" relative="1" as="geometry"> |
<mxPoint x="1040" y="235" as="sourcePoint" /> |
<mxPoint x="1384" y="421" as="targetPoint" /> |
<mxPoint x="1070" y="235" as="sourcePoint" /> |
<mxPoint x="1414" y="421" as="targetPoint" /> |
<mxPoint as="offset" /> |
</mxGeometry> |
</mxCell> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-15" value="&lt;&lt;uses&gt;&gt;" style="endArrow=open;dashed=1;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-9" target="xnW6IEu4I55F3u-ZmjsQ-8" edge="1"> |
<mxCell id="xnW6IEu4I55F3u-ZmjsQ-15" value="&lt;&lt;uses&gt;&gt;" style="endArrow=open;dashed=1;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;endFill=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="HaJfKRJEYKdRmyHm2M7B-9" target="xnW6IEu4I55F3u-ZmjsQ-8"> |
<mxGeometry x="0.755" y="-3" width="50" height="50" relative="1" as="geometry"> |
<mxPoint x="1700" y="855" as="sourcePoint" /> |
<mxPoint x="1700" y="910" as="targetPoint" /> |
/trunk/doc/developer_notes/class_diagram.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/includes/classes/OIDplusAuthContentStore.class.php |
---|
183,7 → 183,7 |
* @return bool |
*/ |
public function isAdminLoggedIn(): bool { |
return $this->getValue('oidplus_admin_logged_in', 0) == 1; |
return $this->getValue('oidplus_admin_logged_in') == 1; |
} |
} |
/trunk/includes/classes/OIDplusAuthContentStoreDummy.class.php |
---|
0,0 → 1,70 |
<?php |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
namespace ViaThinkSoft\OIDplus; |
// phpcs:disable PSR1.Files.SideEffects |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
# TODO: Rename class? |
abstract class OIDplusAuthContentStoreDummy extends OIDplusAuthContentStore { |
/** |
* @var array |
*/ |
protected $content = array(); |
// Override some abstract functions |
/** |
* @param string $name |
* @param mixed|null $default |
* @return mixed|null |
*/ |
public function getValue(string $name, $default = NULL) { |
return $this->content[$name] ?? $default; |
} |
/** |
* @param string $name |
* @param mixed $value |
* @return void |
*/ |
public function setValue(string $name, $value) { |
$this->content[$name] = $value; |
} |
/** |
* @param string $name |
* @return bool |
*/ |
public function exists(string $name): bool { |
return isset($this->content[$name]); |
} |
/** |
* @param string $name |
* @return void |
*/ |
public function delete(string $name) { |
unset($this->content[$name]); |
} |
} |
/trunk/includes/classes/OIDplusAuthContentStoreJWT.class.php |
---|
23,7 → 23,7 |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
class OIDplusAuthContentStoreJWT extends OIDplusAuthContentStore { |
class OIDplusAuthContentStoreJWT extends OIDplusAuthContentStoreDummy { |
/** |
* Cookie name for the JWT auth token |
215,47 → 215,8 |
// Override abstract functions |
/** |
* @var array |
*/ |
protected $content = array(); |
/** |
* @param string $name |
* @param mixed|null $default |
* @return mixed|null |
*/ |
public function getValue(string $name, $default = NULL) { |
return $this->content[$name] ?? $default; |
} |
/** |
* @param string $name |
* @param mixed $value |
* @return void |
*/ |
public function setValue(string $name, $value) { |
$this->content[$name] = $value; |
} |
/** |
* @param string $name |
* @return bool |
*/ |
public function exists(string $name): bool { |
return isset($this->content[$name]); |
} |
/** |
* @param string $name |
* @return void |
*/ |
public function delete(string $name) { |
unset($this->content[$name]); |
} |
/** |
* @return void |
*/ |
public function activate() { |
// Send cookie at the end of the HTTP request, in case there are multiple activate() calls |
OIDplus::register_shutdown_function(array($this,'activateNow')); |
/trunk/includes/classes/OIDplusAuthContentStoreSession.class.php |
---|
25,7 → 25,19 |
class OIDplusAuthContentStoreSession extends OIDplusAuthContentStore { |
/** |
* @return OIDplusSessionHandler |
*/ |
protected static function getSessionHandler(): OIDplusSessionHandler { |
static $sesHandler = null; |
if (is_null($sesHandler)) { |
$sesHandler = new OIDplusSessionHandler(); |
} |
return $sesHandler; |
} |
// Override abstract functions |
# TODO: shouldn't we just include OIDplusSessionHandler in this class? |
/** |
* @param string $name |
35,16 → 47,9 |
*/ |
public function getValue(string $name, $default = NULL) { |
try { |
if (isset($this->cacheSetValues[$name])) return self::decrypt($this->cacheSetValues[$name], $this->secret); |
if (!$this->isActive()) return $default; // GDPR: Only start a session when we really need one |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
if (!isset($_SESSION[$name])) return $default; |
return self::decrypt($_SESSION[$name], $this->secret); |
return self::getSessionHandler()->getValue($name, $default); |
} catch (\Exception $e) { |
$this->destroySession(); |
self::getSessionHandler()->destroySession(); |
// TODO: For some reason If destroySession() is called, we won't get this Exception?! |
throw new OIDplusException(_L('Internal error with session. Please reload the page and log-in again. %1', $e->getMessage())); |
} |
57,14 → 62,7 |
* @throws OIDplusException |
*/ |
public function setValue(string $name, $value) { |
$enc_data = self::encrypt($value, $this->secret); |
$this->cacheSetValues[$name] = $enc_data; |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
$_SESSION[$name] = $enc_data; |
self::getSessionHandler()->setValue($name, $value); |
} |
/** |
73,13 → 71,7 |
* @throws OIDplusException |
*/ |
public function exists(string $name): bool { |
if (isset($this->cacheSetValues[$name])) return true; |
if (!$this->isActive()) return false; // GDPR: Only start a session when we really need one |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
return isset($_SESSION[$name]); |
return self::getSessionHandler()->exists($name); |
} |
/** |
88,13 → 80,7 |
* @throws OIDplusException |
*/ |
public function delete(string $name) { |
if (isset($this->cacheSetValues[$name])) unset($this->cacheSetValues[$name]); |
if (!$this->isActive()) return; // GDPR: Only start a session when we really need one |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
unset($_SESSION[$name]); |
self::getSessionHandler()->delete($name); |
} |
/** |
102,20 → 88,11 |
* @throws OIDplusException |
*/ |
public function destroySession() { |
if (!$this->isActive()) return; |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
$_SESSION = array(); |
session_destroy(); |
session_write_close(); |
OIDplus::cookieUtils()->unsetcookie(session_name()); // remove cookie, so GDPR people are happy |
self::getSessionHandler()->destroySession(); |
} |
/** |
* @return OIDplusAuthContentStoreSession|null |
* @throws OIDplusException |
*/ |
public static function getActiveProvider()/*: ?OIDplusAuthContentStore*/ { |
static $contentProvider = null; |
127,7 → 104,7 |
} |
if (!$contentProvider) { |
if (self::isActive()) { |
if (self::getSessionHandler()->isActive()) { |
$contentProvider = new OIDplusAuthContentStoreSession(); |
} |
} |
139,7 → 116,6 |
* @param string $email |
* @param string $loginfo |
* @return void |
* @throws OIDplusException |
*/ |
public function raLoginEx(string $email, string &$loginfo) { |
$this->raLogin($email); |
153,7 → 129,6 |
/** |
* @param string $loginfo |
* @return void |
* @throws OIDplusException |
*/ |
public function adminLoginEx(string &$loginfo) { |
$this->adminLogin(); |
190,162 → 165,4 |
# Sessions automatically activate during setValue() |
} |
# ------------------------------------------------------------------------------------------------------------------ |
/** |
* @var string|null |
*/ |
private $secret = ''; |
/** |
* @var int|null |
*/ |
protected $sessionLifetime = 0; |
/** |
* @throws OIDplusException |
*/ |
public function __construct() { |
$this->sessionLifetime = OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60); |
$this->secret = OIDplus::authUtils()->makeSecret(['b118abc8-f4ec-11ed-86ca-3c4a92df8582']); |
// **PREVENTING SESSION HIJACKING** |
// Prevents javascript XSS attacks aimed to steal the session ID |
@ini_set('session.cookie_httponly', '1'); |
// **PREVENTING SESSION FIXATION** |
// Session ID cannot be passed through URLs |
@ini_set('session.use_only_cookies', '1'); |
@ini_set('session.use_trans_sid', '0'); |
// Uses a secure connection (HTTPS) if possible |
@ini_set('session.cookie_secure', OIDplus::isSslAvailable() ? '1' : '0'); |
$path = OIDplus::webpath(null,OIDplus::PATH_RELATIVE); |
if (empty($path)) $path = '/'; |
@ini_set('session.cookie_path', $path); |
@ini_set('session.cookie_samesite', OIDplus::baseConfig()->getValue('COOKIE_SAMESITE_POLICY', 'Strict')); |
@ini_set('session.use_strict_mode', '1'); |
@ini_set('session.gc_maxlifetime', $this->sessionLifetime); |
} |
/** |
* @return void |
* @throws OIDplusException |
*/ |
protected function sessionSafeStart() { |
if (!isset($_SESSION)) { |
// TODO: session_name() makes some problems. Leave it away for now. |
//session_name('OIDplus_SESHDLR'); |
if (!session_start()) { |
throw new OIDplusException(_L('Session could not be started')); |
} |
} |
if (!isset($_SESSION['ip'])) { |
if (!isset($_SERVER['REMOTE_ADDR'])) return; |
// Remember the IP address of the user |
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR']; |
} else { |
if ($_SERVER['REMOTE_ADDR'] != $_SESSION['ip']) { |
// Was the session hijacked?! Get out of here! |
// We don't use $this->destroySession(), because this calls sessionSafeStart() again |
$_SESSION = array(); |
session_destroy(); |
session_write_close(); |
OIDplus::cookieUtils()->unsetcookie(session_name()); // remove cookie, so GDPR people are happy |
} |
} |
} |
/** |
* @return void |
*/ |
function __destruct() { |
session_write_close(); |
} |
private $cacheSetValues = array(); // Important if you do a setValue() followed by an getValue() |
/** |
* @return bool |
*/ |
public static function isActive(): bool { |
return isset($_COOKIE[session_name()]); |
} |
/** |
* @param string $data |
* @param string $key |
* @return string |
* @throws \Exception |
*/ |
protected static function encrypt(string $data, string $key): string { |
if (function_exists('openssl_encrypt')) { |
$iv = random_bytes(16); // AES block size in CBC mode |
// Encryption |
$ciphertext = openssl_encrypt( |
$data, |
'AES-256-CBC', |
hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, true), |
OPENSSL_RAW_DATA, |
$iv |
); |
// Authentication |
$hmac = sha3_512_hmac($iv . $ciphertext, $key, true); |
return $hmac . $iv . $ciphertext; |
} else { |
// When OpenSSL is not available, then we just do a HMAC |
$hmac = sha3_512_hmac($data, $key, true); |
return $hmac . $data; |
} |
} |
/** |
* @param string $data |
* @param string $key |
* @return string |
* @throws OIDplusException |
*/ |
protected static function decrypt(string $data, string $key): string { |
if (function_exists('openssl_decrypt')) { |
$hmac = mb_substr($data, 0, 64, '8bit'); |
$iv = mb_substr($data, 64, 16, '8bit'); |
$ciphertext = mb_substr($data, 80, null, '8bit'); |
// Authentication |
$hmacNew = sha3_512_hmac($iv . $ciphertext, $key, true); |
if (!hash_equals($hmac, $hmacNew)) { |
throw new OIDplusException(_L('Authentication failed')); |
} |
// Decryption |
$cleartext = openssl_decrypt( |
$ciphertext, |
'AES-256-CBC', |
hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, true), |
OPENSSL_RAW_DATA, |
$iv |
); |
if ($cleartext === false) { |
throw new OIDplusException(_L('Decryption failed')); |
} |
return $cleartext; |
} else { |
// When OpenSSL is not available, then we just do a HMAC |
$hmac = mb_substr($data, 0, 64, '8bit'); |
$cleartext = mb_substr($data, 64, null, '8bit'); |
$hmacNew = sha3_512_hmac($cleartext, $key, true); |
if (!hash_equals($hmac, $hmacNew)) { |
throw new OIDplusException(_L('Authentication failed')); |
} |
return $cleartext; |
} |
} |
} |
/trunk/includes/classes/OIDplusAuthUtils.class.php |
---|
198,11 → 198,9 |
$loginfo = ''; |
$acs = $this->getAuthContentStore(); |
if (!is_null($acs)) { |
// User is already logged in (a session or JWT exists), so we modify their login status |
$acs->raLoginEx($email, $loginfo); |
$acs->activate(); |
} else { |
// No user is logged in (no session or JWT exists). We now create a auth content store and activate it (cookies will be set etc.) |
if ($remember_me) { |
if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_USER', true)) { |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_LOGIN_USER')); |
330,11 → 328,9 |
$loginfo = ''; |
$acs = $this->getAuthContentStore(); |
if (!is_null($acs)) { |
// User is already logged in (a session or JWT exists), so we modify their login status |
$acs->adminLoginEx($loginfo); |
$acs->activate(); |
} else { |
// No user is logged in (no session or JWT exists). We now create a auth content store and activate it (cookies will be set etc.) |
if ($remember_me) { |
if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_ADMIN', true)) { |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_LOGIN_ADMIN')); |
/trunk/includes/classes/OIDplusSessionHandler.class.php |
---|
0,0 → 1,262 |
<?php |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
namespace ViaThinkSoft\OIDplus; |
// phpcs:disable PSR1.Files.SideEffects |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
class OIDplusSessionHandler extends OIDplusBaseClass implements OIDplusGetterSetterInterface { |
/** |
* @var string|null |
*/ |
private $secret = ''; |
/** |
* @var int|null |
*/ |
protected $sessionLifetime = 0; |
/** |
* @throws OIDplusException |
*/ |
public function __construct() { |
$this->sessionLifetime = OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60); |
$this->secret = OIDplus::authUtils()->makeSecret(['b118abc8-f4ec-11ed-86ca-3c4a92df8582']); |
// **PREVENTING SESSION HIJACKING** |
// Prevents javascript XSS attacks aimed to steal the session ID |
@ini_set('session.cookie_httponly', '1'); |
// **PREVENTING SESSION FIXATION** |
// Session ID cannot be passed through URLs |
@ini_set('session.use_only_cookies', '1'); |
@ini_set('session.use_trans_sid', '0'); |
// Uses a secure connection (HTTPS) if possible |
@ini_set('session.cookie_secure', OIDplus::isSslAvailable() ? '1' : '0'); |
$path = OIDplus::webpath(null,OIDplus::PATH_RELATIVE); |
if (empty($path)) $path = '/'; |
@ini_set('session.cookie_path', $path); |
@ini_set('session.cookie_samesite', OIDplus::baseConfig()->getValue('COOKIE_SAMESITE_POLICY', 'Strict')); |
@ini_set('session.use_strict_mode', '1'); |
@ini_set('session.gc_maxlifetime', $this->sessionLifetime); |
} |
/** |
* @return void |
* @throws OIDplusException |
*/ |
protected function sessionSafeStart() { |
if (!isset($_SESSION)) { |
// TODO: session_name() makes some problems. Leave it away for now. |
//session_name('OIDplus_SESHDLR'); |
if (!session_start()) { |
throw new OIDplusException(_L('Session could not be started')); |
} |
} |
if (!isset($_SESSION['ip'])) { |
if (!isset($_SERVER['REMOTE_ADDR'])) return; |
// Remember the IP address of the user |
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR']; |
} else { |
if ($_SERVER['REMOTE_ADDR'] != $_SESSION['ip']) { |
// Was the session hijacked?! Get out of here! |
// We don't use $this->destroySession(), because this calls sessionSafeStart() again |
$_SESSION = array(); |
session_destroy(); |
session_write_close(); |
OIDplus::cookieUtils()->unsetcookie(session_name()); // remove cookie, so GDPR people are happy |
} |
} |
} |
/** |
* @return void |
*/ |
function __destruct() { |
session_write_close(); |
} |
private $cacheSetValues = array(); // Important if you do a setValue() followed by an getValue() |
/** |
* @param string $name |
* @param mixed $value |
* @return void |
* @throws OIDplusException |
*/ |
public function setValue(string $name, $value) { |
$enc_data = self::encrypt($value, $this->secret); |
$this->cacheSetValues[$name] = $enc_data; |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
$_SESSION[$name] = $enc_data; |
} |
/** |
* @param string $name |
* @param mixed|null $default |
* @return mixed|null |
* @throws OIDplusException |
*/ |
public function getValue(string $name, $default = NULL) { |
if (isset($this->cacheSetValues[$name])) return self::decrypt($this->cacheSetValues[$name], $this->secret); |
if (!$this->isActive()) return $default; // GDPR: Only start a session when we really need one |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
if (!isset($_SESSION[$name])) return $default; |
return self::decrypt($_SESSION[$name], $this->secret); |
} |
/** |
* @param string $name |
* @return bool |
* @throws OIDplusException |
*/ |
public function exists(string $name): bool { |
if (isset($this->cacheSetValues[$name])) return true; |
if (!$this->isActive()) return false; // GDPR: Only start a session when we really need one |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
return isset($_SESSION[$name]); |
} |
/** |
* @param string $name |
* @return void |
* @throws OIDplusException |
*/ |
public function delete(string $name) { |
if (isset($this->cacheSetValues[$name])) unset($this->cacheSetValues[$name]); |
if (!$this->isActive()) return; // GDPR: Only start a session when we really need one |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
unset($_SESSION[$name]); |
} |
/** |
* @return void |
* @throws OIDplusException |
*/ |
public function destroySession() { |
if (!$this->isActive()) return; |
$this->sessionSafeStart(); |
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime); |
$_SESSION = array(); |
session_destroy(); |
session_write_close(); |
OIDplus::cookieUtils()->unsetcookie(session_name()); // remove cookie, so GDPR people are happy |
} |
/** |
* @return bool |
*/ |
public function isActive(): bool { |
return isset($_COOKIE[session_name()]); |
} |
/** |
* @param string $data |
* @param string $key |
* @return string |
* @throws \Exception |
*/ |
protected static function encrypt(string $data, string $key): string { |
if (function_exists('openssl_encrypt')) { |
$iv = random_bytes(16); // AES block size in CBC mode |
// Encryption |
$ciphertext = openssl_encrypt( |
$data, |
'AES-256-CBC', |
hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, true), |
OPENSSL_RAW_DATA, |
$iv |
); |
// Authentication |
$hmac = sha3_512_hmac($iv . $ciphertext, $key, true); |
return $hmac . $iv . $ciphertext; |
} else { |
// When OpenSSL is not available, then we just do a HMAC |
$hmac = sha3_512_hmac($data, $key, true); |
return $hmac . $data; |
} |
} |
/** |
* @param string $data |
* @param string $key |
* @return string |
* @throws OIDplusException |
*/ |
protected static function decrypt(string $data, string $key): string { |
if (function_exists('openssl_decrypt')) { |
$hmac = mb_substr($data, 0, 64, '8bit'); |
$iv = mb_substr($data, 64, 16, '8bit'); |
$ciphertext = mb_substr($data, 80, null, '8bit'); |
// Authentication |
$hmacNew = sha3_512_hmac($iv . $ciphertext, $key, true); |
if (!hash_equals($hmac, $hmacNew)) { |
throw new OIDplusException(_L('Authentication failed')); |
} |
// Decryption |
$cleartext = openssl_decrypt( |
$ciphertext, |
'AES-256-CBC', |
hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, true), |
OPENSSL_RAW_DATA, |
$iv |
); |
if ($cleartext === false) { |
throw new OIDplusException(_L('Decryption failed')); |
} |
return $cleartext; |
} else { |
// When OpenSSL is not available, then we just do a HMAC |
$hmac = mb_substr($data, 0, 64, '8bit'); |
$cleartext = mb_substr($data, 64, null, '8bit'); |
$hmacNew = sha3_512_hmac($cleartext, $key, true); |
if (!hash_equals($hmac, $hmacNew)) { |
throw new OIDplusException(_L('Authentication failed')); |
} |
return $cleartext; |
} |
} |
} |
/trunk/includes/oidplus_dependency.inc.php |
---|
87,7 → 87,7 |
} |
if (!extension_loaded('mbstring') && !extension_loaded('iconv')) { |
// Required for includes/classes/OIDplusAuthContentStoreSession.class.php |
// Required for includes/classes/OIDplusSessionHandler.class.php |
// includes/oid_utils.inc.php |
// vendor/matthiasmullie/path-converter/src/Converter.php |
// vendor/n-other/php-sha3/src/Sha3.php |