diff --git a/data/admin b/data/admin
new file mode 100644
index 0000000..d083dff
--- /dev/null
+++ b/data/admin
@@ -0,0 +1 @@
+admin|admin
\ No newline at end of file
diff --git a/data/admin.json b/data/admin.json
deleted file mode 100644
index cb084e0..0000000
--- a/data/admin.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[
- {
- "NAME":"Toni",
- "PASSWORD":"geheim",
- "PIN":1231239
- }
-]
\ No newline at end of file
diff --git a/data/s/a.svg b/data/s/a.svg
new file mode 100644
index 0000000..0260f1c
--- /dev/null
+++ b/data/s/a.svg
@@ -0,0 +1,10 @@
+
+
+
diff --git a/data/s/b.svg b/data/s/b.svg
new file mode 100644
index 0000000..d0335f6
--- /dev/null
+++ b/data/s/b.svg
@@ -0,0 +1,12 @@
+
+
+
diff --git a/data/s/bundle.45d14.css b/data/s/bundle.45d14.css
new file mode 100644
index 0000000..518bdb4
--- /dev/null
+++ b/data/s/bundle.45d14.css
@@ -0,0 +1 @@
+*{box-sizing:border-box}html{font-family:Helvetica,sans-serif;font-size:16px}body,html{height:100%}body{background-color:#fff;margin:0;padding:0;width:100%}#wrapper{-ms-flex-pack:start;-ms-flex-align:stretch;align-items:stretch;justify-content:flex-start;min-height:100%}#wrapper,.header{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%}.header{-ms-flex-pack:end;background:linear-gradient(#9e9e9e,#d1d1d1);box-shadow:0 0 .2em #444;height:4rem;justify-content:flex-end;margin:0;padding:.5em 0;position:fixed;top:0;z-index:100}.header h1{color:#fff;display:inline-block;margin:0}.header .hamburger{display:inline-block;float:right;font-size:1em;position:relative;width:3em}.header .hamburger hr{background:#fff;border:none;border-radius:.2em;box-shadow:inset 0 0 .2em #000;height:.5em;margin:0;position:relative;transition:all .25s;width:3em}.header .hamburger hr:first-child{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0}.header .hamburger hr:nth-child(2){margin:.5em 0}.header .hamburger hr:nth-child(3){-webkit-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%}.header .hamburger-active hr:first-child{background:#000;box-shadow:0 0 .1em #000;-webkit-transform:translate(.25em) rotate(45deg);-ms-transform:translate(.25em) rotate(45deg);transform:translate(.25em) rotate(45deg)}.header .hamburger-active hr:nth-child(2){opacity:0;-webkit-transform:rotate(0deg) scale(.2);-ms-transform:rotate(0deg) scale(.2);transform:rotate(0deg) scale(.2)}.header .hamburger-active hr:nth-child(3){background:#000;box-shadow:0 0 .1em #000;-webkit-transform:translate(.25em) rotate(-45deg);-ms-transform:translate(.25em) rotate(-45deg);transform:translate(.25em) rotate(-45deg)}.container{margin:0 auto;width:clamp(5ch,100%,75ch)}.container .breadcrumb{padding-top:1rem}.container .breadcrumb ul{background:#eee;border:.05em solid #fff;border-radius:.3em;box-shadow:inset 0 0 .3em #ccc,0 0 .5em #ddd;display:-ms-flexbox;display:flex;list-style-type:none;margin:0;padding:.3em}.container .breadcrumb ul li a{-ms-flex-align:center;align-items:center;background:#ccc;color:#fff;display:-ms-inline-flexbox;display:inline-flex;height:2em;padding:.5em;position:relative;text-align:center;text-decoration:none;vertical-align:middle}.container .breadcrumb ul li a:after{border-bottom:1em solid transparent;border-left:1em solid #ccc;border-top:1em solid transparent;content:"";left:100%;position:absolute;top:0;z-index:2}.container .breadcrumb ul li a:hover{background-color:#777}.container .breadcrumb ul li a:hover:after{border-left:1em solid #777}.container .breadcrumb ul li:first-child a{border-bottom-left-radius:.3em;border-top-left-radius:.3em}.container .breadcrumb ul li:not(:first-child) a{margin-left:.2em;padding-left:1.5em}.container .breadcrumb ul li:not(:first-child) a:before{border-bottom:1em solid transparent;border-left:1em solid #eee;border-top:1em solid transparent;content:"";left:0;position:absolute;top:0;z-index:1}.page{background:#fff;-ms-flex:1;flex:1;margin-top:4rem;width:100%}.menu ul,.page{display:-ms-flexbox;display:flex}.menu ul{-ms-flex-direction:column;flex-direction:column;list-style:none;margin:0;padding:0}.menu ul li a{color:#666;display:block;font-size:2em;font-style:none;padding:1em;position:relative;text-decoration:none;width:100%}.menu ul li a:hover{background:#bbb;color:#333}.menu ul li a:after{background:#8a8080;content:"";height:.1em;left:0;position:absolute;top:100%;width:100%;z-index:2}#login_form{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;margin:0 auto;padding:1em}#login_form .input-box{position:relative}#login_form .input-box input{border:none;border-radius:none;display:block;font-size:1.5em;outline:none;padding:.7em;width:100%}#login_form .input-box input+label{cursor:text;left:0;position:absolute;top:0;transition:all .25s}#login_form .input-box input::-webkit-input-placeholder{color:transparent}#login_form .input-box input:-ms-input-placeholder{color:transparent}#login_form .input-box input::placeholder{color:transparent}#login_form .input-box input:-ms-input-placeholder+label{color:gray;font-size:1.5em;padding:.7em;position:absolute}#login_form .input-box input:placeholder-shown+label{color:gray;font-size:1.5em;padding:.7em;position:absolute}#login_form p{font-size:2em}#login_form input[type=submit]{border:none;border-radius:none;font-size:2em}.page-nav-bar{margin:1em;text-align:center}.page-nav-bar ul{-ms-flex-pack:center;display:-ms-flexbox;display:flex;justify-content:center;list-style:none;margin:0;padding:0}.page-nav-bar ul li a{background:#eee;border:.1em solid #ccc;border-radius:.3em;color:#ccc;font-weight:700;margin:.3em;padding:.2em .5em;text-decoration:none}.page-nav-bar ul li a.active{background:#888;color:#eee}.page-nav-bar ul li a:hover{background:#fff;border:.1em solid #ccc;color:#333}.user-list-item{background:#eee;border-radius:.3em;display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;overflow:hidden;padding:.5em 0}.user-list-item:not(:last-child){margin-bottom:.5em}.user-list-item .user-attributes{padding:.5em}.btn-group{-ms-flex-item-align:end;align-self:flex-end;display:-ms-inline-flexbox;display:inline-flex;-ms-flex-direction:column;flex-direction:column;justify-self:flex-end;margin-left:auto}.btn-trash{background:#eee;background-image:url(/a.svg);background-origin:border-box;background-position:0;background-repeat:no-repeat;border:none;border-bottom-left-radius:1.5em;border-top-left-radius:1.5em;height:3em;margin-left:auto;padding:0 0 0 3em;position:relative;transition:background-size .15s,padding .2s,width .1s;width:3em}.btn-trash:not(:last-of-type){margin-bottom:.5em}.btn-trash:hover{background-color:#000;background-position:0;box-shadow:0 0 .5em #333;color:#ccc;-webkit-filter:invert(120%);filter:invert(120%);padding-right:.5em;width:auto}.btn-trash:hover:before{border-radius:50%;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.btn-edit{background:#eee;background-image:url(/b.svg);background-origin:border-box;background-position:0;background-repeat:no-repeat;border:none;border-bottom-left-radius:1.5em;border-top-left-radius:1.5em;height:3em;margin-left:auto;padding:0 0 0 3em;position:relative;transition:background-size .15s,padding .2s,width .1s;width:3em}.btn-edit:not(:last-of-type){margin-bottom:.5em}.btn-edit:hover{background-color:#000;background-position:0;box-shadow:0 0 .5em #333;color:#ccc;-webkit-filter:invert(120%);filter:invert(120%);padding-right:.5em;width:auto}.btn-edit:hover:before{border-radius:50%;bottom:0;content:"";left:0;position:absolute;right:0;top:0}footer{-ms-flex-negative:0;background:#bbb;color:#fff;display:block;flex-shrink:0;margin-top:1rem;padding:.5rem 0;text-shadow:0 0 .2em #34d;width:100%}
\ No newline at end of file
diff --git a/data/s/bundle.f9ad8.js b/data/s/bundle.f9ad8.js
new file mode 100644
index 0000000..b210df8
--- /dev/null
+++ b/data/s/bundle.f9ad8.js
@@ -0,0 +1,2 @@
+!function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};e.m=t,e.c=n,e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:r})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,n){if(1&n&&(t=e(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var o in t)e.d(r,o,function(e){return t[e]}.bind(null,o));return r},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/",e(e.s="/ODT")}({"/ODT":function(t,e,n){"use strict";function r(t,e){for(var n in e)t[n]=e[n];return t}function o(t){var e=t.parentNode;e&&e.removeChild(t)}function u(t,e,n){var r,o,u,l={};for(u in e)"key"==u?r=e[u]:"ref"==u?o=e[u]:l[u]=e[u];if(arguments.length>2&&(l.children=arguments.length>3?x.call(arguments,2):n),"function"==typeof t&&null!=t.defaultProps)for(u in t.defaultProps)void 0===l[u]&&(l[u]=t.defaultProps[u]);return i(t,l,r,o,null)}function i(t,e,n,r,o){var u={type:t,props:e,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++P:o};return null==o&&null!=C.vnode&&C.vnode(u),u}function l(t){return t.children}function c(t,e){this.props=t,this.context=e}function a(t,e){if(null==e)return t.__?a(t.__,t.__.__k.indexOf(t)+1):null;for(var n;e0?i(b.type,b.props,b.key,null,b.__v):b)){if(b.__=n,b.__b=n.__b+1,null===(v=S[p])||v&&b.key==v.key&&b.type===v.type)S[p]=void 0;else for(y=0;y=n.__.length&&n.__.push({}),n.__[t]}function o(t){return v=1,u(f,t)}function u(t,e,n){var o=r(p++,2);return o.t=t,o.__c||(o.__=[n?n(e):f(void 0,e),function(t){var e=o.t(o.__[0],t);o.__[0]!==e&&(o.__=[e,o.__[1]],o.__c.setState({}))}],o.__c=h),o.__}function i(t,e){var n=r(p++,3);!y.options.__s&&s(n.__H,e)&&(n.__=t,n.__H=e,h.__H.__h.push(n))}function l(t){var e=h.context[t.__c],n=r(p++,9);return n.c=t,e?(null==n.__&&(n.__=!0,e.sub(h)),e.props.value):t.__}function c(){for(var t;t=b.shift();)if(t.__P)try{t.__H.__h.forEach(a),t.__H.__h.forEach(_),t.__H.__h=[]}catch(e){t.__H.__h=[],y.options.__e(e,t.__v)}}function a(t){var e=h,n=t.__c;"function"==typeof n&&(t.__c=void 0,n()),h=e}function _(t){var e=h;t.__c=t.__(),h=e}function s(t,e){return!t||t.length!==e.length||e.some((function(e,n){return e!==t[n]}))}function f(t,e){return"function"==typeof e?e(t):e}n.d(e,"d",(function(){return o})),n.d(e,"c",(function(){return u})),n.d(e,"b",(function(){return i})),n.d(e,"a",(function(){return l}));var p,h,d,y=n("hosL"),v=0,b=[],m=y.options.__b,g=y.options.__r,O=y.options.diffed,j=y.options.__c,k=y.options.unmount;y.options.__b=function(t){h=null,m&&m(t)},y.options.__r=function(t){g&&g(t),p=0;var e=(h=t.__c).__H;e&&(e.__h.forEach(a),e.__h.forEach(_),e.__h=[])},y.options.diffed=function(t){O&&O(t);var e=t.__c;e&&e.__H&&e.__H.__h.length&&(1!==b.push(e)&&d===y.options.requestAnimationFrame||((d=y.options.requestAnimationFrame)||function(t){var e,n=function(){clearTimeout(r),w&&cancelAnimationFrame(e),setTimeout(t)},r=setTimeout(n,100);w&&(e=requestAnimationFrame(n))})(c)),h=null},y.options.__c=function(t,e){e.some((function(t){try{t.__h.forEach(a),t.__h=t.__h.filter((function(t){return!t.__||_(t)}))}catch(n){e.some((function(t){t.__h&&(t.__h=[])})),e=[],y.options.__e(n,t.__v)}})),j&&j(t,e)},y.options.unmount=function(t){k&&k(t);var e,n=t.__c;n&&n.__H&&(n.__H.__.forEach((function(t){try{a(t)}catch(t){e=t}})),e&&y.options.__e(e,n.__v))};var w="function"==typeof requestAnimationFrame},QfWi:function(t,e,n){"use strict";function r(t,e){for(var n in e)t[n]=e[n];return t}function o(t,e,n){var r,o=/(?:\?([^#]*))?(#.*)?$/,u=t.match(o),i={};if(u&&u[1])for(var c=u[1].split("&"),a=0;ae.rank?-1:t.index-e.index}function i(t,e){return t.index=e,t.rank=function(t){return t.props.default?0:(e=t.props.path,l(e).map(c).join(""));var e}(t),t.props}function l(t){return t.replace(/(^\/+|\/+$)/g,"").split("/")}function c(t){return":"==t.charAt(0)?1+"*+?".indexOf(t.charAt(t.length-1))||4:5}function a(){var t;return""+((t=E&&E.location?E.location:E&&E.getCurrentLocation?E.getCurrentLocation():"undefined"!=typeof location?location:T).pathname||"")+(t.search||"")}function _(t,e){return void 0===e&&(e=!1),"string"!=typeof t&&t.url&&(e=t.replace,t=t.url),function(t){for(var e=U.length;e--;)if(U[e].canRoute(t))return!0;return!1}(t)&&function(t,e){void 0===e&&(e="push"),E&&E[e]?E[e](t):"undefined"!=typeof history&&history[e+"State"]&&history[e+"State"](null,null,t)}(t,e?"replace":"push"),s(t)}function s(t){for(var e=!1,n=0;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n0},e.prototype.routeTo=function(t){this.setState({url:t});var e=this.canRoute(t);return this.updating||this.forceUpdate(),e},e.prototype.componentWillMount=function(){U.push(this),this.updating=!0},e.prototype.componentDidMount=function(){var t=this;E&&(this.unlisten=E.listen((function(e){t.routeTo(""+(e.pathname||"")+(e.search||""))}))),this.updating=!1},e.prototype.componentWillUnmount=function(){"function"==typeof this.unlisten&&this.unlisten(),U.splice(U.indexOf(this),1)},e.prototype.componentWillUpdate=function(){this.updating=!0},e.prototype.componentDidUpdate=function(){this.updating=!1},e.prototype.getMatchingChildren=function(t,e,n){return t.filter(i).sort(u).map((function(t){var u=o(e,t.props.path,t.props);if(u){if(!1!==n){var i={url:e,matches:u};return r(i,u),delete i.ref,delete i.key,Object(C.cloneElement)(t,i)}return t}})).filter(Boolean)},e.prototype.render=function(t,e){var n=t.children,r=t.onChange,o=e.url,u=this.getMatchingChildren(Object(C.toChildArray)(n),o,!0),i=u[0]||null,l=this.previousUrl;return o!==l&&(this.previousUrl=o,"function"==typeof r&&r({router:this,url:o,previous:l,active:u,current:i})),i},e}(C.Component),R=function(t){return Object(C.createElement)("a",r({onClick:p},t))};I.subscribers=D,I.getCurrentUrl=a,I.route=_,I.Router=I,I.Route=function(t){return Object(C.createElement)(t.component,t)},I.Link=R,I.exec=o;var N=function(t,e){switch(e){case"show":return!0;case"hide":return!1;case"toggle":return!t;default:throw new Error("menustate unknown to reducer")}},M=function(t,e){switch(e.type){case"start":return{active:!0,token:e.token,username:e.username};case"end":return{active:!1,token:null,username:null,exiry:null};default:throw new Error("action type unknown to session reducer")}},H=n("QRet"),W=function(){return Object(C.h)("div",{class:"container"},Object(C.h)("h1",null,"Home"),Object(C.h)("p",null,"This is the Home component."))},F=n("L7jf"),B=function(t){var e=t.user,n=y(Object(H.d)(Date.now()),2),r=n[0],o=n[1],u=y(Object(H.d)(10),2),i=u[0],l=u[1];return Object(H.b)((function(){var t=setInterval((function(){return o(Date.now())}),1e3);return function(){return clearInterval(t)}}),[]),Object(C.h)("div",{className:"container"},Object(C.h)("div",null,Object(C.h)("h1",null,"Profile: ",e),Object(C.h)("p",null,"This is the user profile for a user named ",e,"."),Object(C.h)("div",null,"Current time: ",new Date(r).toLocaleString()),Object(C.h)("p",null,Object(C.h)("button",{onClick:function(){return l((function(t){return t+1}))}},"Click Me")," ","Clicked ",i," times.")))},$=n("YRIq"),q=function(t){if(t.items)return Object(C.h)("div",{class:"breadcrumb"},Object(C.h)("ul",null,t.items.map((function(t,e){return Object(C.h)("li",{key:e},Object(C.h)("a",{href:"#"},t)," ")}))))},z=function(){var t=O(Object(H.a)($.b).session,2),e=t[0],n=t[1],r=O(Object(H.d)({username:"",password:"",error:null}),2),o=r[0],u=r[1];return e.active&&_("/",!0),Object(C.h)("div",{class:"container"},Object(C.h)(q,{items:["Login"]}),Object(C.h)("form",{id:"login_form",onSubmit:function(t){if(t.preventDefault(),"admin"===o.username){n({type:"start",username:"affe",token:"dsf4w3qr"})}else u(m(m({},o),{},{error:"user"}));u({username:"",password:""})}},Object(C.h)("p",null,"Bitte melden Sie sich mit ihren Nutzerdaten an."),null!==o.error&&Object(C.h)("span",{style:"color: red"},"Fehler: Ungültige Anmeldedaten."),Object(C.h)("div",{class:"input-box"},Object(C.h)("input",{id:"name",type:"text",placeholder:"Username",onInput:function(t){return u(m(m({},o),{},{username:t.target.value}))},value:o.username}),Object(C.h)("label",{for:"name"},"Benutzername")),Object(C.h)("div",{class:"input-box"},Object(C.h)("input",{id:"pass",type:"password",placeholder:"Passwort",onInput:function(t){return u(m(m({},o),{},{password:t.target.value}))},value:o.password}),Object(C.h)("label",{for:"pass"},"Password")),Object(C.h)("input",{type:"submit",value:"Submit"})))},K=function(){var t=k(Object(H.a)($.b).session,2),e=t[0],n=t[1];return this.shouldComponentUpdate=function(){console.log("functional component vs closures")},e.active&&n({type:"end"}),Object(C.h)("div",{class:"container"},Object(C.h)(q,{items:["Logout"]}),Object(C.h)("p",null,"Erfolgreich abgemeldet.",Object(C.h)(R,{href:"/login"},"Erneut Anmelden")))},Q=function(){var t=Object(H.c)(N,!1),e=Object(H.c)(M,{active:!0});return Object(H.b)((function(){console.log("Use Session")})),this.menu_items=[{text:"Übersicht",path:"/"},{text:"Benutzer",path:"/users"},{text:"System",path:"/system"},{text:"Profil",path:"/profile"},{text:"Abmelden",path:"/logout"}],this.handleRoute=function(){var t,n=(t=function*(){e[0].active||_("/login",!0)},function(){var e=this,n=arguments;return new Promise((function(r,o){function u(t){S(l,r,o,u,i,"next",t)}function i(t){S(l,r,o,u,i,"throw",t)}var l=t.apply(e,n);u(void 0)}))});return function(t){return n.apply(this,arguments)}}(),Object(C.h)($.a,{value:{menu:t,session:e}},Object(C.h)("div",{id:"wrapper"},Object(C.h)(V.a,null),Object(C.h)("div",{class:"page"},Object(C.h)(G,{items:this.menu_items}),!t[0]&&Object(C.h)(I,{onChange:this.handleRoute},Object(C.h)(W,{path:"/",user:"me"}),Object(C.h)(z,{path:"login"}),Object(C.h)(B,{path:"/profile"}),Object(C.h)(K,{path:"/logout"}),Object(C.h)(F.a,{path:"/users"}),Object(C.h)("div",{class:"container",default:!0},"Error 404"))),Object(C.h)("footer",null,Object(C.h)("div",{className:"container",style:"text-align: center; align-items: center"},Object(C.h)("span",null,"© Jean Jacques Avril 2022 ")))))},V=(n("ab6c"),n("z8Av")),G=(n("hNgA"),function(t){var e=t.items,n=A(Object(H.a)($.b).menu,2),r=n[1],o=[{text:"Übersicht",path:"/"},{text:"Benutzer",path:"/users"},{text:"System",path:"/system"},{text:"Backup",path:"/backup"},{text:"Abmelden",path:"/logout"}],u=function(t){t.preventDefault(),r("hide")};if(e&&(o=e),n[0])return Object(C.h)("div",{class:"container"},Object(C.h)("nav",{className:"menu"},Object(C.h)("ul",null,o.map((function(t,e){return Object(C.h)("li",{key:e},Object(C.h)(R,{href:t.path,onClick:u},t.text))})))))}),J=Q;Object(C.render)(Object(C.h)(J,null),document.body)},YRIq:function(t,e,n){"use strict";n.d(e,"a",(function(){return u}));var r=n("hosL"),o=Object(r.createContext)({}),u=o.Provider;e.b=o},ab6c:function(t,e,n){"use strict";function r(){return r=Object.assign||function(t){for(var e=1;e"))),Object(o.h)("div",{class:"page-nav-bar"},Object(o.h)("ul",null,e))}},hNgA:function(t,e,n){"use strict";(function(t,r){function o(t){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o(t)}function u(t,e){for(var n=0;n2&&(l.children=arguments.length>3?D.call(arguments,2):n),"function"==typeof t&&null!=t.defaultProps)for(u in t.defaultProps)void 0===l[u]&&(l[u]=t.defaultProps[u]);return i(t,l,r,o,null)}function i(t,e,n,r,o){var u={type:t,props:e,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++L:o};return null==o&&null!=T.vnode&&T.vnode(u),u}function l(){return{current:null}}function c(t){return t.children}function a(t,e){this.props=t,this.context=e}function _(t,e){if(null==e)return t.__?_(t.__,t.__.__k.indexOf(t)+1):null;for(var n;e0?i(b.type,b.props,b.key,null,b.__v):b)){if(b.__=n,b.__b=n.__b+1,null===(y=k[p])||y&&b.key==y.key&&b.type===y.type)k[p]=void 0;else for(h=0;h2&&(c.children=arguments.length>3?D.call(arguments,2):n),i(t.type,c,o||t.key,u||t.ref,null)}function U(t,e){var n={__c:e="__cC"+H++,__:t,Consumer:function(t,e){return t.children(e)},Provider:function(t){var n,r;return this.getChildContext||(n=[],(r={})[e]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(t){this.props.value!==t.value&&n.some(f)},this.sub=function(t){n.push(t);var e=t.componentWillUnmount;t.componentWillUnmount=function(){n.splice(n.indexOf(t),1),e&&e.call(t)}}),t.children}};return n.Provider.__=n.Consumer.contextType=n}n.r(e),n.d(e,"render",(function(){return C})),n.d(e,"hydrate",(function(){return P})),n.d(e,"createElement",(function(){return u})),n.d(e,"h",(function(){return u})),n.d(e,"Fragment",(function(){return c})),n.d(e,"createRef",(function(){return l})),n.d(e,"isValidElement",(function(){return I})),n.d(e,"Component",(function(){return a})),n.d(e,"cloneElement",(function(){return E})),n.d(e,"createContext",(function(){return U})),n.d(e,"toChildArray",(function(){return y})),n.d(e,"options",(function(){return T}));var D,T,L,I,R,N,M,H,W={},F=[],B=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;D=F.slice,T={__e:function(t,e){for(var n,r,o;e=e.__;)if((n=e.__c)&&!n.__)try{if((r=n.constructor)&&null!=r.getDerivedStateFromError&&(n.setState(r.getDerivedStateFromError(t)),o=n.__d),null!=n.componentDidCatch&&(n.componentDidCatch(t),o=n.__d),o)return n.__E=n}catch(e){t=e}throw t}},L=0,I=function(t){return null!=t&&void 0===t.constructor},a.prototype.setState=function(t,e){var n;n=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=r({},this.state),"function"==typeof t&&(t=t(r({},n),this.props)),t&&r(n,t),null!=t&&this.__v&&(e&&this.__h.push(e),f(this))},a.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),f(this))},a.prototype.render=c,R=[],N="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,p.__r=0,H=0},z8Av:function(t,e,n){"use strict";(function(t){function r(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null==n)return;var r,o,u=[],i=!0,l=!1;try{for(n=n.call(t);!(i=(r=n.next()).done)&&(u.push(r.value),!e||u.length!==e);i=!0);}catch(t){l=!0,o=t}finally{try{i||null==n.return||n.return()}finally{if(l)throw o}}return u}(t,e)||function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Array.from(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(t,e)}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);ndoorlock_pwa
\ No newline at end of file
diff --git a/data/s/polyfills.058fb.js b/data/s/polyfills.058fb.js
new file mode 100644
index 0000000..3ddfedd
--- /dev/null
+++ b/data/s/polyfills.058fb.js
@@ -0,0 +1,2 @@
+!function(t){function e(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:o})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,n){if(1&n&&(t=e(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(e.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var r in t)e.d(o,r,function(e){return t[e]}.bind(null,r));return o},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/",e(e.s="Lt8t")}({"5y5z":function(t,e,n){"use strict";function o(t){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o(t)}function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r(t)}function u(t){return Boolean(t&&void 0!==t.length)}function i(){}function f(t){if(!(this instanceof f))throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],y(t,this)}function c(t,e){for(;3===t._state;)t=t._value;0!==t._state?(t._handled=!0,f._immediateFn((function(){var n=1===t._state?e.onFulfilled:e.onRejected;if(null!==n){var o;try{o=n(t._value)}catch(t){return void s(e.promise,t)}l(e.promise,o)}else(1===t._state?l:s)(e.promise,t._value)}))):t._deferreds.push(e)}function l(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"===r(e)||"function"==typeof e)){var n=e.then;if(e instanceof f)return t._state=3,t._value=e,void a(t);if("function"==typeof n)return void y((o=n,u=e,function(){o.apply(u,arguments)}),t)}t._state=1,t._value=e,a(t)}catch(e){s(t,e)}var o,u}function s(t,e){t._state=2,t._value=e,a(t)}function a(t){2===t._state&&0===t._deferreds.length&&f._immediateFn((function(){t._handled||f._unhandledRejectionFn(t._value)}));for(var e=0,n=t._deferreds.length;e
-
-
-
-
-
- Document
-
-
- Error 404: Page not found.
-
-
\ No newline at end of file
diff --git a/data/static/index.html b/data/static/index.html
deleted file mode 100644
index 9847b8e..0000000
--- a/data/static/index.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
- Document
-
-
- Welcome on ESP8266
-
-
\ No newline at end of file
diff --git a/src/Config.cpp b/src/Config.cpp
new file mode 100644
index 0000000..5100fbb
--- /dev/null
+++ b/src/Config.cpp
@@ -0,0 +1,21 @@
+#include "Config.h"
+
+Config::Config()
+{
+ if (!LittleFS.begin())
+ {
+ Serial.println("An Error has occurred while mounting LittleFS");
+ return;
+ }
+}
+
+
+bool Config::loadConfig()
+{
+ StaticJsonDocument<1024> doc;
+ File config_file = LittleFS.open("/config.json","r");
+ deserializeJson(doc, config_file);
+ this->SSID=doc["SSID"].as();
+ this->PASS=doc["PASS"].as();
+ return true;
+}
diff --git a/src/Config.h b/src/Config.h
new file mode 100644
index 0000000..c37f1ff
--- /dev/null
+++ b/src/Config.h
@@ -0,0 +1,12 @@
+#pragma once
+#include "LittleFS.h"
+#include "ArduinoJson.h"
+class Config
+{
+public:
+ Config();
+ const char *SSID;
+ const char *PASS;
+ int THEME;
+ bool loadConfig();
+};
\ No newline at end of file
diff --git a/src/Persistence.cpp b/src/Persistence.cpp
deleted file mode 100644
index db266f6..0000000
--- a/src/Persistence.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "Persistence.h"
-
-Persistence::Persistence()
-{
- if (!LittleFS.begin())
- {
- Serial.println("An Error has occurred while mounting LittleFS");
- return;
- }
-}
-String Persistence::TestRead()
-{
- File file = LittleFS.open("/users.json", "r");
- String result = "";
- if (!file)
- {
- Serial.println("Failed to open file for reading");
- return result;
- }
- Serial.println("File Content:");
- while (file.available())
- {
- result += (char)file.read();
- }
- file.close();
- return result;
-}
-
-Persistence::Configuration Persistence::loadConfig()
-{
- StaticJsonDocument<1024> doc;
- File config_file = LittleFS.open("/config.json","r");
- deserializeJson(doc, config_file);
- Configuration res;
- res.SSID=doc["SSID"].as();
- res.PASS=doc["PASS"].as();
- return res;
-}
-DynamicJsonDocument Persistence::readUsers(){
- File user_file = LittleFS.open("/users.json","r");
- size_t buffersize = user_file.size()+512;
- Serial.printf("Reserved %i for reading UserDB File", buffersize);
- DynamicJsonDocument doc(user_file.size()+512);
- deserializeJson(doc, user_file);
- user_file.close();
- return doc;
-}
-bool Persistence::saveUsers(DynamicJsonDocument &doc){
- File user_file = LittleFS.open("/users.json","w");
- serializeJson(doc, user_file);
- user_file.close();
-
- return true;
-}
\ No newline at end of file
diff --git a/src/Persistence.h b/src/Persistence.h
deleted file mode 100644
index 9530a07..0000000
--- a/src/Persistence.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-#include "LittleFS.h"
-#include "ArduinoJson.h"
-class Persistence
-{
- public:
- Persistence();
- String TestRead();
- typedef struct Configuration{
- const char* SSID;
- const char* PASS;
- int THEME;
- } config;
- Configuration loadConfig();
- DynamicJsonDocument readUsers();
- bool saveUsers(DynamicJsonDocument &doc);
-};
\ No newline at end of file
diff --git a/src/UserDb.h b/src/UserDb.h
index c692ba0..d6e8a98 100644
--- a/src/UserDb.h
+++ b/src/UserDb.h
@@ -1,5 +1,5 @@
#pragma once
-#include "Persistence.h"
+#include "Config.h"
#include "LittleFS.h"
#include
#include
diff --git a/src/Users.cpp b/src/Users.cpp
deleted file mode 100644
index 4c34841..0000000
--- a/src/Users.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "Users.h"
-
-
-Users::Users(Persistence &p): persistence(p){
-}
-Users::~Users()
-{
-}
-bool Users::ImportFromPersistence(){
- Serial.println("Importing Users from Persistence");
- DynamicJsonDocument user_persistence = persistence.readUsers();
- JsonArray array = user_persistence.as();
- for(JsonObject userdata : array){
- User *imported = new User();
- imported->uid= userdata["ID"].as();
- if(_userdb.count(*imported))
- continue;
- imported->first_name = userdata["FIRST_NAME"].as();
- imported->last_name = userdata["LAST_NAME"].as();
- imported->rfid_uid = userdata["RFID_UID"].as();
- imported->user_pin = userdata["USER_PIN"].as();
- imported->enabled = userdata["ENABLED"].as();
- this->_userdb.insert(*imported);
- }
- Serial.println("User import is done!");
- return true;
-}
-
-bool Users::ExportToPersistence(){
- Serial.println("Exporting Users to Persistence");
- size_t user_amount = _userdb.size()+2;
- Serial.print( " User Amount: " );
- Serial.print(user_amount);
- size_t capacity = JSON_ARRAY_SIZE(user_amount) + user_amount*JSON_OBJECT_SIZE(6);
- Serial.print(" JSON Capacity");
- Serial.print(capacity);
- Serial.print(" Free Heap: ");
- Serial.print(ESP.getFreeHeap());
- //DynamicJsonDocument doc;
- DynamicJsonDocument doc(capacity);
-
- for(Users::User u : _userdb){
- JsonObject exported_user = doc.createNestedObject();
- exported_user["ID"] = u.uid;
- exported_user["FIRST_NAME"] = u.first_name;
- exported_user["LAST_NAME"] = u.last_name;
- exported_user["RFID_UID"] = u.rfid_uid;
- exported_user["USER_PIN"] = u.user_pin;
- exported_user["ENABLED"] = u.enabled;
- }
- persistence.saveUsers(doc);
- Serial.println("User export is done!");
- return true;
-}
-bool Users::checkPin(String pin_code, std::vector *logon_users)
-{
- std::copy_if(this->_userdb.begin(), this->_userdb.end(), inserter(*logon_users, logon_users->end()), [=](user_account user)
- { return pin_code == user.user_pin&&user.enabled==true; });
- return (logon_users->size() > 0);
-}
-
-bool Users::checkRfid(String rfid_code, std::vector *logon_users)
-{
- std::copy_if(this->_userdb.begin(), this->_userdb.end(), inserter(*logon_users, logon_users->end()), [=](user_account user)
- { return rfid_code == user.rfid_uid&&user.enabled==true; });
- return (logon_users->size() > 0);
-}
-
-unsigned long Users::addUser(String first_name, String last_name, String rifd_uid, String user_pin)
-{
- Serial.println("Adding User:" + first_name);
- unsigned long new_id = this->_userdb.rbegin()->uid + 1;
- this->_userdb.insert(user_account{.uid = new_id, .first_name = first_name, .last_name = last_name, .rfid_uid = rifd_uid, .user_pin = user_pin});
- return new_id;
-}
-
-bool Users::delUser(unsigned long id)
-{
- return this->_userdb.erase(user_account{.uid = id})>0;
-}
-
-bool Users::updateUser(unsigned long id, ATTRIBUTES attr, String value)
-{
- auto modify = this->_userdb.find(user_account{.uid = id});
- switch (attr)
- {
- case FIRST_NAME:
- modify->first_name = value;
- break;
- case LAST_NAME:
- modify->last_name = value;
- break;
- case RFID_UID:
- modify->rfid_uid = value;
- break;
- case USER_PIN:
- modify->user_pin = value;
- break;
-
- default:
- break;
- }
- return false;
-}
-
-size_t Users::countUsers(){
- return _userdb.size();
-}
-String Users::toString(User *user)
-{
- return "UID: " + String(user->uid) + " Name: " + user->first_name + " " + user->last_name;
-}
-void Users::PrintAllToSerial(){
- Serial.println("#All Users:");
- for(Users::User u : _userdb){
- Serial.println(toString(&u));
- }
-}
\ No newline at end of file
diff --git a/src/Users.h b/src/Users.h
deleted file mode 100644
index fca9dd6..0000000
--- a/src/Users.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-#include
-#include
-#include
-#include "Persistence.h"
-class Users
-{
-public:
- enum ATTRIBUTES{
- FIRST_NAME,
- LAST_NAME,
- RFID_UID,
- USER_PIN
- };
- typedef struct User
- {
- //User(unsigned long new_uid): uid(new_uid){}
- unsigned long uid;
- mutable String first_name;
- mutable String last_name;
- mutable String rfid_uid;
- mutable String user_pin;
- mutable bool enabled = true;
- bool operator < (const User &o) const { return uid _userdb;
- Persistence &persistence;
- /* data */
-public:
- Users(Persistence &persistence);
- ~Users();
- bool checkRfid(String rfid_code, std::vector *logon_users);
- bool checkPin(String pin_code, std::vector *logon_users);
- unsigned long addUser(String first_name, String last_name, String rifd_uid, String user_pin);
- bool delUser(unsigned long id);
- bool updateUser(unsigned long id, ATTRIBUTES attr, String value);
- String toString(User *user);
- bool ImportFromPersistence();
- bool ExportToPersistence();
- void PrintAllToSerial();
- size_t countUsers();
-};
\ No newline at end of file
diff --git a/src/WebConsole.cpp b/src/WebConsole.cpp
index a6f7084..7f279ad 100644
--- a/src/WebConsole.cpp
+++ b/src/WebConsole.cpp
@@ -23,8 +23,8 @@ bool WebConsole::init(userdb::UserDb *userdb)
_server->on(UriBraces("/api/user/{}"), HTTPMethod::HTTP_POST, std::bind(&WebConsole::_updateUser, this));
_server->on(UriBraces("/api/config/{}"), std::bind(&WebConsole::_deleteUser, this));
//_server->on("/bypin",std::bind(&WebConsole::_findPin,this));
- _server->serveStatic("/", LittleFS, "/static/index.html");
- //_server->onNotFound(std::bind(&WebConsole::_handleStatic, this));
+ _server->serveStatic("/", LittleFS, "/s/");
+ _server->onNotFound(std::bind(&WebConsole::_handleUnknown, this));
return true;
}
void WebConsole::attachRfid(Rfid *rfid)
@@ -45,34 +45,19 @@ bool WebConsole::isInterceptingRfid()
{
return catch_rfid;
}
-void WebConsole::_handleStatic()
+void WebConsole::_handleUnknown()
{
- String path = path_prefix + _server->uri();
- Serial.print("Request " + path);
- File src = LittleFS.open(path, "r");
- if (src.isDirectory())
+ if (_server->method() == HTTP_OPTIONS)
{
- path += "index.html";
- src.close();
- src = LittleFS.open(path, "r");
- }
- if (!src)
- {
- path = "/static/error404.html";
- src.close();
- src = LittleFS.open(path, "r");
- }
-
- Serial.println(" resolved to " + path);
- if (src)
- {
- String content_type = "text/html";
- _server->streamFile(src, content_type);
- src.close();
- }
- else
- {
- _server->send(500, "text/plain", "Internal error 500");
+ _server->sendHeader("Access-Control-Allow-Origin", "*");
+ _server->sendHeader("Access-Control-Max-Age", "10000");
+ _server->sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
+ _server->sendHeader("Access-Control-Allow-Headers", "*");
+ _server->send(204);
+ }else {
+ File src = LittleFS.open("s/index.html", "r");
+ _server->streamFile(src, "text/html");
+ src.close();
}
}
@@ -238,3 +223,6 @@ void WebConsole::_catchRFID()
_server->send(500, "text/json", "{\"ok\":\"now activated\"}");
}
}
+void WebConsole::_updateAdmin()
+{
+}
\ No newline at end of file
diff --git a/src/WebConsole.h b/src/WebConsole.h
index 8895bea..4b40651 100644
--- a/src/WebConsole.h
+++ b/src/WebConsole.h
@@ -9,7 +9,7 @@
#include "Rfid.h"
namespace webconsole
{
- static const char path_prefix[] PROGMEM = "/static";
+ static const char path_prefix[] PROGMEM = "/s";
static ESP8266WebServer _server(80);
class WebConsole
{
@@ -23,7 +23,7 @@ namespace webconsole
bool isInterceptingRfid();
private:
- void _handleStatic();
+ void _handleUnknown();
void _getUserDb();
void _deleteUser();
void _getUser();
@@ -31,6 +31,7 @@ namespace webconsole
void _createUser();
void _dropUserDb();
void _catchRFID();
+ void _updateAdmin();
void _print_db_raw()
{
File f = LittleFS.open("userdb.csv", "r");
diff --git a/src/main.cpp b/src/main.cpp
index 1be655f..14c3577 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -7,9 +7,9 @@
#include
#include "WebConsole.h"
#include "UserDb.h"
-#include "Persistence.h"
-// File persistence
-Persistence persistence;
+#include "Config.h"
+// File config
+Config config;
userdb::UserDb userdatabase("userdb.csv");
webconsole::WebConsole web;
// Rfid
@@ -26,12 +26,10 @@ IPAddress local_IP(192, 168, 4, 22);
IPAddress gateway(192, 168, 4, 9);
IPAddress subnet(255, 255, 255, 0);
-// User DB
-// Users users(persistence);
void setup()
{
- Persistence::Configuration config = persistence.loadConfig();
+ config.loadConfig();
Serial.begin(115200);
Serial.println("Starting System");
Serial.print("\t1. Network config ->");