profile and other stuff

This commit is contained in:
2019-08-14 16:38:03 +02:00
parent 859a5d880a
commit 9ab0d43f43
16 changed files with 297 additions and 624 deletions

2
.idea/backend.iml generated
View File

@@ -17,7 +17,7 @@
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.7 (backend-pKjQcArQ)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Pipenv (backend)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="ocmp" /> <orderEntry type="module" module-name="ocmp" />
<orderEntry type="module" module-name="OpenCastPythonClient" /> <orderEntry type="module" module-name="OpenCastPythonClient" />

2
.idea/misc.xml generated
View File

@@ -3,7 +3,7 @@
<component name="JavaScriptSettings"> <component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" /> <option name="languageLevel" value="ES6" />
</component> </component>
<component name="ProjectRootManager" version="2" project-jdk-name="Pipenv (newsMap)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Pipenv (backend)" project-jdk-type="Python SDK" />
<component name="PyCharmProfessionalAdvertiser"> <component name="PyCharmProfessionalAdvertiser">
<option name="shown" value="true" /> <option name="shown" value="true" />
</component> </component>

4
.idea/vcs.xml generated
View File

@@ -2,9 +2,7 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../../OpenCastPythonClient" vcs="Git" />
<mapping directory="$PROJECT_DIR$/.." vcs="Git" /> <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$/../../media-abstraction-layer" vcs="Git" /> <mapping directory="$PROJECT_DIR$/../frontend" vcs="Git" />
<mapping directory="$USER_HOME$/Projects/newsMap" vcs="Git" />
</component> </component>
</project> </project>

662
.idea/workspace.xml generated
View File

@@ -2,18 +2,31 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="dbc2bdbd-c8f7-46d2-961a-6a2b77f8f4c5" name="Default Changelist" comment=""> <list default="true" id="dbc2bdbd-c8f7-46d2-961a-6a2b77f8f4c5" name="Default Changelist" comment="">
<change afterPath="$USER_HOME$/Projects/newsMap/.idea/other.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/../.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/workspace.xml" afterDir="false" />
<change afterPath="$USER_HOME$/Projects/newsMap/news_map/news_sources/de_newspaper.db" afterDir="false" /> <change beforePath="$PROJECT_DIR$/../activate_this.py" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/ingest.py" beforeDir="false" afterPath="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/ingest.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/service.py" beforeDir="false" afterPath="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/service.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$" beforeDir="false" afterPath="$PROJECT_DIR$" afterDir="false" /> <change beforePath="$PROJECT_DIR$" beforeDir="false" afterPath="$PROJECT_DIR$" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/.idea/newsMap.iml" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/.idea/newsMap.iml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/backend.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/backend.iml" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/.idea/workspace.xml" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/Pipfile" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/Pipfile" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/Pipfile.lock" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/Pipfile.lock" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/news_map/gatherer/newsGatherer.py" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/news_map/gatherer/newsGatherer.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/__init__.py" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/news_map/newsMap.py" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/news_map/newsMap.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/api/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/api/__init__.py" afterDir="false" />
<change beforePath="$USER_HOME$/Projects/newsMap/news_map/news_sources/wiki_newspaper_scraper.py" beforeDir="false" afterPath="$USER_HOME$/Projects/newsMap/news_map/news_sources/wiki_newspaper_scraper.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/api/auth_api.py" beforeDir="false" afterPath="$PROJECT_DIR$/api/auth_api.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/control_api.py" beforeDir="false" afterPath="$PROJECT_DIR$/api/control_api.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/user_api.py" beforeDir="false" afterPath="$PROJECT_DIR$/api/user_api.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/auth/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/auth/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/auth/basic_auth.py" beforeDir="false" afterPath="$PROJECT_DIR$/auth/basic_auth.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/auth/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/auth/config.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/auth/templates/login.html" beforeDir="false" afterPath="$PROJECT_DIR$/auth/templates/login.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/config.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/models/recorder_model.py" beforeDir="false" afterPath="$PROJECT_DIR$/models/recorder_model.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/models/user_model.py" beforeDir="false" afterPath="$PROJECT_DIR$/models/user_model.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/api/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/api/userRepository.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/userRepository.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/components/Profile.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/components/Profile.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/main.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/main.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/plugins/i18n.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/plugins/i18n.ts" afterDir="false" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@@ -24,102 +37,6 @@
<component name="DjangoConsoleOptions" custom-start-script="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)"> <component name="DjangoConsoleOptions" custom-start-script="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)">
<option name="myCustomStartScript" value="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)" /> <option name="myCustomStartScript" value="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)" />
</component> </component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/api.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1275">
<caret line="97" column="47" selection-start-line="97" selection-start-column="47" selection-end-line="97" selection-end-column="47" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/recorder_adapters/extron_smp.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="385">
<caret line="383" column="20" selection-start-line="383" selection-start-column="20" selection-end-line="383" selection-end-column="20" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/recorder_adapters/extron_smp_testing.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/recorder_adapters/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="426">
<caret line="75" column="17" lean-forward="true" selection-start-line="75" selection-start-column="17" selection-end-line="75" selection-end-column="17" />
<folding>
<element signature="e#0#16#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/models.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="27" column="28" selection-start-line="27" selection-start-column="28" selection-end-line="27" selection-end-column="28" />
<folding>
<element signature="e#0#9#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/divaapiclient.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="252">
<caret line="322" selection-start-line="322" selection-end-line="322" />
<folding>
<element signature="e#23#37#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_item_store/newsItemStore.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/diva_testing.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="7320">
<caret line="492" column="26" selection-start-line="492" selection-start-column="26" selection-end-line="492" selection-end-column="26" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_item_store/dictNewsItemStore.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_analyzer/basicWordcountNewsAnalyzer.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
<list> <list>
@@ -127,117 +44,23 @@
</list> </list>
</option> </option>
</component> </component>
<component name="FindInProjectRecents">
<findStrings>
<find>metadata</find>
<find>UploadFiles(</find>
<find>api</find>
<find>get_api</find>
<find>alternate_user</find>
<find>DIVA_INGEST_SESSIONS</find>
<find>chunked_upload</find>
<find>diva_create_asset</find>
<find>getin</find>
<find>ingesti</find>
<find>api_v1</find>
<find>newsItems</find>
<find>expect</find>
<find>app</find>
<find>logger</find>
<find>dumps</find>
<find>create_user</find>
<find>move_media_from_user_to_user</find>
<find>DIVA_INGEST_USER_BASE_NAME</find>
<find>index</find>
<find>get_ingest_user_name_pw</find>
<find>other_roles</find>
<find>other_ro</find>
<find>_build</find>
<find>genre</find>
<find>roles</find>
<find>author</find>
<find>nested</find>
<find>_build_asset_dict</find>
<find>esc</find>
</findStrings>
<replaceStrings>
<replace />
</replaceStrings>
</component>
<component name="Git.Settings"> <component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." /> <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/api/room_api.py" />
<option value="$PROJECT_DIR$/api/recorder_api.py" />
<option value="$PROJECT_DIR$/models/recorder_model.py" />
<option value="$PROJECT_DIR$/../../oc_media_portal/frontend/src/components/Uploader.vue" />
<option value="$PROJECT_DIR$/models/room_model.py" />
<option value="$PROJECT_DIR$/../../oc_media_portal/backend/__init__.py" />
<option value="$PROJECT_DIR$/../../oc_media_portal/backend/spectrogram.py" />
<option value="$PROJECT_DIR$/../../oc_media_portal/backend/main.py" />
<option value="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/ingest.py" />
<option value="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/service.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/tools/upload.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/tools/media_files.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/models.py" />
<option value="$USER_HOME$/Projects/newsMap/news_map/newsMap.py" />
<option value="$USER_HOME$/Projects/newsMap/news_map/gatherer/newsGatherer.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/__init__.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/api.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/diva_testing.py" />
<option value="$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/divaapiclient.py" />
<option value="$PROJECT_DIR$/recorder_adapters/__init__.py" />
<option value="$PROJECT_DIR$/recorder_adapters/extron_smp.py" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" fullScreen="true">
<option name="x" value="1680" />
<option name="y" value="-49" />
<option name="width" value="1920" />
<option name="height" value="1200" />
</component> </component>
<component name="ProjectId" id="1PPJuamSCMuifjd70Sp8tYSAlOw" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" /> <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="backend" type="b2602c69:ProjectViewProjectNode" />
<item name="lrc" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="backend" type="b2602c69:ProjectViewProjectNode" />
<item name="lrc" type="462c0819:PsiDirectoryNode" />
<item name="backend" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="backend" type="b2602c69:ProjectViewProjectNode" />
<item name="lrc" type="462c0819:PsiDirectoryNode" />
<item name="backend" type="462c0819:PsiDirectoryNode" />
<item name="recorder_adapters" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent"> <component name="PropertiesComponent">
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" /> <property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" /> <property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" /> <property name="last_opened_file_path" value="$PROJECT_DIR$/models" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" /> <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" /> <property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" /> <property name="settings.editor.selected.configurable" value="project.propVCSSupport.Mappings" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\tkurz\kit_projects\lrc\backend\models" />
</key>
</component> </component>
<component name="RunDashboard"> <component name="RunDashboard">
<option name="ruleStates"> <option name="ruleStates">
@@ -251,7 +74,29 @@
</list> </list>
</option> </option>
</component> </component>
<component name="RunManager" selected="Python.extron_smp"> <component name="RunManager" selected="Python.__main__">
<configuration name="__main__" type="PythonConfigurationType" factoryName="Python" temporary="true">
<module name="backend" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/__main__.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="api" type="PythonConfigurationType" factoryName="Python" temporary="true"> <configuration name="api" type="PythonConfigurationType" factoryName="Python" temporary="true">
<module name="ocmp" /> <module name="ocmp" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
@@ -264,6 +109,7 @@
<option name="IS_MODULE_SDK" value="false" /> <option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/../../media-abstraction-layer/backend/api.py" /> <option name="SCRIPT_NAME" value="$PROJECT_DIR$/../../media-abstraction-layer/backend/api.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
@@ -285,6 +131,7 @@
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$USER_HOME$/Projects/newsMap/news_map/news_item_store/dictNewsItemStore.py" /> <option name="SCRIPT_NAME" value="$USER_HOME$/Projects/newsMap/news_map/news_item_store/dictNewsItemStore.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
@@ -306,6 +153,7 @@
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$USER_HOME$/Projects/newsMap/news_map/gatherer/dummyNewsGatherer.py" /> <option name="SCRIPT_NAME" value="$USER_HOME$/Projects/newsMap/news_map/gatherer/dummyNewsGatherer.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
@@ -327,6 +175,7 @@
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/recorder_adapters/extron_smp.py" /> <option name="SCRIPT_NAME" value="$PROJECT_DIR$/recorder_adapters/extron_smp.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
@@ -336,27 +185,6 @@
<option name="INPUT_FILE" value="" /> <option name="INPUT_FILE" value="" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="ingest" type="PythonConfigurationType" factoryName="Python" temporary="true">
<module name="OpenCastPythonClient" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/ingest.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="backend" type="Python.FlaskServer"> <configuration name="backend" type="Python.FlaskServer">
<module name="backend" /> <module name="backend" />
<option name="target" value="$PROJECT_DIR$/__init__.py" /> <option name="target" value="$PROJECT_DIR$/__init__.py" />
@@ -373,19 +201,20 @@
<method v="2" /> <method v="2" />
</configuration> </configuration>
<list> <list>
<item itemvalue="Flask server.backend" />
<item itemvalue="Python.api" /> <item itemvalue="Python.api" />
<item itemvalue="Python.ingest" />
<item itemvalue="Python.dummyNewsGatherer" /> <item itemvalue="Python.dummyNewsGatherer" />
<item itemvalue="Python.dictNewsItemStore" /> <item itemvalue="Python.dictNewsItemStore" />
<item itemvalue="Python.extron_smp" /> <item itemvalue="Python.extron_smp" />
<item itemvalue="Python.__main__" />
</list> </list>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Python.__main__" />
<item itemvalue="Python.extron_smp" /> <item itemvalue="Python.extron_smp" />
<item itemvalue="Python.dictNewsItemStore" /> <item itemvalue="Python.dictNewsItemStore" />
<item itemvalue="Python.dummyNewsGatherer" /> <item itemvalue="Python.dummyNewsGatherer" />
<item itemvalue="Python.api" /> <item itemvalue="Python.api" />
<item itemvalue="Python.ingest" />
</list> </list>
</recent_temporary> </recent_temporary>
</component> </component>
@@ -402,355 +231,38 @@
<workItem from="1556266473180" duration="14572000" /> <workItem from="1556266473180" duration="14572000" />
<workItem from="1557483399929" duration="284000" /> <workItem from="1557483399929" duration="284000" />
<workItem from="1557483805341" duration="173000" /> <workItem from="1557483805341" duration="173000" />
<workItem from="1565770023268" duration="8793000" />
<workItem from="1565778873035" duration="9376000" />
</task> </task>
<servers /> <servers />
</component> </component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="40587000" />
</component>
<component name="ToolWindowManager">
<frame x="1680" y="-49" width="1920" height="1200" extended-state="0" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.22064245" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.32920355" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" order="8" />
<window_info anchor="bottom" id="Database Changes" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" weight="0.28584072" />
<window_info anchor="bottom" id="Python Console" order="11" />
<window_info anchor="bottom" id="Event Log" order="12" side_tool="true" weight="0.32959184" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="SciView" order="3" />
<window_info anchor="right" id="Database" order="4" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" /> <option name="version" value="1" />
</component> </component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="COLUMN_ORDER" />
</State>
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<ignored-roots>
<path value="$USER_HOME$/Projects/newsMap" />
<path value="$PROJECT_DIR$/../../OpenCastPythonClient" />
<path value="$PROJECT_DIR$/../../media-abstraction-layer" />
</ignored-roots>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl"> <component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/backend$extron_smp.coverage" NAME="extron_smp Coverage Results" MODIFIED="1565782117031" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/recorder_adapters" />
<SUITE FILE_PATH="coverage/backend$main.coverage" NAME="main Coverage Results" MODIFIED="1557306314589" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/../../oc_media_portal/backend" /> <SUITE FILE_PATH="coverage/backend$main.coverage" NAME="main Coverage Results" MODIFIED="1557306314589" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/../../oc_media_portal/backend" />
<SUITE FILE_PATH="coverage/backend$backend.coverage" NAME="backend Coverage Results" MODIFIED="1556810339611" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" /> <SUITE FILE_PATH="coverage/backend$backend.coverage" NAME="backend Coverage Results" MODIFIED="1556810339611" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
</component> <SUITE FILE_PATH="coverage/backend$__main__.coverage" NAME="__main__ Coverage Results" MODIFIED="1565793060617" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<component name="editorHistoryManager">
<entry file="file://$USER_HOME$/.virtualenvs/backend-ogkP9-fi/lib/python3.7/site-packages/ffmpeg/_ffmpeg.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="15" column="4" selection-start-line="15" selection-start-column="4" selection-end-line="15" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/wave.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="465">
<caret line="31" column="21" selection-start-line="31" selection-start-column="21" selection-end-line="31" selection-end-column="21" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.virtualenvs/backend-ogkP9-fi/lib/python3.7/site-packages/matplotlib/pyplot.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="540">
<caret line="686" column="4" selection-start-line="686" selection-start-column="4" selection-end-line="686" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.virtualenvs/backend-ogkP9-fi/lib/python3.7/site-packages/matplotlib/figure.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="318">
<caret line="1820" column="8" selection-start-line="1820" selection-start-column="8" selection-end-line="1820" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/frontend/src/router.js" />
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/frontend/public/index.html" />
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/frontend/src/views/Home.vue" />
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/backend/main.py" />
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/backend/__init__.py" />
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/backend/spectrogram.py" />
<entry file="file://$PROJECT_DIR$/../../oc_media_portal/frontend/src/components/Uploader.vue" />
<entry file="file://$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/ingest.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="903">
<caret line="167" column="14" selection-start-line="167" selection-start-column="14" selection-end-line="167" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/info.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#15#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/api/service.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3255">
<caret line="228" column="50" selection-start-line="228" selection-start-column="50" selection-end-line="228" selection-end-column="50" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.virtualenvs/backend-ogkP9-fi/lib/python3.7/site-packages/flask/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="44" selection-start-line="44" selection-end-line="44" selection-end-column="7" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="298" column="4" selection-start-line="298" selection-start-column="4" selection-end-line="298" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/uploads/test.txt">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$USER_HOME$/.local/share/virtualenvs/OpenCastPythonClient-4-tsbEhp/lib/python3.7/site-packages/werkzeug/wrappers.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="7740">
<caret line="543" column="17" selection-start-line="543" selection-start-column="17" selection-end-line="543" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/tools/upload.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="420">
<caret line="30" column="13" selection-start-line="30" selection-start-column="13" selection-end-line="30" selection-end-column="13" />
<folding>
<element signature="e#0#9#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/tools/media_files.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="14" column="87" selection-start-line="14" selection-start-column="87" selection-end-line="14" selection-end-column="87" />
<folding>
<element signature="e#0#9#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/manage.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="373">
<caret line="32" column="71" lean-forward="true" selection-start-line="32" selection-start-column="71" selection-end-line="32" selection-end-column="71" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/serve_frontend.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="135">
<caret line="15" selection-start-line="15" selection-end-line="15" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/api/group_api.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="186">
<caret line="29" column="40" selection-start-line="29" selection-start-column="40" selection-end-line="29" selection-end-column="40" />
<folding>
<element signature="e#267#310#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/api/recorder_api.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1815">
<caret line="127" selection-start-line="127" selection-end-line="127" />
<folding>
<element signature="e#267#310#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/main.py" />
<entry file="file://$PROJECT_DIR$/api/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="36" selection-start-line="36" selection-end-line="36" />
<folding>
<element signature="e#25#59#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/../../OpenCastPythonClient/ocpy/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="105">
<caret line="7" column="64" selection-start-line="7" selection-start-column="55" selection-end-line="7" selection-end-column="64" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/test.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/gatherer/faz_website.txt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="15" column="21" lean-forward="true" selection-start-line="15" selection-start-column="21" selection-end-line="15" selection-end-column="21" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/newsMap.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="435">
<caret line="29" column="29" selection-start-line="29" selection-start-column="29" selection-end-line="29" selection-end-column="29" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/gatherer/basicNewsGatherer.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#77#121#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/gatherer/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/gatherer/dummyNewsGatherer.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="216">
<caret line="40" column="37" selection-start-line="40" selection-start-column="37" selection-end-line="40" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/gatherer/newsGatherer.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="540">
<caret line="42" column="8" selection-start-line="42" selection-start-column="8" selection-end-line="42" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/gatherer/rssNewsGatherer.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="268">
<caret line="44" column="38" selection-start-line="44" selection-start-column="38" selection-end-line="44" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_item_store/mongoNewsItemStore.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="41" column="8" selection-start-line="41" selection-start-column="8" selection-end-line="41" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/telnetlib.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-105">
<caret selection-end-line="32" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="240">
<caret line="24" column="2" selection-start-line="24" selection-start-column="2" selection-end-line="24" selection-end-column="2" />
<folding>
<element signature="e#0#9#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/api.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1275">
<caret line="97" column="47" selection-start-line="97" selection-start-column="47" selection-end-line="97" selection-end-column="47" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/models.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="27" column="28" selection-start-line="27" selection-start-column="28" selection-end-line="27" selection-end-column="28" />
<folding>
<element signature="e#0#9#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_item_store/newsItemStore.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/diva_testing.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="7320">
<caret line="492" column="26" selection-start-line="492" selection-start-column="26" selection-end-line="492" selection-end-column="26" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_item_store/dictNewsItemStore.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$USER_HOME$/Projects/newsMap/news_map/news_analyzer/basicWordcountNewsAnalyzer.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/../../media-abstraction-layer/backend/media_backends/divaapiclient.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="252">
<caret line="322" selection-start-line="322" selection-end-line="322" />
<folding>
<element signature="e#23#37#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/recorder_adapters/extron_smp_testing.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/recorder_adapters/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="426">
<caret line="75" column="17" lean-forward="true" selection-start-line="75" selection-start-column="17" selection-end-line="75" selection-end-column="17" />
<folding>
<element signature="e#0#16#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/recorder_adapters/extron_smp.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="385">
<caret line="383" column="20" selection-start-line="383" selection-start-column="20" selection-end-line="383" selection-end-column="20" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component> </component>
</project> </project>

View File

@@ -42,7 +42,6 @@ def verify_token(token):
app.logger.info(decoded) app.logger.info(decoded)
return True return True
basic_auth = HTTPBasicAuth() basic_auth = HTTPBasicAuth()
multi_auth = MultiAuth(basic_auth, jwt_auth) multi_auth = MultiAuth(basic_auth, jwt_auth)

View File

@@ -45,6 +45,13 @@ api_v1.add_namespace(api_cron_job)
api_v1.add_namespace(api_control) api_v1.add_namespace(api_control)
auth_api_bp = Blueprint('auth_api', __name__, url_prefix='/api/auth') auth_api_bp = Blueprint('auth_api', __name__, url_prefix='/api/auth')
auth_api_v1 = Api(auth_api_bp, prefix="/v1", version='0.1', title='Auth API',
description='Auth API', doc='/v1/doc/', authorizations=api_authorizations, security='bearerAuth')
auth_api_providers_ns = Namespace('providers')
auth_api_register_ns = Namespace('register')
auth_api_v1.add_namespace(auth_api_providers_ns)
auth_api_v1.add_namespace(auth_api_register_ns)
# user_api_bp = Blueprint('user_api', __name__, url_prefix='/api/user') # user_api_bp = Blueprint('user_api', __name__, url_prefix='/api/user')
# group_api_bp = Blueprint('group_api', __name__, url_prefix='/api/group') # group_api_bp = Blueprint('group_api', __name__, url_prefix='/api/group')

View File

@@ -7,23 +7,27 @@ Login through API does not start a new session, but instead returns JWT.
""" """
import base64 import base64
import json import json
from pprint import pprint
import flask import flask
from datetime import datetime, timedelta from datetime import datetime, timedelta
import jwt import jwt
from flask import request, jsonify, current_app, url_for, Response, session, redirect, make_response from flask import request, jsonify, current_app, url_for, Response, session, redirect, make_response
from flask_jwt_extended import create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity from flask_jwt_extended import create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity, \
get_raw_jwt, jwt_required
from functools import wraps from functools import wraps
from random import randint from random import randint
from flask_login import logout_user, login_user from flask_login import logout_user, login_user
from typing import Iterable from typing import Iterable
from flask_restplus import Resource, fields
from werkzeug.routing import BuildError from werkzeug.routing import BuildError
from backend import db, app from backend import db, app, jwt_extended
from backend.api import auth_api_bp from backend.api import auth_api_bp, auth_api_providers_ns, auth_api_register_ns
from backend.auth import AUTH_PROVIDERS, oidc_auth from backend.auth import AUTH_PROVIDERS, oidc_auth
from backend.models.user_model import User, Group from backend.models.user_model import User, Group, BlacklistToken
@auth_api_bp.route('/providers', methods=('GET',)) @auth_api_bp.route('/providers', methods=('GET',))
@@ -39,6 +43,12 @@ def get_auth_providers():
return jsonify(providers) return jsonify(providers)
@auth_api_providers_ns.route('/')
class AuthProviders(Resource):
def get(self):
return get_auth_providers()
@auth_api_bp.route('/register', methods=('POST',)) @auth_api_bp.route('/register', methods=('POST',))
def register(): def register():
data = request.get_json() data = request.get_json()
@@ -48,6 +58,21 @@ def register():
return jsonify(user.to_dict()), 201 return jsonify(user.to_dict()), 201
@auth_api_register_ns.route('/')
@auth_api_register_ns.expect(auth_api_register_ns.model('RegisterModel', {
'nickname': fields.String(required=False, description='The user\'s nickname'),
'first_name': fields.String(required=False, description='The user\'s first name'),
'last_name': fields.String(required=False, description='The user\'s last name'),
'lang': fields.String(required=False, description='The user\'s preferred language'),
'timezone': fields.String(required=False, description='The user\'s preferred timezone'),
'email': fields.String(required=True, description='The user\'s e-mail address'),
'password': fields.String(required=False, description='The group\'s name')
}))
class AuthProviders(Resource):
def get(self):
return register()
@auth_api_bp.route('/login', methods=('GET', 'POST',)) @auth_api_bp.route('/login', methods=('GET', 'POST',))
def login(): def login():
print("login") print("login")
@@ -62,11 +87,30 @@ def login():
return jsonify({'message': 'Invalid credentials', 'authenticated': False}), 401 return jsonify({'message': 'Invalid credentials', 'authenticated': False}), 401
token = { token = {
'access_token': create_access_token(identity=user.email, fresh=True), 'access_token': create_access_token(identity=user, fresh=True),
'refresh_token': create_refresh_token(identity=user.email) 'refresh_token': create_refresh_token(identity=user)
} }
return jsonify(token), 200 return jsonify(token), 200
# Endpoint for revoking the current users access token
@auth_api_bp.route('/logout', methods=['GET', 'DELETE'])
@jwt_required
def logout():
jti = get_raw_jwt()['jti']
db.session.add(BlacklistToken(token=jti))
db.session.commit()
return jsonify({"msg": "Successfully logged out"}), 200
# Endpoint for revoking the current users refresh token
@auth_api_bp.route('/logout2', methods=['GET', 'DELETE'])
@jwt_refresh_token_required
def logout2():
jti = get_raw_jwt()['jti']
db.session.add(BlacklistToken(token=jti))
db.session.commit()
return jsonify({"msg": "Successfully logged out"}), 200
def check_and_create_groups(groups: Iterable[str]): def check_and_create_groups(groups: Iterable[str]):
user_groups = [] user_groups = []
@@ -92,6 +136,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
if user is not None: if user is not None:
app.logger.info("user found -> update user") app.logger.info("user found -> update user")
pprint(user.to_dict())
user.first_name = userinfo.get("given_name", "") user.first_name = userinfo.get("given_name", "")
user.last_name = userinfo.get("family_name", "") user.last_name = userinfo.get("family_name", "")
for g in user_groups: for g in user_groups:
@@ -121,8 +166,8 @@ def oidc(redirect_url=None):
token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY']) token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY'])
else: else:
token = json.dumps({ token = json.dumps({
'access_token': create_access_token(identity=user.email, fresh=True), 'access_token': create_access_token(identity=user, fresh=True),
'refresh_token': create_refresh_token(identity=user.email) 'refresh_token': create_refresh_token(identity=user)
}) })
if redirect_url is None: if redirect_url is None:
redirect_url = request.headers.get("Referer") redirect_url = request.headers.get("Referer")
@@ -142,8 +187,10 @@ def refresh():
"""Refresh token endpoint. This will generate a new access token from """Refresh token endpoint. This will generate a new access token from
the refresh token, but will mark that access token as non-fresh, the refresh token, but will mark that access token as non-fresh,
as we do not actually verify a password in this endpoint.""" as we do not actually verify a password in this endpoint."""
current_user = get_jwt_identity() jwt_identity = get_jwt_identity()
app.logger.info("Refreshing token for " + current_user) user = User.get_by_identifier(jwt_identity)
new_token = create_access_token(identity=current_user, fresh=False) app.logger.info("Refreshing token for " + str(user))
new_token = create_access_token(identity=user, fresh=False)
ret = {'access_token': new_token} ret = {'access_token': new_token}
return jsonify(ret), 200 return jsonify(ret), 200

View File

@@ -8,7 +8,7 @@ Login through API does not start a new session, but instead returns JWT.
import json import json
from datetime import datetime from datetime import datetime
from flask_jwt_extended import jwt_required from flask_jwt_extended import jwt_required, get_current_user, get_jwt_claims
from flask_restplus import fields, Resource from flask_restplus import fields, Resource
from backend import db from backend import db
@@ -35,6 +35,8 @@ class ControlCommand(Resource):
@api_control.expect(control_command_parser) @api_control.expect(control_command_parser)
@api_control.marshal_with(control_command_response_model, skip_none=False, code=201) @api_control.marshal_with(control_command_response_model, skip_none=False, code=201)
def post(self): def post(self):
current_user = {'identity': get_jwt_identity(), 'type': type(get_jwt_identity())} print(get_current_user())
print(get_jwt_identity())
current_user = {'user': get_current_user(), 'claims': get_jwt_claims()}
args = self.control_command_parser.parse_args() args = self.control_command_parser.parse_args()
return {'time': datetime.utcnow(), 'output': args, 'state': current_user} return {'time': datetime.utcnow(), 'output': args, 'state': current_user}

View File

@@ -5,45 +5,71 @@ For example: listing of available auth providers or registration of users.
Login through API does not start a new session, but instead returns JWT. Login through API does not start a new session, but instead returns JWT.
""" """
from datetime import datetime
from pprint import pprint
import flask import flask
import jwt import jwt
from flask import request, jsonify, current_app, url_for from flask import request, jsonify, current_app, url_for
from flask_jwt_extended import get_jwt_identity, jwt_optional, jwt_required from flask_jwt_extended import get_jwt_identity, jwt_optional, jwt_required
from flask_restplus import Resource, fields from flask_restplus import Resource, fields, inputs
from backend import db, app, jwt_auth from backend import db, app, jwt_auth
from backend.api import api_bp, api_user from backend.api import api_bp, api_user
from backend.auth import oidc_auth from backend.auth import oidc_auth
from backend.models.user_model import User, Group from backend.models.user_model import User, Group
user_model = api_user.model('User', { user_model = api_user.model('User', {
'id': fields.String(required=True, description='The user\'s identifier'), 'id': fields.String(required=True, description='The user\'s identifier'),
'first_name': fields.String(required=True, description='The user\'s first name'), 'first_name': fields.String(required=True, description='The user\'s first name'),
'last_name': fields.String(required=True, description='The user\'s last name'), 'last_name': fields.String(required=True, description='The user\'s last name'),
'email': fields.String(required=True, description='The user\'s email address'), 'email': fields.String(required=True, description='The user\'s email address'),
'nickname': fields.String(required=False, description='The user\'s nick name'), 'nickname': fields.String(required=False, description='The user\'s nick name'),
'groups': fields.List(fields.Nested(api_user.model('user_group', {'id':fields.Integer(), 'name': fields.String()})), 'groups': fields.List(
fields.Nested(api_user.model('user_group', {'id': fields.Integer(), 'name': fields.String()})),
required=False, description='Group memberships.'), required=False, description='Group memberships.'),
}) })
user_update_parser = api_user.parser()
user_update_parser.add_argument('email', type=inputs.email, required=False, nullable=False, store_missing=False)
user_update_parser.add_argument('nickname', type=str, required=False, store_missing=False)
user_update_parser.add_argument('first_name', type=str, required=False, store_missing=False)
user_update_parser.add_argument('last_name', type=str, required=False, store_missing=False)
@api_user.route('/profile', methods=['GET']) @api_user.route('/profile')
class Profile(Resource): class Profile(Resource):
@jwt_auth.login_required @jwt_required
@api_user.marshal_list_with(user_model) @api_user.marshal_with(user_model)
def get(self): def get(self):
"""Get infos about logged in user.""" """Get infos about logged in user."""
current_user_id = get_jwt_identity() current_user_id = get_jwt_identity()
app.logger.info(current_user_id) app.logger.info(current_user_id)
return User.get_by_identifier(current_user_id) return User.get_by_identifier(current_user_id)
@jwt_required
def put(self):
current_user_id = get_jwt_identity()
print(api_user.payload)
app.logger.info(current_user_id)
args = user_update_parser.parse_args()
args['last_time_modified'] = datetime.utcnow()
pprint(args)
num_rows_matched = User.query.filter_by(id=current_user_id).update(args)
print(num_rows_matched)
if num_rows_matched < 1:
api_user.abort(404)
db.session.commit()
return "ok"
@api_user.route('') @api_user.route('')
class UserList(Resource): class UserList(Resource):
""" """
This is a test class. This is a test class.
""" """
# @jwt_auth.login_required # @jwt_auth.login_required
@jwt_required @jwt_required
@api_user.doc('users') @api_user.doc('users')

View File

@@ -8,10 +8,13 @@ If frontend pages are build by frontend code (JS, etc.) authentication should co
This code uses login_user and logout user (to start and end sessions) ... API code returns JWTs. This code uses login_user and logout user (to start and end sessions) ... API code returns JWTs.
""" """
from flask import Blueprint, jsonify from flask import Blueprint, jsonify, url_for
from flask_login import logout_user, LoginManager from flask_login import logout_user, LoginManager
from werkzeug.routing import BuildError from werkzeug.routing import BuildError
from backend import jwt_extended
from backend.models import BlacklistToken, User
auth_bp = Blueprint('auth', __name__, url_prefix='/auth', template_folder='templates') auth_bp = Blueprint('auth', __name__, url_prefix='/auth', template_folder='templates')
from backend.auth.config import AUTH_PROVIDERS, DEFAULT_FRONTEND_PROVIDER from backend.auth.config import AUTH_PROVIDERS, DEFAULT_FRONTEND_PROVIDER
@@ -49,3 +52,27 @@ def login_select():
@auth_bp.route('/logout', methods=('GET', )) @auth_bp.route('/logout', methods=('GET', ))
def logout(): def logout():
logout_user() logout_user()
@jwt_extended.user_claims_loader
def add_claims_to_access_token(user):
if isinstance(user, str):
return {}
return {'role': user.role, 'groups': [g.to_dict() for g in user.groups]}
@jwt_extended.user_identity_loader
def user_identity_loader(user):
return user.email
@jwt_extended.user_loader_callback_loader
def user_loader_callback(identity):
user = User.get_by_identifier(identity)
return user
@jwt_extended.token_in_blacklist_loader
def check_if_token_in_blacklist(decrypted_token):
jti = decrypted_token['jti']
return BlacklistToken.get_by_token(jti) is not None

View File

@@ -1,18 +1,20 @@
# Route for handling the login page logic # Route for handling the login page logic
from flask import request, redirect, render_template, url_for from flask import request, redirect, render_template
from flask_login import login_user from flask_login import login_user
from backend.auth import auth_bp from backend.auth import auth_bp
from backend.models.user_model import User
@auth_bp.route('/base_login', methods=['GET', 'POST']) @auth_bp.route('/base_login', methods=['GET', 'POST'])
def base_login(): def base_login():
error = None error = None
if request.method == 'POST': if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin': user = User.authenticate(email=request.form['email'], password=request.form['password'])
if user is None:
error = 'Invalid Credentials. Please try again.' error = 'Invalid Credentials. Please try again.'
else: else:
login_user() login_user(user)
return redirect("/") return redirect("/")
return render_template('login.html', error=error) return render_template('login.html', error=error)

View File

@@ -4,7 +4,7 @@ AUTH_PROVIDERS: Dict[str, Dict[str, str]] = {
"KIT OIDC": "KIT OIDC":
{ {
"type": "oidc", "type": "oidc",
"url": "auth.oidc" "url": "auth_api.oidc"
}, },
"Base Login": "Base Login":
{ {

View File

@@ -9,7 +9,7 @@
<h1>Please login</h1> <h1>Please login</h1>
<br> <br>
<form action="" method="post"> <form action="" method="post">
<input type="text" placeholder="Username" name="username" value="{{ <input type="text" placeholder="E-Mail" name="email" value="{{
request.form.username }}"> request.form.username }}">
<input type="password" placeholder="Password" name="password" value="{{ <input type="password" placeholder="Password" name="password" value="{{
request.form.password }}"> request.form.password }}">

View File

@@ -2,6 +2,7 @@
# ... # ...
# available languages # available languages
import os import os
basedir = os.path.abspath(os.path.dirname(__file__)) basedir = os.path.abspath(os.path.dirname(__file__))
@@ -69,17 +70,32 @@ class Config():
# JWT_EXP_DELTA_SECONDS = 5 * 60 # JWT_EXP_DELTA_SECONDS = 5 * 60
JWT_SECRET_KEY = "abcxyz" JWT_SECRET_KEY = "abcxyz"
JWT_BLACKLIST_ENABLED = True
JWT_BLACKLIST_TOKEN_CHECKS = ['access', 'refresh']
AUTH_RETURN_EXTERNAL_JWT = False AUTH_RETURN_EXTERNAL_JWT = False
INDEX_TEMPLATE = "index.html" INDEX_TEMPLATE = "index.html"
# # INITIAL VALUES # #
PERMISSIONS = ["RECODER_NEW", "RECORDER_EDIT", "RECODER_SHOW", "RECORDER_DELETE", PERMISSIONS = ["RECODER_NEW", "RECORDER_EDIT", "RECODER_SHOW", "RECORDER_DELETE",
"RECORDER_COMMAND_EXECUTE", "RECORDER_COMMAND_EDIT_ACL", "RECORDER_COMMAND_EXECUTE", "RECORDER_COMMAND_EDIT_ACL",
"VIRTUAL_COMMAND_CREATE", "VIRTUAL_COMMAND_EDIT", "VIRTUAL_COMMAND_SHOW", "VIRTUAL_COMMAND_DELETE", "VIRTUAL_COMMAND_CREATE", "VIRTUAL_COMMAND_EDIT", "VIRTUAL_COMMAND_SHOW", "VIRTUAL_COMMAND_DELETE",
"CRON_JOB_CREATE", "CRON_JOB_EDIT", "CRON_JOB_SHOW", "CRON_JOB_DELETE"] "CRON_JOB_CREATE", "CRON_JOB_EDIT", "CRON_JOB_SHOW", "CRON_JOB_DELETE"]
GROUPS = ["Admins", "ZML", "read_only"] GROUPS = [ #{"name": "Admins",
#"permissions": PERMISSIONS},
{"name": "ZML"},
{"name": "read_only"}]
USERS = [{"nickname": "admin",
"first_name": "tobias",
"last_name": "kurze",
"email": "kurze@kit.edu",
"role": "admin",
"password": "admin"}
]
class ProductionConfig(Config): class ProductionConfig(Config):

View File

@@ -28,8 +28,8 @@ class RecorderModel(db.Model):
recorder_commands = db.relationship('RecorderCommand', back_populates='recorder_model') recorder_commands = db.relationship('RecorderCommand', back_populates='recorder_model')
recorders = db.relationship('Recorder', back_populates='recorder_model') recorders = db.relationship('Recorder', back_populates='recorder_model')
checksum = db.Column(db.String(63), unique=True, nullable=False) checksum = db.Column(db.String(63), unique=True, nullable=False)
requires_user = db.Column(db.Boolean) _requires_user = db.Column(db.Integer, default=False, name='requires_user')
requires_password = db.Column(db.Boolean) _requires_password = db.Column(db.Integer, default=True, name='requires_password')
@staticmethod @staticmethod
def get_all(): def get_all():
@@ -47,6 +47,22 @@ class RecorderModel(db.Model):
def get_by_checksum(md5_sum): def get_by_checksum(md5_sum):
return RecorderModel.query.filter(RecorderModel.checksum == md5_sum).first() return RecorderModel.query.filter(RecorderModel.checksum == md5_sum).first()
@hybrid_property
def requires_user(self):
return self._requires_user > 0
@requires_user.setter
def requires_user(self, val: bool):
self._requires_user = 1 if val else 0
@hybrid_property
def requires_password(self):
return self._requires_password > 0
@requires_password.setter
def requires_password(self, val: bool):
self._requires_password = 1 if val else 0
class Recorder(db.Model): class Recorder(db.Model):
id = db.Column(db.Integer, autoincrement=True, primary_key=True) id = db.Column(db.Integer, autoincrement=True, primary_key=True)
@@ -64,8 +80,8 @@ class Recorder(db.Model):
network_name = db.Column(db.String(127), unique=True, nullable=True, default=None) network_name = db.Column(db.String(127), unique=True, nullable=True, default=None)
telnet_port = db.Column(db.Integer, unique=False, nullable=False, default=23) telnet_port = db.Column(db.Integer, unique=False, nullable=False, default=23)
ssh_port = db.Column(db.Integer, unique=False, nullable=False, default=22) ssh_port = db.Column(db.Integer, unique=False, nullable=False, default=22)
username = db.column(db.String(127)) username = db.Column(db.String, nullable=True, default=None)
password = db.column(db.String(127)) password = db.Column(db.String, nullable=True, default=None)
recorder_model_id = db.Column(db.Integer, db.ForeignKey('recorder_model.id')) recorder_model_id = db.Column(db.Integer, db.ForeignKey('recorder_model.id'))
recorder_model = db.relationship('RecorderModel', back_populates='recorders') recorder_model = db.relationship('RecorderModel', back_populates='recorders')
virtual_commands = db.relationship('VirtualCommand', secondary=virtual_command_recorder_table, back_populates='recorders') virtual_commands = db.relationship('VirtualCommand', secondary=virtual_command_recorder_table, back_populates='recorders')

View File

@@ -83,6 +83,7 @@ class User(UserMixin, db.Model):
registered_on = db.Column(db.DateTime, nullable=False, default=datetime.utcnow()) registered_on = db.Column(db.DateTime, nullable=False, default=datetime.utcnow())
external_user = db.Column(db.Boolean, default=False) external_user = db.Column(db.Boolean, default=False)
last_seen = db.Column(db.DateTime, default=datetime.utcnow()) last_seen = db.Column(db.DateTime, default=datetime.utcnow())
last_time_modified = db.Column(db.DateTime, default=datetime.utcnow())
jwt_exp_delta_seconds = db.Column(db.Integer, nullable=True) jwt_exp_delta_seconds = db.Column(db.Integer, nullable=True)
acquainted = db.relationship('User', acquainted = db.relationship('User',
secondary=acquaintances, secondary=acquaintances,
@@ -264,6 +265,8 @@ class User(UserMixin, db.Model):
:param password: :param password:
:return: :return:
""" """
if self.password is None:
return False
return sha256_crypt.verify(password, self.password) return sha256_crypt.verify(password, self.password)
def get_id(self): def get_id(self):
@@ -375,7 +378,7 @@ class User(UserMixin, db.Model):
sort_keys=True, indent=4) sort_keys=True, indent=4)
def __repr__(self): def __repr__(self):
return '<User %r>' % self.nickname return '<User %r>' % self.email
class BlacklistToken(db.Model): class BlacklistToken(db.Model):
@@ -395,6 +398,10 @@ class BlacklistToken(db.Model):
def __repr__(self): def __repr__(self):
return '<id: token: {}'.format(self.token) return '<id: token: {}'.format(self.token)
@staticmethod
def get_by_token(jwt_id):
return BlacklistToken.query.filter(BlacklistToken.token == jwt_id).first()
@staticmethod @staticmethod
def check_blacklist(auth_token): def check_blacklist(auth_token):
""" """
@@ -457,6 +464,20 @@ class Permission(db.Model):
back_populates='permissions') back_populates='permissions')
@event.listens_for(User.__table__, 'after_create')
def insert_initial_users(*args, **kwargs):
for u in app.config.get("USERS", []):
db.session.add(User(**u))
db.session.commit()
@event.listens_for(Group.__table__, 'after_create')
def insert_initial_groups(*args, **kwargs):
for g in app.config.get("GROUPS", []):
db.session.add(Group(**g))
db.session.commit()
@event.listens_for(Permission.__table__, 'after_create') @event.listens_for(Permission.__table__, 'after_create')
def insert_initial_permissions(*args, **kwargs): def insert_initial_permissions(*args, **kwargs):
for p in app.config.get("PERMISSIONS", []): for p in app.config.get("PERMISSIONS", []):