diff --git a/.gitignore b/.gitignore index eb8c16e4dd5008eddd65e0e9df46c55e7b3ddcf0..7528976112287fc7f887d3a99df6c64b0cd6e2ae 100644 --- a/.gitignore +++ b/.gitignore @@ -32,11 +32,6 @@ build/ dist/ setup.json parser.osio.log -gui/src/metainfo.json -gui/src/searchQuantities.json -gui/src/toolkitMetadata.json -gui/src/unitsData.js -gui/src/parserMetadata.js examples/workdir/ gunicorn.log.conf nomad/gitinfo.py @@ -44,4 +39,3 @@ nomad/gitinfo.py jupyterhub_cookie_secret jupyterhub.sqlite jupyterhub-proxy.pid -gui/src/parserMetadata.json diff --git a/.gitmodules b/.gitmodules index 6e57245aa5ccaee9530ae1ff225ac50599e8a0a3..a11072e9929bc0d3f29d96efc62a48f35b82e008 100644 --- a/.gitmodules +++ b/.gitmodules @@ -213,6 +213,6 @@ [submodule "dependencies/parsers/asr"] path = dependencies/parsers/asr url = https://github.com/nomad-coe/nomad-parser-asr.git -[submodule "ops/images/webtop/north-guacamole-client"] - path = ops/images/webtop/north-guacamole-client - url = https://github.com/nomad-coe/north-guacamole-client.git +[submodule "dependencies/nomad-remote-tools-hub"] + path = dependencies/nomad-remote-tools-hub + url = https://gitlab.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub.git diff --git a/dependencies/nomad-remote-tools-hub b/dependencies/nomad-remote-tools-hub new file mode 160000 index 0000000000000000000000000000000000000000..e8003e43d2e2593a33d48847851d11fc67be3964 --- /dev/null +++ b/dependencies/nomad-remote-tools-hub @@ -0,0 +1 @@ +Subproject commit e8003e43d2e2593a33d48847851d11fc67be3964 diff --git a/generate_gui_artifacts.sh b/generate_gui_artifacts.sh index aa3993e2de43fb07d106f0320dc4e03178ad4348..588eb46c46da5db1eefa882759ba886210794f13 100755 --- a/generate_gui_artifacts.sh +++ b/generate_gui_artifacts.sh @@ -3,4 +3,5 @@ python -m nomad.cli dev metainfo > gui/src/metainfo.json python -m nomad.cli dev search-quantities > gui/src/searchQuantities.json python -m nomad.cli dev toolkit-metadata > gui/src/toolkitMetadata.json python -m nomad.cli dev units > gui/src/unitsData.js -python -m nomad.cli dev parser-metadata > gui/src/parserMetadata.json \ No newline at end of file +python -m nomad.cli dev parser-metadata > gui/src/parserMetadata.json +cp dependencies/nomad-remote-tools-hub/tools.json gui/src/northTools.json \ No newline at end of file diff --git a/gui/.gitignore b/gui/.gitignore index 38049dcc5bed9444ede700201dd4dbff18a626ec..016538a7073425af9fbc0531ca0b4ef0dd77ae8e 100644 --- a/gui/.gitignore +++ b/gui/.gitignore @@ -14,6 +14,11 @@ public/metainfo/ public/meta.json src/toolkitMetadata.json +src/northTools.json +src/metainfo.json +src/searchQuantities.json +src/unitsData.js +src/parserMetadata.json # misc .DS_Store diff --git a/gui/public/jupyter_logo.svg b/gui/public/jupyter_logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab255087431725b5ae37c0fe279a6572f1064252 --- /dev/null +++ b/gui/public/jupyter_logo.svg @@ -0,0 +1,90 @@ +<svg width="44" height="51" viewBox="0 0 44 51" version="2.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:figma="http://www.figma.com/figma/ns"> +<title>Group.svg</title> +<desc>Created using Figma 0.90</desc> +<g id="Canvas" transform="translate(-1640 -2453)" figma:type="canvas"> +<g id="Group" style="mix-blend-mode:normal;" figma:type="group"> +<g id="Group" style="mix-blend-mode:normal;" figma:type="group"> +<g id="Group" style="mix-blend-mode:normal;" figma:type="group"> +<g id="g" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path9 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path0_fill" transform="translate(1640.54 2474.36)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path10 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path1_fill" transform="translate(1645.68 2474.37)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path11 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path2_fill" transform="translate(1653.39 2474.26)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path12 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path3_fill" transform="translate(1660.43 2474.39)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path13 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path4_fill" transform="translate(1667.55 2472.54)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path14 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path5_fill" transform="translate(1672.47 2474.29)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path15 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path6_fill" transform="translate(1679.98 2474.24)" fill="#4E4E4E" style="mix-blend-mode:normal;"/> +</g> +</g> +</g> +</g> +<g id="g" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path16 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path7_fill" transform="translate(1673.48 2453.69)" fill="#767677" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path17 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path8_fill" transform="translate(1643.21 2484.27)" fill="#F37726" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path18 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path9_fill" transform="translate(1643.21 2457.88)" fill="#F37726" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path19 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path10_fill" transform="translate(1643.28 2496.09)" fill="#9E9E9E" style="mix-blend-mode:normal;"/> +</g> +</g> +<g id="path" style="mix-blend-mode:normal;" figma:type="group"> +<g id="path20 fill" style="mix-blend-mode:normal;" figma:type="vector"> +<use xlink:href="#path11_fill" transform="translate(1641.87 2458.43)" fill="#616262" style="mix-blend-mode:normal;"/> +</g> +</g> +</g> +</g> +</g> +</g> +<defs> +<path id="path0_fill" d="M 1.74498 5.47533C 1.74498 7.03335 1.62034 7.54082 1.29983 7.91474C 0.943119 8.23595 0.480024 8.41358 0 8.41331L 0.124642 9.3036C 0.86884 9.31366 1.59095 9.05078 2.15452 8.56466C 2.45775 8.19487 2.6834 7.76781 2.818 7.30893C 2.95261 6.85005 2.99341 6.36876 2.93798 5.89377L 2.93798 0L 1.74498 0L 1.74498 5.43972L 1.74498 5.47533Z"/> +<path id="path1_fill" d="M 5.50204 4.76309C 5.50204 5.43081 5.50204 6.02731 5.55545 6.54368L 4.496 6.54368L 4.42478 5.48423C 4.20318 5.85909 3.88627 6.16858 3.50628 6.38125C 3.12628 6.59392 2.69675 6.70219 2.26135 6.69503C 1.22861 6.69503 0 6.13415 0 3.84608L 0 0.0445149L 1.193 0.0445149L 1.193 3.6057C 1.193 4.84322 1.57583 5.67119 2.65309 5.67119C 2.87472 5.67358 3.09459 5.63168 3.29982 5.54796C 3.50505 5.46424 3.69149 5.34039 3.84822 5.18366C 4.00494 5.02694 4.1288 4.84049 4.21252 4.63527C 4.29623 4.43004 4.33813 4.21016 4.33575 3.98853L 4.33575 0L 5.52874 0L 5.52874 4.72748L 5.50204 4.76309Z"/> +<path id="path2_fill" d="M 0.0534178 2.27264C 0.0534178 1.44466 0.0534178 0.768036 0 0.153731L 1.06836 0.153731L 1.12177 1.2666C 1.3598 0.864535 1.70247 0.534594 2.11325 0.311954C 2.52404 0.0893145 2.98754 -0.0176786 3.45435 0.00238095C 5.03908 0.00238095 6.23208 1.32892 6.23208 3.30538C 6.23208 5.63796 4.7987 6.79535 3.24958 6.79535C 2.85309 6.81304 2.45874 6.7281 2.10469 6.54874C 1.75064 6.36937 1.44888 6.10166 1.22861 5.77151L 1.22861 5.77151L 1.22861 9.33269L 0.0534178 9.33269L 0.0534178 2.29935L 0.0534178 2.27264ZM 1.22861 4.00872C 1.23184 4.17026 1.24972 4.33117 1.28203 4.48948C 1.38304 4.88479 1.61299 5.23513 1.93548 5.48506C 2.25798 5.735 2.65461 5.87026 3.06262 5.86944C 4.31794 5.86944 5.05689 4.8456 5.05689 3.3588C 5.05689 2.05897 4.36246 0.946096 3.10714 0.946096C 2.61036 0.986777 2.14548 1.20726 1.79965 1.5662C 1.45382 1.92514 1.25079 2.3979 1.22861 2.89585L 1.22861 4.00872Z"/> +<path id="path3_fill" d="M 1.31764 0.0178059L 2.75102 3.85499C 2.90237 4.28233 3.06262 4.7987 3.16946 5.18153C 3.2941 4.7898 3.42764 4.29123 3.5879 3.82828L 4.88773 0.0178059L 6.14305 0.0178059L 4.36246 4.64735C 3.47216 6.87309 2.92908 8.02158 2.11 8.71601C 1.69745 9.09283 1.19448 9.35658 0.649917 9.48166L 0.356119 8.48453C 0.736886 8.35942 1.09038 8.16304 1.39777 7.90584C 1.8321 7.55188 2.17678 7.10044 2.4038 6.5882C 2.45239 6.49949 2.48551 6.40314 2.50173 6.3033C 2.49161 6.19586 2.46457 6.0907 2.42161 5.9917L 0 0L 1.29983 0L 1.31764 0.0178059Z"/> +<path id="path4_fill" d="M 2.19013 0L 2.19013 1.86962L 3.8995 1.86962L 3.8995 2.75992L 2.19013 2.75992L 2.19013 6.26769C 2.19013 7.06896 2.42161 7.53191 3.08043 7.53191C 3.31442 7.53574 3.54789 7.5088 3.77486 7.45179L 3.82828 8.34208C 3.48794 8.45999 3.12881 8.51431 2.76882 8.50234C 2.53042 8.51726 2.29161 8.48043 2.06878 8.39437C 1.84595 8.30831 1.64438 8.17506 1.47789 8.00377C 1.11525 7.51873 0.949826 6.91431 1.01494 6.31221L 1.01494 2.75102L 0 2.75102L 0 1.86072L 1.03274 1.86072L 1.03274 0.275992L 2.19013 0Z"/> +<path id="path5_fill" d="M 1.17716 3.57899C 1.153 3.88093 1.19468 4.18451 1.29933 4.46876C 1.40398 4.75301 1.5691 5.01114 1.78329 5.22532C 1.99747 5.43951 2.2556 5.60463 2.53985 5.70928C 2.8241 5.81393 3.12768 5.85561 3.42962 5.83145C 4.04033 5.84511 4.64706 5.72983 5.21021 5.49313L 5.41498 6.38343C 4.72393 6.66809 3.98085 6.80458 3.23375 6.78406C 2.79821 6.81388 2.36138 6.74914 1.95322 6.59427C 1.54505 6.43941 1.17522 6.19809 0.869071 5.88688C 0.562928 5.57566 0.327723 5.2019 0.179591 4.79125C 0.0314584 4.38059 -0.0260962 3.94276 0.0108748 3.50777C 0.0108748 1.54912 1.17716 0 3.0824 0C 5.21911 0 5.75329 1.86962 5.75329 3.06262C 5.76471 3.24644 5.76471 3.43079 5.75329 3.61461L 1.15046 3.61461L 1.17716 3.57899ZM 4.66713 2.6887C 4.70149 2.45067 4.68443 2.20805 4.61709 1.97718C 4.54976 1.74631 4.43372 1.53255 4.2768 1.35031C 4.11987 1.16808 3.92571 1.0216 3.70739 0.920744C 3.48907 0.81989 3.25166 0.767006 3.01118 0.765656C 2.52201 0.801064 2.06371 1.01788 1.72609 1.37362C 1.38847 1.72935 1.19588 2.19835 1.18607 2.6887L 4.66713 2.6887Z"/> +<path id="path6_fill" d="M 0.0534178 2.19228C 0.0534178 1.42663 0.0534178 0.767806 0 0.162404L 1.06836 0.162404L 1.06836 1.43553L 1.12177 1.43553C 1.23391 1.04259 1.4656 0.694314 1.78468 0.439049C 2.10376 0.183783 2.4944 0.034196 2.90237 0.0110538C 3.01466 -0.00368459 3.12839 -0.00368459 3.24068 0.0110538L 3.24068 1.12393C 3.10462 1.10817 2.9672 1.10817 2.83114 1.12393C 2.427 1.13958 2.04237 1.30182 1.7491 1.58035C 1.45583 1.85887 1.27398 2.23462 1.23751 2.63743C 1.20422 2.8196 1.18635 3.00425 1.1841 3.18941L 1.1841 6.65267L 0.00890297 6.65267L 0.00890297 2.20118L 0.0534178 2.19228Z"/> +<path id="path7_fill" d="M 6.03059 2.83565C 6.06715 3.43376 5.92485 4.02921 5.6218 4.54615C 5.31875 5.0631 4.86869 5.47813 4.32893 5.73839C 3.78917 5.99864 3.18416 6.09233 2.59097 6.00753C 1.99778 5.92272 1.44326 5.66326 0.998048 5.26219C 0.552837 4.86113 0.23709 4.33661 0.0910307 3.75546C -0.0550287 3.17431 -0.0247891 2.56283 0.177897 1.99893C 0.380583 1.43503 0.746541 0.944221 1.22915 0.589037C 1.71176 0.233853 2.28918 0.0303686 2.88784 0.00450543C 3.28035 -0.0170932 3.67326 0.0391144 4.04396 0.169896C 4.41467 0.300677 4.75587 0.503453 5.04794 0.766561C 5.34 1.02967 5.57718 1.34792 5.74582 1.70301C 5.91446 2.0581 6.01124 2.44303 6.03059 2.83565L 6.03059 2.83565Z"/> +<path id="path8_fill" d="M 18.6962 7.12238C 10.6836 7.12238 3.64131 4.24672 0 0C 1.41284 3.82041 3.96215 7.1163 7.30479 9.44404C 10.6474 11.7718 14.623 13.0196 18.6962 13.0196C 22.7695 13.0196 26.745 11.7718 30.0877 9.44404C 33.4303 7.1163 35.9796 3.82041 37.3925 4.0486e-13C 33.7601 4.24672 26.7445 7.12238 18.6962 7.12238Z"/> +<path id="path9_fill" d="M 18.6962 5.89725C 26.7089 5.89725 33.7512 8.77291 37.3925 13.0196C 35.9796 9.19922 33.4303 5.90333 30.0877 3.57559C 26.745 1.24785 22.7695 4.0486e-13 18.6962 0C 14.623 4.0486e-13 10.6474 1.24785 7.30479 3.57559C 3.96215 5.90333 1.41284 9.19922 0 13.0196C 3.64131 8.76401 10.648 5.89725 18.6962 5.89725Z"/> +<path id="path10_fill" d="M 7.59576 3.56656C 7.64276 4.31992 7.46442 5.07022 7.08347 5.72186C 6.70251 6.3735 6.13619 6.89698 5.45666 7.22561C 4.77713 7.55424 4.01515 7.67314 3.26781 7.56716C 2.52046 7.46117 1.82158 7.13511 1.26021 6.63051C 0.698839 6.12591 0.300394 5.46561 0.115637 4.73375C -0.0691191 4.00188 -0.0318219 3.23159 0.222777 2.52099C 0.477376 1.8104 0.93775 1.19169 1.54524 0.743685C 2.15274 0.295678 2.87985 0.0386595 3.63394 0.00537589C 4.12793 -0.0210471 4.62229 0.0501173 5.08878 0.214803C 5.55526 0.37949 5.98473 0.63447 6.35264 0.965179C 6.72055 1.29589 7.01971 1.69584 7.233 2.1422C 7.4463 2.58855 7.56957 3.07256 7.59576 3.56656L 7.59576 3.56656Z"/> +<path id="path11_fill" d="M 2.25061 4.37943C 1.81886 4.39135 1.39322 4.27535 1.02722 4.04602C 0.661224 3.81668 0.371206 3.48424 0.193641 3.09052C 0.0160762 2.69679 -0.0411078 2.25935 0.0292804 1.83321C 0.0996686 1.40707 0.294486 1.01125 0.589233 0.695542C 0.883981 0.37983 1.2655 0.158316 1.68581 0.0588577C 2.10611 -0.0406005 2.54644 -0.0135622 2.95143 0.136572C 3.35641 0.286707 3.70796 0.553234 3.96186 0.902636C 4.21577 1.25204 4.3607 1.66872 4.37842 2.10027C 4.39529 2.6838 4.18131 3.25044 3.78293 3.67715C 3.38455 4.10387 2.83392 4.35623 2.25061 4.37943Z"/> +</defs> +</svg> diff --git a/gui/src/components/datatable/Datatable.js b/gui/src/components/datatable/Datatable.js index 0fd430ae2db9859342ae1e23795e1daabe18fb5b..e1fd86452f5b5b113aa5e1886cd250a0ab77c406 100644 --- a/gui/src/components/datatable/Datatable.js +++ b/gui/src/components/datatable/Datatable.js @@ -229,7 +229,8 @@ const DatatableHeader = React.memo(function DatatableHeader({actions}) { onSelectedChanged, shownColumns, pagination, - onPaginationChanged + onPaginationChanged, + multiple } = useDatatableContext() const columns = shownColumns const {order, order_by} = pagination @@ -256,13 +257,13 @@ const DatatableHeader = React.memo(function DatatableHeader({actions}) { return <TableHead> <TableRow> - {withSelectionFeature && <TableCell padding="checkbox" classes={{stickyHeader: classes.stickyHeader}}> - <Checkbox + <TableCell padding="checkbox" classes={{stickyHeader: classes.stickyHeader}}> + {(withSelectionFeature && multiple) && <Checkbox indeterminate={selected.length > 0 && selected !== 'all'} checked={selected === 'all'} onChange={handleSelectAllChanged} - /> - </TableCell>} + />} + </TableCell> {columns.map(column => ( <TableCell classes={{stickyHeader: classes.stickyHeader}} @@ -721,6 +722,8 @@ Datatable.propTypes = { PropTypes.oneOf(['all']), PropTypes.arrayOf(PropTypes.object) ]), + /** Whether multiple values can be selected or not */ + multiple: PropTypes.bool, /** Optional callback for selection changes. Takes either "all" or new array of * selected row objects as parameter. */ onSelectedChanged: PropTypes.func, @@ -730,3 +733,7 @@ Datatable.propTypes = { PropTypes.node ]) } + +Datatable.defaultProps = { + multiple: true +} diff --git a/gui/src/components/nav/Routes.js b/gui/src/components/nav/Routes.js index d229ef1edcfae0a9d690e4110ece33dcaa4b5ea7..29f10a3e527d06e97541516941d47e0377fa807e 100644 --- a/gui/src/components/nav/Routes.js +++ b/gui/src/components/nav/Routes.js @@ -33,6 +33,7 @@ import UserdataPage, { help as userdataHelp } from '../UserdataPage' import APIs from '../APIs' import SearchPageEntries, {help as searchEntriesHelp} from '../search/SearchPageEntries' import SearchPageMaterials, {help as searchMaterialsHelp} from '../search/SearchPageMaterials' +import NORTHMainPage, {help as NORTHHelp} from '../north/NORTHMainPage' import { aitoolkitEnabled, appBase, oasis, encyclopediaBase } from '../../config' import EntryQuery from '../entry/EntryQuery' import ResolvePID from '../entry/ResolvePID' @@ -286,7 +287,19 @@ export const routes = [ path: 'reproduce', title: 'Artificial Intelligence Toolkit', component: ReproducePage - } + }, + { + path: 'north', + menu: 'NOMAD Remote Tools Hub', + tooltip: 'Browse the list of available remote tools.', + breadcrumb: 'NOMAD Remote Tools Hub', + help: { + title: 'NOMAD Remote Tools help page', + content: NORTHHelp + }, + component: NORTHMainPage + }, + toolkitRoute ] }, { diff --git a/gui/src/components/north/NORTHLaunchButton.js b/gui/src/components/north/NORTHLaunchButton.js new file mode 100644 index 0000000000000000000000000000000000000000..191f1609090604ae189118212f4428ac0ec82ce0 --- /dev/null +++ b/gui/src/components/north/NORTHLaunchButton.js @@ -0,0 +1,47 @@ +/* eslint-disable quotes */ +/* + * Copyright The NOMAD Authors. + * + * This file is part of NOMAD. See https://nomad-lab.eu for further info. + * + * 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. + */ +import React from 'react' +import PropTypes from 'prop-types' +import { Button } from '@material-ui/core' +import { northBase } from '../../config' + +const NORTHLaunchButton = React.memo(({ + name, + path, + disabled, + children +}) => { + return <Button + component="a" + href={`${northBase}/user-redirect/${name}/${path || ''}`} + target="_blank" + color="primary" + variant="contained" + disabled={disabled} + >{children}</Button> +}) + +NORTHLaunchButton.propTypes = { + name: PropTypes.string.isRequired, // The unique identitifier for this tool + path: PropTypes.string, // Path to add to container url + disabled: PropTypes.bool, // Whether the button is disabled + children: PropTypes.node +} + +export default NORTHLaunchButton diff --git a/gui/src/components/north/NORTHMainPage.js b/gui/src/components/north/NORTHMainPage.js new file mode 100644 index 0000000000000000000000000000000000000000..8879b04076226423b6c4d2113f93f90e7e6bd087 --- /dev/null +++ b/gui/src/components/north/NORTHMainPage.js @@ -0,0 +1,194 @@ +/* eslint-disable quotes */ +/* + * Copyright The NOMAD Authors. + * + * This file is part of NOMAD. See https://nomad-lab.eu for further info. + * + * 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. + */ +import React, { useState, useEffect, useCallback } from 'react' +import { + Grid, + List, + Paper, + Divider, + Step, + StepLabel, + Stepper, + makeStyles +} from '@material-ui/core' +import Alert from '@material-ui/lab/Alert' +import Page from '../Page' +import { useApi, withLoginRequired } from '../api' +import { useErrors } from '../errors' +import NORTHToolItem from './NORTHToolItem' +import { + addColumnDefaults, + combinePagination, + Datatable, + DatatableLoadMorePagination, + DatatableTable +} from '../datatable/Datatable' +import * as _tools from '../../northTools.json'; + +export const help = ` +The NOMAD Remote Tools Hub (NORTH) provides access to tools which you can use to +work remotely on unpublished data stored within NOMAD. +` + +// Datatable column setup +const columns = [ + {key: 'upload_id'}, + {key: 'upload_create_time'}, + {key: 'upload_name'} +] +addColumnDefaults(columns, {align: 'left'}) + +/** + * Landing page for the NOMAD Remote Tools Hub. + */ + +const useStyles = makeStyles(theme => ({ + stepper: { + padding: 0, + backgroundColor: 'inherit' + }, + stepContent: { + marginTop: theme.spacing(2), + marginLeft: theme.spacing(3) + } +})) +const NORTHMainPage = React.memo(() => { + const styles = useStyles() + const tools = useTools() + // const instances = useInstances() + const {api} = useApi() + const errors = useErrors() + const [uploads, setUploads] = useState(null) + const [selected, setSelected] = useState([]) + const [pagination, setPagination] = useState({ + page_size: 10, + page: 1, + order_by: 'upload_create_time', + order: 'desc' + }) + const canLaunch = selected.length > 0 + + console.log('###', tools) + + // Fetch the list of unpublished uploads. + useEffect(() => { + const {page_size, page, order_by, order} = pagination + api.get(`/uploads?is_published=false&page_size=${page_size}&page=${page}&order_by=${order_by}&order=${order}`) + .then(data => setUploads(data)) + .catch(errors.raiseError) + }, [pagination, setUploads, errors, api]) + + // Only one upload can be selected at this time + const handleSelect = useCallback((callBack) => { + const selected = callBack([]) + setSelected(old => { + if (old[0]?.upload_id === selected[0]?.upload_id) { + return [] + } + return selected + }) + }, []) + + return (uploads) + ? <Page limitedWidth> + <Grid container spacing={1}> + <Grid item xs={8}> + <Stepper className={styles.stepper} orientation="horizontal"> + <Step active> + <StepLabel icon={1}>Select an upload</StepLabel> + </Step> + </Stepper> + <Paper className={styles.stepContent}> + {uploads.data.length > 0 + ? <Datatable + multiple={false} + selected={selected} + onSelectedChanged={handleSelect} + columns={columns} + selectedColumns={columns.map(column => column.key)} + data={uploads.data || []} + pagination={combinePagination(pagination, uploads.pagination)} + onPaginationChanged={setPagination} + > + <DatatableTable> + <DatatableLoadMorePagination /> + </DatatableTable> + </Datatable> + : <Alert severity="info">No uploads available. Notice that you can only work on unpublished uploads.</Alert> + } + </Paper> + </Grid> + <Grid item xs={4}> + <Stepper className={styles.stepper} orientation="horizontal"> + <Step active={canLaunch}> + <StepLabel icon={2}>Launch a tool</StepLabel> + </Step> + </Stepper> + <Paper className={styles.stepContent}> + <List> + {Object.keys(tools).map(key => ({name: key, title: key, ...tools[key]})).map((tool, index) => ( + <div key={tool.name}> + <NORTHToolItem + {...tool} + // running={instances ? tool.name in instances : false} + disabled={!canLaunch} + uploadId={selected[0] && selected[0].upload_id} + /> + {index !== Object.keys(tools).length - 1 && <Divider/>} + </div> + ))} + </List> + </Paper> + </Grid> + </Grid> + </Page> + : null +}) + +export default withLoginRequired(NORTHMainPage) + + +/** + * Hook for loading the list of running instances from the NORTH API. +*/ +// TODO use Jupyterhub for this +export function useInstances() { + const [instances, setInstances] = useState() + const { api } = useApi() + + useEffect(() => { + api.northInstances() + .then(data => { + const instances = {} + data.forEach(instance => { + instances[instance.name] = {...instance} + }) + setInstances(instances) + }) + }, [api]) + + return instances +} + +/** + * Hook for loading the list of available tools from the NORTH API. +*/ +export function useTools() { + return _tools.default +} diff --git a/gui/src/components/north/NORTHToolItem.js b/gui/src/components/north/NORTHToolItem.js new file mode 100644 index 0000000000000000000000000000000000000000..4caff311197969ee9d2e5466f48bda8f7591058f --- /dev/null +++ b/gui/src/components/north/NORTHToolItem.js @@ -0,0 +1,100 @@ +/* + * Copyright The NOMAD Authors. + * + * This file is part of NOMAD. See https://nomad-lab.eu for further info. + * + * 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. + */ +import React from 'react' +import PropTypes from 'prop-types' +import { makeStyles } from '@material-ui/core/styles' +import { + CardHeader, + CardContent, + Typography +} from '@material-ui/core' +import AssessmentIcon from '@material-ui/icons/Assessment' +import Icon from '@material-ui/core/Icon' +import NORTHLaunchButton from './NORTHLaunchButton' + +/** + * Remote tool item. Can be shown within a list or as a standalone component. + */ +const useStyles = makeStyles(theme => ({ + root: {}, + imageIcon: { + height: '100%' + }, + iconRoot: { + textAlign: 'center', + height: '3rem', + width: '3rem', + marginRight: theme.spacing(2) + }, + action: { + marginTop: 0, + marginRight: 0 + } +})) + +const NORTHToolItem = React.memo(({ + name, + title, + version, + description, + path_prefix, + icon, + running, + disableDescription, + disableActions, + uploadId +}) => { + const styles = useStyles() + + const path = path_prefix && uploadId ? `${path_prefix}/uploads/${uploadId}` : null + + return <div> + <CardHeader + avatar={icon + ? <Icon classes={{root: styles.iconRoot}}> + <img className={styles.imageIcon} src={`../${icon}`} alt="icon"/> + </Icon> + : <AssessmentIcon classes={{root: styles.iconRoot}}/>} + title={title} + subheader={version} + action={!disableActions && <NORTHLaunchButton + name={name} + path={path} + >Launch</NORTHLaunchButton>} + classes={{action: styles.action}} + /> + {(!disableDescription && description) && <CardContent> + <Typography variant="body2" component="p">{description}</Typography> + </CardContent>} + </div> +}) + +NORTHToolItem.propTypes = { + name: PropTypes.string.isRequired, // The unique identitifier for this tool + title: PropTypes.string.isRequired, // The displayed name of this tool + version: PropTypes.string, // Version number if available + description: PropTypes.string, // Version number if available + path_prefix: PropTypes.string, // A path prefix. With path prefix selected upload or file will be added to path. + icon: PropTypes.string, // Path to tool icon if available, relative to gui/public + running: PropTypes.bool, // Whether the tool is running + disableDescription: PropTypes.bool, // Whether to hide the description + disableActions: PropTypes.bool, // Whether to hide actions for this tool + uploadId: PropTypes.string // Upload id +} + +export default NORTHToolItem diff --git a/gui/src/unitsData.js b/gui/src/unitsData.js deleted file mode 100644 index c37e376f91c3f74d611ec4f5fa01b58d689f7314..0000000000000000000000000000000000000000 --- a/gui/src/unitsData.js +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Copyright The NOMAD Authors. - * - * This file is part of NOMAD. See https://nomad-lab.eu for further info. - * - * 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. - */ -// Generated by NOMAD CLI. Do not edit manually. -export const unitMap = { - second: { - dimension: 'time', - label: 'Second', - abbreviation: 's' - }, - atomic_unit_of_time: { - dimension: 'time', - label: 'Atomic unit of time', - abbreviation: 'a_u_time' - }, - meter: { - dimension: 'length', - label: 'Meter', - abbreviation: 'm' - }, - bohr: { - dimension: 'length', - label: 'Bohr', - abbreviation: 'bohr' - }, - angstrom: { - dimension: 'length', - label: '\u00c5ngstrom', - abbreviation: '\u00c5' - }, - kilogram: { - dimension: 'mass', - label: 'Kilogram', - abbreviation: 'kg' - }, - electron_mass: { - dimension: 'mass', - label: 'Electron mass', - abbreviation: 'm\u2091' - }, - unified_atomic_mass_unit: { - dimension: 'mass', - label: 'Unified atomic mass unit', - abbreviation: 'u' - }, - ampere: { - dimension: 'current', - label: 'Ampere', - abbreviation: 'A' - }, - atomic_unit_of_current: { - dimension: 'current', - label: 'Atomic unit of current', - abbreviation: 'a_u_current' - }, - mole: { - dimension: 'substance', - label: 'Mole', - abbreviation: 'mole' - }, - candela: { - dimension: 'luminosity', - label: 'Candela', - abbreviation: 'cd' - }, - kelvin: { - dimension: 'temperature', - label: 'Kelvin', - abbreviation: 'K' - }, - celsius: { - dimension: 'temperature', - label: 'Celsius', - abbreviation: '\u00b0C' - }, - fahrenheit: { - dimension: 'temperature', - label: 'Fahrenheit', - abbreviation: '\u00b0F' - }, - atomic_unit_of_temperature: { - dimension: 'temperature', - label: 'Atomic unit of temperature', - abbreviation: 'a_u_temperature' - }, - newton: { - dimension: 'force', - label: 'Newton', - abbreviation: 'N' - }, - atomic_unit_of_force: { - dimension: 'force', - label: 'Atomic unit of force', - abbreviation: 'a_u_force' - }, - pascal: { - dimension: 'pressure', - label: 'Pascal', - abbreviation: 'Pa' - }, - gigapascal: { - dimension: 'pressure', - label: 'Gigapascal', - abbreviation: 'GPa' - }, - atomic_unit_of_pressure: { - dimension: 'pressure', - label: 'Atomic unit of pressure', - abbreviation: 'a_u_pressure' - }, - joule: { - dimension: 'energy', - label: 'Joule', - abbreviation: 'J' - }, - electron_volt: { - dimension: 'energy', - label: 'Electron volt', - abbreviation: 'eV' - }, - hartree: { - dimension: 'energy', - label: 'Hartree', - abbreviation: 'Ha' - }, - watt: { - dimension: 'power', - label: 'Watt', - abbreviation: 'W' - }, - hertz: { - dimension: 'frequency', - label: 'Hertz', - abbreviation: 'Hz' - }, - volt: { - dimension: 'electric_potential', - label: 'Volt', - abbreviation: 'V' - }, - farad: { - dimension: 'capacitance', - label: 'Farad', - abbreviation: 'F' - }, - coulomb: { - dimension: 'charge', - label: 'Coulomb', - abbreviation: 'C' - }, - elementary_charge: { - dimension: 'charge', - label: 'Elementary charge', - abbreviation: 'e' - }, - tesla: { - dimension: 'magnetic_field', - label: 'Tesla', - abbreviation: 'T' - }, - weber: { - dimension: 'magnetic_flux', - label: 'Weber', - abbreviation: 'Wb' - }, - bohr_magneton: { - dimension: 'magnetic_dipole', - label: 'Bohr magneton', - abbreviation: 'Bm' - }, - henry: { - dimension: 'inductance', - label: 'Henry', - abbreviation: 'H' - }, - radian: { - dimension: 'angle', - label: 'Radian', - abbreviation: 'rad' - }, - degree: { - dimension: 'angle', - label: 'Degree', - abbreviation: '\u00b0' - }, - dimensionless: { - dimension: 'dimensionless', - label: 'Dimensionless', - abbreviation: '' - } -} -export const conversionMap = { - time: { - units: [ - 'second', - 'atomic_unit_of_time' - ], - multipliers: { - second: { - second: 1, - atomic_unit_of_time: 4.134137333518244e+16 - }, - atomic_unit_of_time: { - second: 2.4188843265856806e-17, - atomic_unit_of_time: 1 - } - } - }, - length: { - units: [ - 'meter', - 'bohr', - 'angstrom' - ], - multipliers: { - meter: { - meter: 1, - bohr: 18897261246.22279, - angstrom: 10000000000.0 - }, - bohr: { - meter: 5.2917721090397754e-11, - bohr: 1, - angstrom: 0.5291772109039775 - }, - angstrom: { - meter: 1e-10, - bohr: 1.8897261246222794, - angstrom: 1 - } - } - }, - mass: { - units: [ - 'kilogram', - 'electron_mass', - 'unified_atomic_mass_unit' - ], - multipliers: { - kilogram: { - kilogram: 1, - electron_mass: 1.0977691057577633e+30, - unified_atomic_mass_unit: 6.022140762081123e+26 - }, - electron_mass: { - kilogram: 9.1093837015e-31, - electron_mass: 1, - unified_atomic_mass_unit: 0.0005485799090624057 - }, - unified_atomic_mass_unit: { - kilogram: 1.6605390666e-27, - electron_mass: 1822.8884862173131, - unified_atomic_mass_unit: 1 - } - } - }, - current: { - units: [ - 'ampere', - 'atomic_unit_of_current' - ], - multipliers: { - ampere: { - ampere: 1, - atomic_unit_of_current: 150.97488474455437 - }, - atomic_unit_of_current: { - ampere: 0.006623618237509995, - atomic_unit_of_current: 1 - } - } - }, - substance: { - units: [ - 'mole' - ], - multipliers: { - mole: { - mole: 1 - } - } - }, - luminosity: { - units: [ - 'candela' - ], - multipliers: { - candela: { - candela: 1 - } - } - }, - temperature: { - units: [ - 'kelvin', - 'celsius', - 'fahrenheit', - 'atomic_unit_of_temperature' - ], - multipliers: { - kelvin: { - kelvin: 1, - celsius: 1.0, - fahrenheit: 1.7999999999999998, - atomic_unit_of_temperature: 3.1668115634555572e-06 - }, - celsius: { - kelvin: 1, - celsius: 1, - fahrenheit: 1.7999999999999998, - atomic_unit_of_temperature: 3.1668115634555572e-06 - }, - fahrenheit: { - kelvin: 0.5555555555555556, - celsius: 0.5555555555555556, - fahrenheit: 1, - atomic_unit_of_temperature: 1.7593397574753097e-06 - }, - atomic_unit_of_temperature: { - kelvin: 315775.0248040719, - celsius: 315775.0248040719, - fahrenheit: 568395.0446473294, - atomic_unit_of_temperature: 1 - } - }, - constants: { - kelvin: { - celsius: -273.15, - fahrenheit: -459.67 - }, - celsius: { - celsius: -273.15, - fahrenheit: -459.67 - }, - fahrenheit: { - celsius: -273.15, - fahrenheit: -459.67 - }, - atomic_unit_of_temperature: { - celsius: -273.15, - fahrenheit: -459.67 - } - } - }, - force: { - units: [ - 'newton', - 'atomic_unit_of_force' - ], - multipliers: { - newton: { - newton: 1, - atomic_unit_of_force: 12137802.66097955 - }, - atomic_unit_of_force: { - newton: 8.238723498238991e-08, - atomic_unit_of_force: 1 - } - } - }, - pressure: { - units: [ - 'pascal', - 'gigapascal', - 'atomic_unit_of_pressure' - ], - multipliers: { - pascal: { - pascal: 1, - gigapascal: 1.0000000000000003e-09, - atomic_unit_of_pressure: 3.3989309217619455e-14 - }, - gigapascal: { - pascal: 1000000000.0, - gigapascal: 1, - atomic_unit_of_pressure: 3.398930921761947e-05 - }, - atomic_unit_of_pressure: { - pascal: 29421015696359.54, - gigapascal: 29421.015696359544, - atomic_unit_of_pressure: 1 - } - } - }, - energy: { - units: [ - 'joule', - 'electron_volt', - 'hartree' - ], - multipliers: { - joule: { - joule: 1, - electron_volt: 6.241509074460763e+18, - hartree: 2.2937122783962883e+17 - }, - electron_volt: { - joule: 1.602176634e-19, - electron_volt: 1, - hartree: 0.03674932217565436 - }, - hartree: { - joule: 4.35974472220717e-18, - electron_volt: 27.21138624598847, - hartree: 1 - } - } - }, - power: { - units: [ - 'watt' - ], - multipliers: { - watt: { - watt: 1 - } - } - }, - frequency: { - units: [ - 'hertz' - ], - multipliers: { - hertz: { - hertz: 1 - } - } - }, - electric_potential: { - units: [ - 'volt' - ], - multipliers: { - volt: { - volt: 1 - } - } - }, - capacitance: { - units: [ - 'farad' - ], - multipliers: { - farad: { - farad: 1 - } - } - }, - charge: { - units: [ - 'coulomb', - 'elementary_charge' - ], - multipliers: { - coulomb: { - coulomb: 1, - elementary_charge: 6.241509074460763e+18 - }, - elementary_charge: { - coulomb: 1.602176634e-19, - elementary_charge: 1 - } - } - }, - magnetic_field: { - units: [ - 'tesla' - ], - multipliers: { - tesla: { - tesla: 1 - } - } - }, - magnetic_flux: { - units: [ - 'weber' - ], - multipliers: { - weber: { - weber: 1 - } - } - }, - magnetic_dipole: { - units: [ - 'bohr_magneton' - ], - multipliers: { - bohr_magneton: { - bohr_magneton: 1 - } - } - }, - inductance: { - dimension: 'inductance', - units: [ - 'henry' - ], - multipliers: { - henry: { - henry: 1 - } - } - }, - angle: { - dimension: 'angle', - units: [ - 'radian', - 'degree' - ], - multipliers: { - radian: { - radian: 1, - degree: 57.29577951308232 - }, - degree: { - radian: 0.017453292519943295, - degree: 1 - } - } - }, - dimensionless: { - dimension: 'dimensionless', - units: [ - 'dimensionless' - ], - multipliers: { - dimensionless: { - dimensionless: 1 - } - } - } -} -export const unitSystems = { - SI: { - label: 'SI', - description: 'International System of Units (SI)', - units: { - time: 'second', - length: 'meter', - mass: 'kilogram', - current: 'ampere', - substance: 'mole', - luminosity: 'candela', - temperature: 'kelvin', - force: 'newton', - pressure: 'pascal', - energy: 'joule', - power: 'watt', - frequency: 'hertz', - electric_potential: 'volt', - charge: 'coulomb', - angle: 'radian' - } - }, - AU: { - label: 'Atomic units', - description: 'Hartree atomic units', - units: { - time: 'atomic_unit_of_time', - length: 'bohr', - mass: 'electron_mass', - current: 'atomic_unit_of_current', - temperature: 'atomic_unit_of_temperature', - force: 'atomic_unit_of_force', - energy: 'hartree', - pressure: 'atomic_unit_of_pressure', - angle: 'radian' - } - } -} diff --git a/nomad/jupyterhub_config.py b/nomad/jupyterhub_config.py index cda6140e3c9e704a5b11bfa777a3ace0a8f56b11..8fe4f953bc48f1732bb5ff3fd12ce78cd8a83e3b 100644 --- a/nomad/jupyterhub_config.py +++ b/nomad/jupyterhub_config.py @@ -29,6 +29,7 @@ import os import os.path import requests import pathlib +import json from nomad import config @@ -175,25 +176,25 @@ if config.north.hub_ip: c.JupyterHub.hub_ip = config.north.hub_ip -def configure_toolkit(spawner: DockerSpawner): - spawner.image = 'gitlab-registry.mpcdf.mpg.de/nomad-lab/analytics:latest' - +def configure_default(spawner: DockerSpawner): + spawner.image = 'jupyter/base-notebook' -def configure_webtop(spawner: DockerSpawner): - spawner.image = 'gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/webtop' - spawner.cmd = ["/bin/sh", "-c", "sleep infinity"] +def create_configure_from_tool_json(tool_json): + def configure(spawner: DockerSpawner): + spawner.image = tool_json['image'] -def configure_test(spawner: DockerSpawner): - spawner.image = 'jyp_test' + return configure -def configure_default(spawner: DockerSpawner): - spawner.image = 'jupyter/base-notebook' +tools_json_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + '../dependencies/nomad-remote-tools-hub/tools.json') +with open(tools_json_path, 'rt') as f: + tools_json = json.load(f) tools = { - 'toolkit': configure_toolkit, - 'webtop': configure_webtop, - 'test': configure_test + key: create_configure_from_tool_json(value) + for key, value in tools_json.items() } diff --git a/ops/images/jyp_test/.dockerignore b/ops/images/jyp_test/.dockerignore deleted file mode 100644 index 5171c54083337f0b87926da2e8f52abefe19d70f..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -npm-debug.log \ No newline at end of file diff --git a/ops/images/jyp_test/.gitignore b/ops/images/jyp_test/.gitignore deleted file mode 100644 index 3c3629e647f5ddf82548912e337bea9826b434af..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/ops/images/jyp_test/Dockerfile b/ops/images/jyp_test/Dockerfile deleted file mode 100644 index 1c168967fda9bc9ae2ea34301c07f07a9f366fc2..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM node:14 - -# Create app directory -WORKDIR /usr/src/app - -# Install app dependencies -# A wildcard is used to ensure both package.json AND package-lock.json are copied -# where available (npm@5+) -COPY package*.json ./ - -RUN npm install -# If you are building your code for production -# RUN npm ci --only=production - -# Bundle app source -COPY . . - -EXPOSE 8888 -CMD [ "node", "server.js" ] \ No newline at end of file diff --git a/ops/images/jyp_test/README.md b/ops/images/jyp_test/README.md deleted file mode 100644 index 5ad55953f3086cc91fb6256b9f73445d58c3b0fa..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/README.md +++ /dev/null @@ -1,9 +0,0 @@ -This is a test image for north tools authorization. - -To build: -``` -docker build -t jyp_test . -``` - -To use it, you have to adopt `/nomad/jupyterhub_config.py` to use the -`jyp_test` as an image. \ No newline at end of file diff --git a/ops/images/jyp_test/package-lock.json b/ops/images/jyp_test/package-lock.json deleted file mode 100644 index a239bf450f7b6a27ebd9cb214cb1d400f252818a..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/package-lock.json +++ /dev/null @@ -1,1163 +0,0 @@ -{ - "name": "jyp_test", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "axios": "^0.23.0", - "cookie-parser": "^1.4.5", - "express": "^4.17.1", - "express-session": "^1.17.2", - "passport": "^0.5.0", - "passport-oauth2": "^1.6.1" - } - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/axios": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.23.0.tgz", - "integrity": "sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==", - "dependencies": { - "follow-redirects": "^1.14.4" - } - }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", - "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", - "dependencies": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express-session/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express-session/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", - "dependencies": { - "mime-db": "1.50.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.0.tgz", - "integrity": "sha512-ln+ue5YaNDS+fes6O5PCzXKSseY5u8MYhX9H5Co4s+HfYI5oqvnHKoOORLYDUPh+8tHvrxugF2GFcUA1Q1Gqfg==", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-oauth2": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz", - "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==", - "dependencies": { - "base64url": "3.x.x", - "oauth": "0.9.x", - "passport-strategy": "1.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - } - }, - "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "axios": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.23.0.tgz", - "integrity": "sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==", - "requires": { - "follow-redirects": "^1.14.4" - } - }, - "base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-parser": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", - "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", - "requires": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", - "requires": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==" - }, - "mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", - "requires": { - "mime-db": "1.50.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "passport": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.0.tgz", - "integrity": "sha512-ln+ue5YaNDS+fes6O5PCzXKSseY5u8MYhX9H5Co4s+HfYI5oqvnHKoOORLYDUPh+8tHvrxugF2GFcUA1Q1Gqfg==", - "requires": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - } - }, - "passport-oauth2": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz", - "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==", - "requires": { - "base64url": "3.x.x", - "oauth": "0.9.x", - "passport-strategy": "1.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - } - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, - "uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - } - } -} diff --git a/ops/images/jyp_test/package.json b/ops/images/jyp_test/package.json deleted file mode 100644 index d9196ef175e99576071fafec05b9225b82649366..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "dependencies": { - "axios": "^0.23.0", - "cookie-parser": "^1.4.5", - "express": "^4.17.1", - "express-session": "^1.17.2", - "passport": "^0.5.0", - "passport-oauth2": "^1.6.1" - } -} diff --git a/ops/images/jyp_test/server.js b/ops/images/jyp_test/server.js deleted file mode 100644 index f1f08bad256a87306874ef993086fb978a8571df..0000000000000000000000000000000000000000 --- a/ops/images/jyp_test/server.js +++ /dev/null @@ -1,81 +0,0 @@ -const express = require('express'); -const session = require('express-session'); -const passport = require('passport'); -const OAuth2Strategy = require('passport-oauth2'); -const axios = require('axios') - -const port = 8888 -const app = express(); -const baserouter = express.Router(); - -const clientHubApiUrl = 'http://localhost:9000/fairdi/nomad/latest/north/hub/api'; // process.env.JUPYTERHUB_API_URL -const serverHubApiUrl = 'http://host.docker.internal:9000/fairdi/nomad/latest/north/hub/api'; -const baseurl = process.env.JUPYTERHUB_SERVICE_PREFIX || process.env.SUBFOLDER || '/'; -const secret = process.env.JUPYTERHUB_API_TOKEN -const user = process.env.JUPYTERHUB_USER - -const passportOptions = { - authorizationURL: `${clientHubApiUrl}/oauth2/authorize`, - tokenURL: `${serverHubApiUrl}/oauth2/token`, - clientID: process.env.JUPYTERHUB_CLIENT_ID, - clientSecret: secret -} - -passport.use(new OAuth2Strategy( - passportOptions, - function(accessToken, refreshToken, params, profile, done) { - axios.get(`${serverHubApiUrl}/user`, { - headers: { 'Authorization': `Bearer ${params['access_token']}`} - }).then(response => { - if (!response?.data?.name) { - done('Cannot info for loggedin user to authorize access.', null); - } else if (response?.data?.name !== user) { - done('Logged in user does not match the container\'s user', null); - } else { - done(null, response.data); - } - }).catch(error => done(error, null)) - } -)); - -passport.serializeUser(function(user, done) { - done(null, user); -}); - -passport.deserializeUser(function(user, done) { - done(null, user); -}); - -baserouter.use(session({ secret: secret, cookie: { maxAge: 60000, path: baseurl }})) -baserouter.use(passport.initialize()); -baserouter.use(passport.session()); - -baserouter.get('/', (req, res, next) => { - if (!req.user) { - res.redirect(`${baseurl}/login`); - return - } - res.send('Welcome Home'); -}); - -baserouter.get('/login', passport.authenticate('oauth2')); - -baserouter.get('/oauth_callback', - passport.authenticate('oauth2'), - function(req, res) { - res.redirect(baseurl); - }); - -app.use((req, res, next) => { - if (!req.path.startsWith(baseurl)) { - res.redirect(301, baseurl) - } else { - next() - } -}) - -app.use(baseurl, baserouter); - -app.listen(port, function () { - console.log('Example app listening on port ' + port + '!'); -}); diff --git a/ops/images/webtop/.dockerignore b/ops/images/webtop/.dockerignore deleted file mode 100644 index 996fed7b45c7923bab1df7f1b84d90fff26c284b..0000000000000000000000000000000000000000 --- a/ops/images/webtop/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -north-guacamole-client/node_modules -north-guacamole-client/npm-debug.log \ No newline at end of file diff --git a/ops/images/webtop/Dockerfile b/ops/images/webtop/Dockerfile deleted file mode 100644 index d1e49c3436f2adf0b651b833cd5f8b3a5532a32e..0000000000000000000000000000000000000000 --- a/ops/images/webtop/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -# build stage -FROM ghcr.io/linuxserver/baseimage-ubuntu:focal as nodebuilder - -RUN \ - echo "**** install build deps ****" && \ - apt-get update && \ - apt-get install -y \ - gnupg && \ - curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ - echo 'deb https://deb.nodesource.com/node_14.x focal main' \ - > /etc/apt/sources.list.d/nodesource.list && \ - apt-get update && \ - apt-get install -y \ - g++ \ - gcc \ - libpam0g-dev \ - make \ - nodejs - -COPY north-guacamole-client /gclient - -RUN \ - echo "**** install node modules ****" && \ - cd /gclient && \ - npm install - -# runtime stage -FROM ghcr.io/linuxserver/webtop:ubuntu-openbox - -RUN rm -rf /gclient -COPY --from=nodebuilder /gclient /gclient - -# ports and volumes -EXPOSE 8888 -VOLUME /config diff --git a/ops/images/webtop/README.md b/ops/images/webtop/README.md deleted file mode 100644 index 28ed17944f6e258c4414319cca2e39e1dc203919..0000000000000000000000000000000000000000 --- a/ops/images/webtop/README.md +++ /dev/null @@ -1,15 +0,0 @@ -This is a test image for north tools authorization. - -To build: -``` -docker build -t gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/webtop . -``` - -To push: -``` -docker login gitlab-registry.mpcdf.mpg.de -docker push gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/webtop -``` - -To use it, you have to adopt `/nomad/jupyterhub_config.py` to use the -`gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/webtop` as an image. \ No newline at end of file diff --git a/ops/images/webtop/auth.js b/ops/images/webtop/auth.js deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/ops/images/webtop/north-guacamole-client b/ops/images/webtop/north-guacamole-client deleted file mode 160000 index c23da51ff35cee2f38d1e70b0a7edf6b662a63cc..0000000000000000000000000000000000000000 --- a/ops/images/webtop/north-guacamole-client +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c23da51ff35cee2f38d1e70b0a7edf6b662a63cc