igs-slm 0.1.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- igs_slm-0.1.0b0.dist-info/LICENSE +21 -0
- igs_slm-0.1.0b0.dist-info/METADATA +151 -0
- igs_slm-0.1.0b0.dist-info/RECORD +447 -0
- igs_slm-0.1.0b0.dist-info/WHEEL +4 -0
- igs_slm-0.1.0b0.dist-info/entry_points.txt +3 -0
- igs_tools/__init__.py +0 -0
- igs_tools/connection.py +88 -0
- igs_tools/defines/__init__.py +8 -0
- igs_tools/defines/constellation.py +21 -0
- igs_tools/defines/data_center.py +75 -0
- igs_tools/defines/rinex.py +49 -0
- igs_tools/directory.py +247 -0
- igs_tools/utils.py +66 -0
- slm/__init__.py +21 -0
- slm/admin.py +674 -0
- slm/api/edit/__init__.py +0 -0
- slm/api/edit/serializers.py +316 -0
- slm/api/edit/views.py +1632 -0
- slm/api/fields.py +89 -0
- slm/api/filter.py +504 -0
- slm/api/pagination.py +55 -0
- slm/api/permissions.py +65 -0
- slm/api/public/__init__.py +0 -0
- slm/api/public/serializers.py +249 -0
- slm/api/public/views.py +606 -0
- slm/api/serializers.py +132 -0
- slm/api/views.py +148 -0
- slm/apps.py +323 -0
- slm/authentication.py +198 -0
- slm/bin/__init__.py +0 -0
- slm/bin/startproject.py +262 -0
- slm/bin/templates/{{ project_dir }}/pyproject.toml +35 -0
- slm/bin/templates/{{ project_dir }}/sites/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/base.py +15 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/__init__.py +56 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/local.py +4 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/wsgi.py +16 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/manage.py +34 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/__init__.py +61 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/wsgi.py +16 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/urls.py +7 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/validation.py +11 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/admin.py +5 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/apps.py +14 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/import_archive.py +64 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/migrations/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/models.py +6 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/templates/slm/base.html +8 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/urls.py +10 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/views.py +5 -0
- slm/defines/AlertLevel.py +24 -0
- slm/defines/AntennaCalibration.py +25 -0
- slm/defines/AntennaFeatures.py +27 -0
- slm/defines/AntennaReferencePoint.py +22 -0
- slm/defines/Aspiration.py +13 -0
- slm/defines/CardinalDirection.py +19 -0
- slm/defines/CollocationStatus.py +12 -0
- slm/defines/EquipmentState.py +22 -0
- slm/defines/FlagSeverity.py +14 -0
- slm/defines/FractureSpacing.py +15 -0
- slm/defines/FrequencyStandardType.py +15 -0
- slm/defines/GeodesyMLVersion.py +48 -0
- slm/defines/ISOCountry.py +1194 -0
- slm/defines/Instrumentation.py +19 -0
- slm/defines/LogEntryType.py +30 -0
- slm/defines/SLMFileType.py +18 -0
- slm/defines/SiteFileUploadStatus.py +61 -0
- slm/defines/SiteLogFormat.py +49 -0
- slm/defines/SiteLogStatus.py +78 -0
- slm/defines/TectonicPlates.py +28 -0
- slm/defines/__init__.py +46 -0
- slm/forms.py +1126 -0
- slm/jinja2/slm/sitelog/ascii_9char.log +346 -0
- slm/jinja2/slm/sitelog/legacy.log +346 -0
- slm/jinja2/slm/sitelog/xsd/0.4/collocationInformation.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/condition.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/contact.xml +52 -0
- slm/jinja2/slm/sitelog/xsd/0.4/formInformation.xml +5 -0
- slm/jinja2/slm/sitelog/xsd/0.4/frequencyStandard.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/gnssAntenna.xml +16 -0
- slm/jinja2/slm/sitelog/xsd/0.4/gnssReceiver.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.4/humiditySensor.xml +13 -0
- slm/jinja2/slm/sitelog/xsd/0.4/localEpisodicEffect.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/moreInformation.xml +22 -0
- slm/jinja2/slm/sitelog/xsd/0.4/multipathSource.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/otherInstrumentation.xml +5 -0
- slm/jinja2/slm/sitelog/xsd/0.4/pressureSensor.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/radioInterference.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.4/sensor.xml +16 -0
- slm/jinja2/slm/sitelog/xsd/0.4/signalObstruction.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/siteIdentification.xml +22 -0
- slm/jinja2/slm/sitelog/xsd/0.4/siteLocation.xml +21 -0
- slm/jinja2/slm/sitelog/xsd/0.4/surveyedLocalTie.xml +20 -0
- slm/jinja2/slm/sitelog/xsd/0.4/temperatureSensor.xml +13 -0
- slm/jinja2/slm/sitelog/xsd/0.4/waterVaporSensor.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.5/document.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/geodesyml_0.4.xml +99 -0
- slm/jinja2/slm/sitelog/xsd/geodesyml_0.5.xml +112 -0
- slm/management/__init__.py +0 -0
- slm/management/commands/__init__.py +53 -0
- slm/management/commands/build_index.py +96 -0
- slm/management/commands/generate_sinex.py +675 -0
- slm/management/commands/head_from_index.py +541 -0
- slm/management/commands/import_archive.py +908 -0
- slm/management/commands/import_equipment.py +351 -0
- slm/management/commands/set_site.py +56 -0
- slm/management/commands/sitelog.py +144 -0
- slm/management/commands/synchronize.py +60 -0
- slm/management/commands/update_data_availability.py +167 -0
- slm/management/commands/validate_db.py +186 -0
- slm/management/commands/validate_gml.py +73 -0
- slm/map/__init__.py +1 -0
- slm/map/admin.py +5 -0
- slm/map/api/__init__.py +0 -0
- slm/map/api/edit/__init__.py +0 -0
- slm/map/api/edit/serializers.py +28 -0
- slm/map/api/edit/views.py +46 -0
- slm/map/api/public/__init__.py +0 -0
- slm/map/api/public/serializers.py +29 -0
- slm/map/api/public/views.py +64 -0
- slm/map/apps.py +7 -0
- slm/map/defines.py +53 -0
- slm/map/migrations/0001_initial.py +115 -0
- slm/map/migrations/__init__.py +0 -0
- slm/map/models.py +63 -0
- slm/map/static/slm/css/map.css +86 -0
- slm/map/static/slm/js/map.js +159 -0
- slm/map/templates/slm/map.html +374 -0
- slm/map/templates/slm/station/base.html +11 -0
- slm/map/templates/slm/station/edit.html +10 -0
- slm/map/templates/slm/top_nav.html +17 -0
- slm/map/templatetags/__init__.py +0 -0
- slm/map/templatetags/slm_map.py +18 -0
- slm/map/urls.py +25 -0
- slm/map/views.py +36 -0
- slm/middleware.py +29 -0
- slm/migrations/0001_alter_siteantenna_marker_enu_alter_sitelocation_llh_and_more.py +47 -0
- slm/migrations/0001_initial.py +4826 -0
- slm/migrations/0002_alter_dataavailability_site.py +22 -0
- slm/migrations/0003_remove_logentry_slm_logentr_site_lo_7a2af7_idx_and_more.py +80 -0
- slm/migrations/0004_alter_logentry_timestamp_and_more.py +25 -0
- slm/migrations/0005_alter_logentry_options_alter_logentry_section_and_more.py +46 -0
- slm/migrations/0006_alter_logentry_options_alter_logentry_index_together.py +24 -0
- slm/migrations/0007_alter_dataavailability_rate.py +23 -0
- slm/migrations/0008_alter_archiveindex_options_and_more.py +64 -0
- slm/migrations/0009_alter_archiveindex_end.py +21 -0
- slm/migrations/0010_alter_dataavailability_rinex_version_and_more.py +844 -0
- slm/migrations/0011_alter_siteidentification_fracture_spacing.py +33 -0
- slm/migrations/0012_alter_logentry_type.py +36 -0
- slm/migrations/0013_unpublishedfilesalert.py +48 -0
- slm/migrations/0014_sitelogpublished.py +48 -0
- slm/migrations/0015_alter_siteantenna_options_and_more.py +181 -0
- slm/migrations/0016_alter_antenna_description_alter_radome_description_and_more.py +42 -0
- slm/migrations/0017_alter_logentry_unique_together_and_more.py +54 -0
- slm/migrations/0018_afix_deleted.py +34 -0
- slm/migrations/0018_alter_siteantenna_options_and_more.py +244 -0
- slm/migrations/0019_remove_siteantenna_marker_enu_siteantenna_marker_une_and_more.py +101 -0
- slm/migrations/0020_alter_manufacturer_options.py +16 -0
- slm/migrations/0021_alter_siteform_report_type.py +23 -0
- slm/migrations/0022_rename_antcal_antenna_radome_slm_antcal_antenna_20827a_idx_and_more.py +297 -0
- slm/migrations/0023_archivedsitelog_gml_version_and_more.py +55 -0
- slm/migrations/0024_alter_agency_name_alter_agency_shortname.py +24 -0
- slm/migrations/0025_alter_archivedsitelog_log_format_and_more.py +61 -0
- slm/migrations/0026_alter_archivedsitelog_log_format_and_more.py +61 -0
- slm/migrations/0027_importalert_file_contents_importalert_findings_and_more.py +41 -0
- slm/migrations/0028_antenna_replaced_manufacturer_url_radome_replaced_and_more.py +46 -0
- slm/migrations/0029_manufacturer_full_name.py +17 -0
- slm/migrations/0030_alter_antenna_state_alter_radome_state_and_more.py +43 -0
- slm/migrations/__init__.py +0 -0
- slm/migrations/load_satellitesystems.py +27 -0
- slm/models/__init__.py +118 -0
- slm/models/about.py +14 -0
- slm/models/alerts.py +1204 -0
- slm/models/data.py +58 -0
- slm/models/equipment.py +229 -0
- slm/models/help.py +14 -0
- slm/models/index.py +428 -0
- slm/models/sitelog.py +4279 -0
- slm/models/system.py +723 -0
- slm/models/user.py +304 -0
- slm/parsing/__init__.py +786 -0
- slm/parsing/legacy/__init__.py +4 -0
- slm/parsing/legacy/binding.py +817 -0
- slm/parsing/legacy/parser.py +377 -0
- slm/parsing/xsd/__init__.py +34 -0
- slm/parsing/xsd/binding.py +86 -0
- slm/parsing/xsd/geodesyml/0.4/commonTypes.xsd +133 -0
- slm/parsing/xsd/geodesyml/0.4/contact.xsd +29 -0
- slm/parsing/xsd/geodesyml/0.4/dataStreams.xsd +129 -0
- slm/parsing/xsd/geodesyml/0.4/document.xsd +64 -0
- slm/parsing/xsd/geodesyml/0.4/equipment.xsd +427 -0
- slm/parsing/xsd/geodesyml/0.4/fieldMeasurement.xsd +170 -0
- slm/parsing/xsd/geodesyml/0.4/geodesyML.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.4/geodeticEquipment.xsd +343 -0
- slm/parsing/xsd/geodesyml/0.4/geodeticMonument.xsd +147 -0
- slm/parsing/xsd/geodesyml/0.4/lineage.xsd +614 -0
- slm/parsing/xsd/geodesyml/0.4/localInterferences.xsd +131 -0
- slm/parsing/xsd/geodesyml/0.4/measurement.xsd +473 -0
- slm/parsing/xsd/geodesyml/0.4/monumentInfo.xsd +251 -0
- slm/parsing/xsd/geodesyml/0.4/observationSystem.xsd +429 -0
- slm/parsing/xsd/geodesyml/0.4/project.xsd +38 -0
- slm/parsing/xsd/geodesyml/0.4/quality.xsd +176 -0
- slm/parsing/xsd/geodesyml/0.4/referenceFrame.xsd +194 -0
- slm/parsing/xsd/geodesyml/0.4/siteLog.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.5/commonTypes.xsd +133 -0
- slm/parsing/xsd/geodesyml/0.5/contact.xsd +29 -0
- slm/parsing/xsd/geodesyml/0.5/dataStreams.xsd +129 -0
- slm/parsing/xsd/geodesyml/0.5/document.xsd +64 -0
- slm/parsing/xsd/geodesyml/0.5/equipment.xsd +427 -0
- slm/parsing/xsd/geodesyml/0.5/fieldMeasurement.xsd +170 -0
- slm/parsing/xsd/geodesyml/0.5/geodesyML.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.5/geodeticEquipment.xsd +343 -0
- slm/parsing/xsd/geodesyml/0.5/geodeticMonument.xsd +147 -0
- slm/parsing/xsd/geodesyml/0.5/lineage.xsd +614 -0
- slm/parsing/xsd/geodesyml/0.5/localInterferences.xsd +131 -0
- slm/parsing/xsd/geodesyml/0.5/measurement.xsd +473 -0
- slm/parsing/xsd/geodesyml/0.5/monumentInfo.xsd +306 -0
- slm/parsing/xsd/geodesyml/0.5/observationSystem.xsd +429 -0
- slm/parsing/xsd/geodesyml/0.5/project.xsd +38 -0
- slm/parsing/xsd/geodesyml/0.5/quality.xsd +176 -0
- slm/parsing/xsd/geodesyml/0.5/referenceFrame.xsd +194 -0
- slm/parsing/xsd/geodesyml/0.5/siteLog.xsd +73 -0
- slm/parsing/xsd/parser.py +116 -0
- slm/parsing/xsd/resolver.py +28 -0
- slm/receivers/__init__.py +11 -0
- slm/receivers/alerts.py +87 -0
- slm/receivers/cleanup.py +41 -0
- slm/receivers/event_loggers.py +175 -0
- slm/receivers/index.py +67 -0
- slm/settings/__init__.py +55 -0
- slm/settings/auth.py +15 -0
- slm/settings/ckeditor.py +14 -0
- slm/settings/debug.py +47 -0
- slm/settings/internationalization.py +12 -0
- slm/settings/logging.py +113 -0
- slm/settings/platform/__init__.py +0 -0
- slm/settings/platform/darwin.py +10 -0
- slm/settings/rest.py +21 -0
- slm/settings/root.py +152 -0
- slm/settings/routines.py +43 -0
- slm/settings/secrets.py +37 -0
- slm/settings/security.py +5 -0
- slm/settings/slm.py +188 -0
- slm/settings/static_templates.py +53 -0
- slm/settings/templates.py +29 -0
- slm/settings/uploads.py +8 -0
- slm/settings/urls.py +126 -0
- slm/settings/validation.py +196 -0
- slm/signals.py +250 -0
- slm/singleton.py +49 -0
- slm/static/rest_framework/css/bootstrap-tweaks.css +204 -0
- slm/static/rest_framework/css/bootstrap.min.css +7 -0
- slm/static/rest_framework/css/bootstrap.min.css.map +1 -0
- slm/static/rest_framework/css/default.css +82 -0
- slm/static/rest_framework/css/prettify.css +30 -0
- slm/static/rest_framework/docs/css/base.css +344 -0
- slm/static/rest_framework/docs/css/highlight.css +125 -0
- slm/static/rest_framework/docs/css/jquery.json-view.min.css +11 -0
- slm/static/rest_framework/docs/img/favicon.ico +0 -0
- slm/static/rest_framework/docs/img/grid.png +0 -0
- slm/static/rest_framework/docs/js/api.js +321 -0
- slm/static/rest_framework/docs/js/highlight.pack.js +2 -0
- slm/static/rest_framework/docs/js/jquery.json-view.min.js +7 -0
- slm/static/rest_framework/img/grid.png +0 -0
- slm/static/rest_framework/js/ajax-form.js +127 -0
- slm/static/rest_framework/js/bootstrap.bundle.min.js +7 -0
- slm/static/rest_framework/js/bootstrap.bundle.min.js.map +1 -0
- slm/static/rest_framework/js/bootstrap.min.js.map +1 -0
- slm/static/rest_framework/js/coreapi-0.1.1.js +2043 -0
- slm/static/rest_framework/js/csrf.js +52 -0
- slm/static/rest_framework/js/default.js +47 -0
- slm/static/rest_framework/js/jquery-3.5.1.min.js +2 -0
- slm/static/rest_framework/js/prettify-min.js +28 -0
- slm/static/slm/css/admin.css +3 -0
- slm/static/slm/css/defines.css +82 -0
- slm/static/slm/css/forms.css +1 -0
- slm/static/slm/css/style.css +1004 -0
- slm/static/slm/img/email-branding.png +0 -0
- slm/static/slm/img/favicon.ico +0 -0
- slm/static/slm/img/login-bg.jpg +0 -0
- slm/static/slm/img/slm-logo.svg +4 -0
- slm/static/slm/js/autocomplete.js +341 -0
- slm/static/slm/js/enums.js +322 -0
- slm/static/slm/js/fileIcons.js +30 -0
- slm/static/slm/js/form.js +404 -0
- slm/static/slm/js/formWidget.js +23 -0
- slm/static/slm/js/persistable.js +33 -0
- slm/static/slm/js/slm.js +1028 -0
- slm/static/slm/js/time24.js +212 -0
- slm/static_templates/slm/css/defines.css +26 -0
- slm/static_templates/slm/js/enums.js +28 -0
- slm/static_templates/slm/js/fileIcons.js +16 -0
- slm/static_templates/slm/js/urls.js +5 -0
- slm/templates/account/base.html +20 -0
- slm/templates/account/email/base.html +43 -0
- slm/templates/account/email/base_message.txt +7 -0
- slm/templates/account/email/email_confirmation_message.html +16 -0
- slm/templates/account/email/email_confirmation_message.txt +7 -0
- slm/templates/account/email/email_confirmation_signup_message.html +1 -0
- slm/templates/account/email/email_confirmation_signup_message.txt +1 -0
- slm/templates/account/email/email_confirmation_signup_subject.txt +1 -0
- slm/templates/account/email/email_confirmation_subject.txt +4 -0
- slm/templates/account/email/password_reset_key_message.html +28 -0
- slm/templates/account/email/password_reset_key_message.txt +9 -0
- slm/templates/account/email/password_reset_key_subject.txt +4 -0
- slm/templates/account/email/unknown_account_message.html +25 -0
- slm/templates/account/email/unknown_account_message.txt +12 -0
- slm/templates/account/email/unknown_account_subject.txt +4 -0
- slm/templates/account/login.html +67 -0
- slm/templates/account/logout.html +38 -0
- slm/templates/account/password_change.html +48 -0
- slm/templates/account/password_reset.html +51 -0
- slm/templates/account/password_reset_done.html +20 -0
- slm/templates/account/password_reset_from_key.html +52 -0
- slm/templates/account/password_reset_from_key_done.html +17 -0
- slm/templates/admin/base.html +7 -0
- slm/templates/messages.html +8 -0
- slm/templates/rest_framework/README +16 -0
- slm/templates/rest_framework/admin/detail.html +10 -0
- slm/templates/rest_framework/admin/dict_value.html +11 -0
- slm/templates/rest_framework/admin/list.html +32 -0
- slm/templates/rest_framework/admin/list_value.html +11 -0
- slm/templates/rest_framework/admin/simple_list_value.html +2 -0
- slm/templates/rest_framework/admin.html +282 -0
- slm/templates/rest_framework/api.html +3 -0
- slm/templates/rest_framework/base.html +334 -0
- slm/templates/rest_framework/docs/auth/basic.html +42 -0
- slm/templates/rest_framework/docs/auth/session.html +40 -0
- slm/templates/rest_framework/docs/auth/token.html +41 -0
- slm/templates/rest_framework/docs/document.html +37 -0
- slm/templates/rest_framework/docs/error.html +71 -0
- slm/templates/rest_framework/docs/index.html +55 -0
- slm/templates/rest_framework/docs/interact.html +57 -0
- slm/templates/rest_framework/docs/langs/javascript-intro.html +5 -0
- slm/templates/rest_framework/docs/langs/javascript.html +15 -0
- slm/templates/rest_framework/docs/langs/python-intro.html +3 -0
- slm/templates/rest_framework/docs/langs/python.html +13 -0
- slm/templates/rest_framework/docs/langs/shell-intro.html +3 -0
- slm/templates/rest_framework/docs/langs/shell.html +6 -0
- slm/templates/rest_framework/docs/link.html +113 -0
- slm/templates/rest_framework/docs/sidebar.html +78 -0
- slm/templates/rest_framework/filters/base.html +16 -0
- slm/templates/rest_framework/filters/ordering.html +17 -0
- slm/templates/rest_framework/filters/search.html +13 -0
- slm/templates/rest_framework/horizontal/checkbox.html +23 -0
- slm/templates/rest_framework/horizontal/checkbox_multiple.html +32 -0
- slm/templates/rest_framework/horizontal/dict_field.html +11 -0
- slm/templates/rest_framework/horizontal/fieldset.html +16 -0
- slm/templates/rest_framework/horizontal/form.html +6 -0
- slm/templates/rest_framework/horizontal/input.html +21 -0
- slm/templates/rest_framework/horizontal/list_field.html +11 -0
- slm/templates/rest_framework/horizontal/list_fieldset.html +13 -0
- slm/templates/rest_framework/horizontal/radio.html +42 -0
- slm/templates/rest_framework/horizontal/select.html +36 -0
- slm/templates/rest_framework/horizontal/select_multiple.html +38 -0
- slm/templates/rest_framework/horizontal/textarea.html +21 -0
- slm/templates/rest_framework/inline/checkbox.html +8 -0
- slm/templates/rest_framework/inline/checkbox_multiple.html +14 -0
- slm/templates/rest_framework/inline/dict_field.html +9 -0
- slm/templates/rest_framework/inline/fieldset.html +6 -0
- slm/templates/rest_framework/inline/form.html +8 -0
- slm/templates/rest_framework/inline/input.html +9 -0
- slm/templates/rest_framework/inline/list_field.html +9 -0
- slm/templates/rest_framework/inline/list_fieldset.html +3 -0
- slm/templates/rest_framework/inline/radio.html +25 -0
- slm/templates/rest_framework/inline/select.html +24 -0
- slm/templates/rest_framework/inline/select_multiple.html +25 -0
- slm/templates/rest_framework/inline/textarea.html +9 -0
- slm/templates/rest_framework/login.html +3 -0
- slm/templates/rest_framework/login_base.html +65 -0
- slm/templates/rest_framework/pagination/numbers.html +47 -0
- slm/templates/rest_framework/pagination/previous_and_next.html +21 -0
- slm/templates/rest_framework/raw_data_form.html +11 -0
- slm/templates/rest_framework/schema.js +3 -0
- slm/templates/rest_framework/vertical/checkbox.html +16 -0
- slm/templates/rest_framework/vertical/checkbox_multiple.html +30 -0
- slm/templates/rest_framework/vertical/dict_field.html +7 -0
- slm/templates/rest_framework/vertical/fieldset.html +13 -0
- slm/templates/rest_framework/vertical/form.html +6 -0
- slm/templates/rest_framework/vertical/input.html +17 -0
- slm/templates/rest_framework/vertical/list_field.html +7 -0
- slm/templates/rest_framework/vertical/list_fieldset.html +7 -0
- slm/templates/rest_framework/vertical/radio.html +40 -0
- slm/templates/rest_framework/vertical/select.html +34 -0
- slm/templates/rest_framework/vertical/select_multiple.html +31 -0
- slm/templates/rest_framework/vertical/textarea.html +17 -0
- slm/templates/slm/about.html +21 -0
- slm/templates/slm/alerts/alert.html +15 -0
- slm/templates/slm/alerts/geodesymlinvalid.html +8 -0
- slm/templates/slm/alerts/importalert.html +10 -0
- slm/templates/slm/alerts.html +18 -0
- slm/templates/slm/auth_menu.html +41 -0
- slm/templates/slm/base.html +195 -0
- slm/templates/slm/emails/alert_issued.html +31 -0
- slm/templates/slm/emails/alert_issued.txt +9 -0
- slm/templates/slm/emails/base.html +6 -0
- slm/templates/slm/emails/changes_rejected.txt +7 -0
- slm/templates/slm/emails/review_requested.txt +7 -0
- slm/templates/slm/forms/widgets/auto_complete.html +21 -0
- slm/templates/slm/forms/widgets/auto_complete_multiple.html +18 -0
- slm/templates/slm/forms/widgets/checkbox_multiple.html +6 -0
- slm/templates/slm/forms/widgets/inline_multi.html +1 -0
- slm/templates/slm/forms/widgets/splitdatetime.html +14 -0
- slm/templates/slm/forms/widgets/time24.html +37 -0
- slm/templates/slm/help.html +54 -0
- slm/templates/slm/messages.html +13 -0
- slm/templates/slm/new_site.html +88 -0
- slm/templates/slm/profile.html +57 -0
- slm/templates/slm/register.html +40 -0
- slm/templates/slm/reports/file_log.html +43 -0
- slm/templates/slm/reports/head_log.html +23 -0
- slm/templates/slm/reports/head_report.html +55 -0
- slm/templates/slm/reports/index_log.html +23 -0
- slm/templates/slm/reports/index_report.html +71 -0
- slm/templates/slm/station/alert.html +8 -0
- slm/templates/slm/station/alerts.html +19 -0
- slm/templates/slm/station/base.html +104 -0
- slm/templates/slm/station/download.html +87 -0
- slm/templates/slm/station/edit.html +283 -0
- slm/templates/slm/station/form.html +110 -0
- slm/templates/slm/station/log.html +18 -0
- slm/templates/slm/station/review.html +461 -0
- slm/templates/slm/station/upload.html +295 -0
- slm/templates/slm/station/uploads/attachment.html +20 -0
- slm/templates/slm/station/uploads/geodesyml.html +1 -0
- slm/templates/slm/station/uploads/image.html +27 -0
- slm/templates/slm/station/uploads/json.html +0 -0
- slm/templates/slm/station/uploads/legacy.html +77 -0
- slm/templates/slm/top_nav.html +14 -0
- slm/templates/slm/user_activity.html +16 -0
- slm/templates/slm/widgets/alert_scroll.html +135 -0
- slm/templates/slm/widgets/filelist.html +258 -0
- slm/templates/slm/widgets/legend.html +12 -0
- slm/templates/slm/widgets/log_scroll.html +88 -0
- slm/templates/slm/widgets/stationlist.html +233 -0
- slm/templatetags/__init__.py +0 -0
- slm/templatetags/jinja2.py +9 -0
- slm/templatetags/slm.py +459 -0
- slm/urls.py +148 -0
- slm/utils.py +299 -0
- slm/validators.py +297 -0
- slm/views.py +654 -0
- slm/widgets.py +134 -0
slm/authentication.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is taken and modified from here: https://github.com/ahknight/drf-httpsig
|
|
3
|
+
|
|
4
|
+
There is an http signature IETF standard in the works, presumably a more mature and maintained
|
|
5
|
+
library will emerge at some point - when that happens this should be replaced with that one.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from functools import lru_cache
|
|
9
|
+
|
|
10
|
+
from allauth.account import app_settings
|
|
11
|
+
from allauth.account.adapter import get_adapter
|
|
12
|
+
from allauth.account.app_settings import AuthenticationMethod # do not remove!
|
|
13
|
+
from allauth.account.forms import EmailAwarePasswordResetTokenGenerator
|
|
14
|
+
from allauth.account.utils import user_pk_to_url_str, user_username
|
|
15
|
+
from allauth.utils import build_absolute_uri
|
|
16
|
+
from django.conf import settings
|
|
17
|
+
from django.contrib.auth import get_user_model
|
|
18
|
+
from django.contrib.sites.shortcuts import get_current_site
|
|
19
|
+
from django.urls import reverse
|
|
20
|
+
from django.utils.module_loading import import_string
|
|
21
|
+
from rest_framework import authentication, exceptions
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
Reusing failure exceptions serves several purposes:
|
|
25
|
+
1. Lack of useful information regarding the failure inhibits attackers
|
|
26
|
+
from learning about valid keyIDs or other forms of information leakage.
|
|
27
|
+
Using the same actual object for any failure makes preventing such
|
|
28
|
+
leakage through mistakenly-distinct error messages less likely.
|
|
29
|
+
2. In an API scenario, the object is created once and raised many times
|
|
30
|
+
rather than generated on every failure, which could lead to higher loads
|
|
31
|
+
or memory usage in high-volume attack scenarios.
|
|
32
|
+
"""
|
|
33
|
+
FAILED = exceptions.AuthenticationFailed("Invalid signature.")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SignatureAuthentication(authentication.BaseAuthentication):
|
|
37
|
+
"""
|
|
38
|
+
DRF authentication class for HTTP Signature support.
|
|
39
|
+
|
|
40
|
+
You must subclass this class in your own project and implement the
|
|
41
|
+
`fetch_user_data(self, keyId, algorithm)` method, returning a tuple of
|
|
42
|
+
the User object and a bytes object containing the user's secret. Note
|
|
43
|
+
that key_id and algorithm are DIRTY as they are supplied by the client
|
|
44
|
+
and so must be verified in your subclass!
|
|
45
|
+
|
|
46
|
+
You may set the following class properties in your subclass to configure
|
|
47
|
+
authentication for your particular use case:
|
|
48
|
+
|
|
49
|
+
:param www_authenticate_realm: Default: "api"
|
|
50
|
+
:param required_headers: Default: ["(request-target)", "date"]
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
www_authenticate_realm = "api"
|
|
54
|
+
required_headers = ["date"]
|
|
55
|
+
|
|
56
|
+
def fetch_user_data(self, api_key, algorithm="hmac-sha256"):
|
|
57
|
+
"""Retuns a tuple (User, secret) or (None, None)."""
|
|
58
|
+
try:
|
|
59
|
+
user = get_user_model().objects.get(username=api_key)
|
|
60
|
+
if not user.is_active:
|
|
61
|
+
return None, None
|
|
62
|
+
secret = user.secret
|
|
63
|
+
if isinstance(secret, memoryview):
|
|
64
|
+
secret = secret.tobytes()
|
|
65
|
+
return user, secret
|
|
66
|
+
except get_user_model().DoesNotExist:
|
|
67
|
+
return None, None
|
|
68
|
+
|
|
69
|
+
def authenticate_header(self, request):
|
|
70
|
+
"""
|
|
71
|
+
DRF sends this for unauthenticated responses if we're the primary
|
|
72
|
+
authenticator.
|
|
73
|
+
"""
|
|
74
|
+
h = " ".join(self.required_headers)
|
|
75
|
+
return 'Signature realm="%s",headers="%s"' % (self.www_authenticate_realm, h)
|
|
76
|
+
|
|
77
|
+
def authenticate(self, request):
|
|
78
|
+
from httpsig import HeaderVerifier, utils
|
|
79
|
+
|
|
80
|
+
"""
|
|
81
|
+
Perform the actual authentication.
|
|
82
|
+
|
|
83
|
+
Note that the exception raised is always the same. This is so that we
|
|
84
|
+
don't leak information about in/valid keyIds and other such useful
|
|
85
|
+
things.
|
|
86
|
+
"""
|
|
87
|
+
auth_header = authentication.get_authorization_header(request)
|
|
88
|
+
if not auth_header or len(auth_header) == 0:
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
method, fields = utils.parse_authorization_header(auth_header)
|
|
92
|
+
|
|
93
|
+
# Ignore foreign Authorization headers.
|
|
94
|
+
if method.lower() != "signature":
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
# Verify basic header structure.
|
|
98
|
+
if len(fields) == 0:
|
|
99
|
+
raise FAILED
|
|
100
|
+
|
|
101
|
+
# Ensure all required fields were included.
|
|
102
|
+
if len(set(("keyid", "algorithm", "signature")) - set(fields.keys())) > 0:
|
|
103
|
+
raise FAILED
|
|
104
|
+
|
|
105
|
+
# Fetch the secret associated with the keyid
|
|
106
|
+
user, secret = self.fetch_user_data(
|
|
107
|
+
fields["keyid"], algorithm=fields["algorithm"]
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if not (user and secret):
|
|
111
|
+
raise FAILED
|
|
112
|
+
|
|
113
|
+
# Gather all request headers and translate them as stated in the Django docs:
|
|
114
|
+
# https://docs.djangoproject.com/en/1.6/ref/request-response/#django.http.HttpRequest.META
|
|
115
|
+
headers = {}
|
|
116
|
+
for key in request.META.keys():
|
|
117
|
+
if key.startswith("HTTP_") or key in ("CONTENT_TYPE", "CONTENT_LENGTH"):
|
|
118
|
+
header = key[5:].lower().replace("_", "-")
|
|
119
|
+
headers[header] = request.META[key]
|
|
120
|
+
|
|
121
|
+
# Verify headers
|
|
122
|
+
hs = HeaderVerifier(
|
|
123
|
+
headers,
|
|
124
|
+
secret,
|
|
125
|
+
required_headers=self.required_headers,
|
|
126
|
+
method=request.method.lower(),
|
|
127
|
+
path=request.get_full_path(),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# All of that just to get to this.
|
|
131
|
+
if not hs.verify():
|
|
132
|
+
raise FAILED
|
|
133
|
+
|
|
134
|
+
return (user, fields["keyid"])
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def initiate_password_resets(users, request=None):
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
:param users: Either an iterable (including queryset) of user accounts or
|
|
141
|
+
a single user account.
|
|
142
|
+
:return:
|
|
143
|
+
"""
|
|
144
|
+
if isinstance(users, get_user_model()):
|
|
145
|
+
users = [users]
|
|
146
|
+
|
|
147
|
+
token_generator = EmailAwarePasswordResetTokenGenerator()
|
|
148
|
+
|
|
149
|
+
for user in users:
|
|
150
|
+
temp_key = token_generator.make_token(user)
|
|
151
|
+
|
|
152
|
+
# send the password reset email
|
|
153
|
+
path = reverse(
|
|
154
|
+
"account_reset_password_from_key",
|
|
155
|
+
kwargs=dict(uidb36=user_pk_to_url_str(user), key=temp_key),
|
|
156
|
+
)
|
|
157
|
+
url = build_absolute_uri(request, path)
|
|
158
|
+
|
|
159
|
+
context = {
|
|
160
|
+
"current_site": get_current_site(request),
|
|
161
|
+
"user": user,
|
|
162
|
+
"password_reset_url": url,
|
|
163
|
+
"request": request,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if app_settings.AUTHENTICATION_METHOD != AuthenticationMethod.EMAIL:
|
|
167
|
+
context["username"] = user_username(user)
|
|
168
|
+
|
|
169
|
+
get_adapter(request).send_mail(
|
|
170
|
+
"account/email/password_reset_key", user.email, context
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@lru_cache(maxsize=None)
|
|
175
|
+
def permissions():
|
|
176
|
+
try:
|
|
177
|
+
return import_string(
|
|
178
|
+
getattr(
|
|
179
|
+
settings, "SLM_PERMISSIONS", "slm.authentication.default_permissions"
|
|
180
|
+
)
|
|
181
|
+
)().all()
|
|
182
|
+
except ImportError:
|
|
183
|
+
# this is not critical don't make it mean! - so we fail quietly
|
|
184
|
+
# a check for this setting is performed in check
|
|
185
|
+
from django.contrib.auth.models import Permission
|
|
186
|
+
|
|
187
|
+
return Permission.objects.all()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def default_permissions():
|
|
191
|
+
from django.contrib.auth import get_user_model
|
|
192
|
+
from django.contrib.auth.models import Permission
|
|
193
|
+
from django.contrib.contenttypes.models import ContentType
|
|
194
|
+
|
|
195
|
+
return Permission.objects.filter(
|
|
196
|
+
content_type=ContentType.objects.get_for_model(get_user_model()),
|
|
197
|
+
codename__in=[perm[0] for perm in get_user_model()._meta.permissions],
|
|
198
|
+
)
|
slm/bin/__init__.py
ADDED
|
File without changes
|
slm/bin/startproject.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from urllib.parse import urlparse
|
|
6
|
+
|
|
7
|
+
import django
|
|
8
|
+
from django.conf import settings
|
|
9
|
+
from django_typer.completers import complete_path
|
|
10
|
+
from render_static.engine import StaticTemplateEngine
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.markdown import Markdown
|
|
13
|
+
from typer import Argument, Option, Typer, secho
|
|
14
|
+
from typing_extensions import Annotated
|
|
15
|
+
|
|
16
|
+
import slm
|
|
17
|
+
|
|
18
|
+
template_dir = Path(__file__).parent / "templates"
|
|
19
|
+
|
|
20
|
+
app = Typer()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def yes(response):
|
|
24
|
+
return not response or response.lower() in ["y", "yes", "true", "1"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
REPORT_MARKDOWN = """
|
|
28
|
+
## SLM Project Information
|
|
29
|
+
|
|
30
|
+
**Your project has been written to:** `{output}`
|
|
31
|
+
|
|
32
|
+
- **Develop settings:** `{develop}`
|
|
33
|
+
- **Production settings:** `{production}`
|
|
34
|
+
- **Manage Script:** `{site}`
|
|
35
|
+
- **Package Config:** `{pyproject}`
|
|
36
|
+
|
|
37
|
+
### Installation Instructions
|
|
38
|
+
|
|
39
|
+
1. Create a database called `{site}`.
|
|
40
|
+
|
|
41
|
+
2. Use `poetry` to install your project's virtual environment:
|
|
42
|
+
|
|
43
|
+
{install_poetry}
|
|
44
|
+
|
|
45
|
+
Install dependencies:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
poetry install
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
3. To install your database and import existing sitelogs, run:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
{site} routine install
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
4. To run the development server, run:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
network runserver
|
|
61
|
+
```
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
INSTALL_POETRY = """
|
|
65
|
+
**You do not have `poetry` installed, see**: https://python-poetry.org/docs/#installing-with-the-official-installer
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@app.command(
|
|
70
|
+
help="Create a directory structure for an slm deployment. This includes settings files and an extension app. You can change any names or settings at a later time!"
|
|
71
|
+
)
|
|
72
|
+
def main(
|
|
73
|
+
netloc: Annotated[
|
|
74
|
+
str,
|
|
75
|
+
Argument(
|
|
76
|
+
help="The network location of your production deployment will be hosted on. (e.g. slm.igs.org)",
|
|
77
|
+
show_default=False,
|
|
78
|
+
),
|
|
79
|
+
],
|
|
80
|
+
directory: Annotated[Path, Argument(shell_complete=complete_path)] = os.getcwd(),
|
|
81
|
+
organization: Annotated[
|
|
82
|
+
str,
|
|
83
|
+
Option(
|
|
84
|
+
prompt="What is the name of your organization?",
|
|
85
|
+
help="What is the name of your organization?"
|
|
86
|
+
),
|
|
87
|
+
] = "",
|
|
88
|
+
project_dir: Annotated[
|
|
89
|
+
str,
|
|
90
|
+
Option(
|
|
91
|
+
prompt="What should we name your project directory?",
|
|
92
|
+
help="What should we name your project directory?",
|
|
93
|
+
),
|
|
94
|
+
] = "{subdomain}",
|
|
95
|
+
package_name: Annotated[
|
|
96
|
+
str,
|
|
97
|
+
Option(
|
|
98
|
+
prompt="What should we name your installable wheel?",
|
|
99
|
+
help="What should we name your installable wheel?",
|
|
100
|
+
),
|
|
101
|
+
] = "{project_dir}",
|
|
102
|
+
site: Annotated[
|
|
103
|
+
str,
|
|
104
|
+
Option(
|
|
105
|
+
prompt="What is the name of your site?",
|
|
106
|
+
help="What is the name of your site?",
|
|
107
|
+
),
|
|
108
|
+
] = "{subdomain}",
|
|
109
|
+
production_dir: Annotated[
|
|
110
|
+
str,
|
|
111
|
+
Option(
|
|
112
|
+
prompt="Where should files live in production?",
|
|
113
|
+
help="Where should files live in production?",
|
|
114
|
+
),
|
|
115
|
+
] = "/var/www/{site}/production",
|
|
116
|
+
extension_app: Annotated[
|
|
117
|
+
str,
|
|
118
|
+
Option(
|
|
119
|
+
prompt="What should we call your custom Django app?",
|
|
120
|
+
help="What should we call your custom Django app?",
|
|
121
|
+
),
|
|
122
|
+
] = "{org}_extensions",
|
|
123
|
+
include_map: Annotated[
|
|
124
|
+
bool,
|
|
125
|
+
Option(
|
|
126
|
+
"--include-map",
|
|
127
|
+
prompt="Install the mapbox map app?",
|
|
128
|
+
help="Install the mapbox map app?",
|
|
129
|
+
),
|
|
130
|
+
] = False,
|
|
131
|
+
use_igs_validation: Annotated[
|
|
132
|
+
bool,
|
|
133
|
+
Option(
|
|
134
|
+
"--use-igs-validation",
|
|
135
|
+
prompt="Use IGS sitelog validation defaults?",
|
|
136
|
+
help="Use IGS sitelog validation defaults?",
|
|
137
|
+
),
|
|
138
|
+
] = False
|
|
139
|
+
):
|
|
140
|
+
netloc = (urlparse(netloc).netloc or netloc).lower()
|
|
141
|
+
parts = netloc.split(".")
|
|
142
|
+
if len(parts) == 2:
|
|
143
|
+
subdomain = "www"
|
|
144
|
+
domain = parts[0]
|
|
145
|
+
elif len(parts) > 2:
|
|
146
|
+
subdomain = parts[0]
|
|
147
|
+
domain = parts[1]
|
|
148
|
+
else:
|
|
149
|
+
secho("Unable to interpret network location: {netloc}".format(netloc=netloc), fg="red")
|
|
150
|
+
sys.exit(1)
|
|
151
|
+
|
|
152
|
+
if extension_app == "slm":
|
|
153
|
+
secho(
|
|
154
|
+
'extension_app cannot be "slm" this will clash with the slm namespace.',
|
|
155
|
+
fg="red",
|
|
156
|
+
)
|
|
157
|
+
sys.exit(1)
|
|
158
|
+
|
|
159
|
+
if "." in extension_app:
|
|
160
|
+
secho(
|
|
161
|
+
f'extension_app ({extension_app}) cannot have any "." in its name.',
|
|
162
|
+
fg="red",
|
|
163
|
+
)
|
|
164
|
+
sys.exit(1)
|
|
165
|
+
|
|
166
|
+
settings.configure(
|
|
167
|
+
INSTALLED_APPS=[],
|
|
168
|
+
DEBUG=False,
|
|
169
|
+
TEMPLATES=[{"BACKEND": "django.template.backends.django.DjangoTemplates"}],
|
|
170
|
+
)
|
|
171
|
+
django.setup()
|
|
172
|
+
|
|
173
|
+
engine = StaticTemplateEngine(
|
|
174
|
+
{
|
|
175
|
+
"ENGINES": [
|
|
176
|
+
{
|
|
177
|
+
"BACKEND": "render_static.backends.StaticDjangoTemplates",
|
|
178
|
+
"DIRS": [template_dir],
|
|
179
|
+
"OPTIONS": {
|
|
180
|
+
"loaders": ["render_static.loaders.StaticFilesystemBatchLoader"]
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
if not organization:
|
|
187
|
+
organization = domain.title()
|
|
188
|
+
org = organization.replace(" ", "_").lower()
|
|
189
|
+
extension_app = extension_app.format(org=(org or "slm"))
|
|
190
|
+
site = site.format(subdomain=subdomain).replace(" ", "_").lower()
|
|
191
|
+
project_dir = project_dir.format(subdomain=subdomain)
|
|
192
|
+
package_name = package_name.format(project_dir=project_dir)
|
|
193
|
+
|
|
194
|
+
# find site packages dir
|
|
195
|
+
local_slm = None
|
|
196
|
+
slm_pth = Path(slm.__file__).parent
|
|
197
|
+
for pth in (Path(pth) for pth in sys.path):
|
|
198
|
+
if pth.name == "site-packages":
|
|
199
|
+
if pth not in slm_pth.parents:
|
|
200
|
+
if yes(
|
|
201
|
+
input(
|
|
202
|
+
"It looks like you are using a local clone of the SLM, would "
|
|
203
|
+
"you prefer to use this instead of a release on pypi? (Y/n): "
|
|
204
|
+
)
|
|
205
|
+
):
|
|
206
|
+
local_slm = os.path.relpath(
|
|
207
|
+
slm_pth.parent, directory.absolute().resolve() / project_dir
|
|
208
|
+
)
|
|
209
|
+
break
|
|
210
|
+
|
|
211
|
+
ctx = {
|
|
212
|
+
"netloc": netloc,
|
|
213
|
+
"subdomain": subdomain,
|
|
214
|
+
"organization": organization,
|
|
215
|
+
"org": org,
|
|
216
|
+
"project_dir": project_dir,
|
|
217
|
+
"site": site,
|
|
218
|
+
"production_dir": production_dir.format(site=site),
|
|
219
|
+
"slm_version": slm.__version__,
|
|
220
|
+
"extension_app_class": extension_app.title().replace(" ", "").replace("_", ""),
|
|
221
|
+
"extension_app": extension_app.replace(" ", "_").lower(),
|
|
222
|
+
"include_map": include_map,
|
|
223
|
+
"use_igs_validation": use_igs_validation,
|
|
224
|
+
"package_name": package_name.replace("_", "-").replace(" ", "-"),
|
|
225
|
+
"local_slm": local_slm,
|
|
226
|
+
}
|
|
227
|
+
engine.render_to_disk(
|
|
228
|
+
"{{ project_dir }}/**",
|
|
229
|
+
context=ctx,
|
|
230
|
+
dest=directory,
|
|
231
|
+
exclude=[template_dir / "{{ project_dir }}/{{ extension_app }}/templates"],
|
|
232
|
+
)
|
|
233
|
+
engine.render_to_disk(
|
|
234
|
+
"{{ project_dir }}/{{ extension_app }}/templates/**",
|
|
235
|
+
context=ctx,
|
|
236
|
+
dest=directory,
|
|
237
|
+
render_contents=False,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
output = (directory / project_dir).absolute().resolve()
|
|
241
|
+
assert output.is_dir() and output.exists()
|
|
242
|
+
|
|
243
|
+
Console().print(
|
|
244
|
+
Markdown(
|
|
245
|
+
REPORT_MARKDOWN.format(
|
|
246
|
+
output=output,
|
|
247
|
+
develop=(output / "sites" / site / "develop/__init__.py").relative_to(
|
|
248
|
+
output
|
|
249
|
+
),
|
|
250
|
+
production=(
|
|
251
|
+
output / "sites" / site / "production/__init__.py"
|
|
252
|
+
).relative_to(output),
|
|
253
|
+
site=site,
|
|
254
|
+
install_poetry=INSTALL_POETRY if not shutil.which("poetry") else "",
|
|
255
|
+
pyproject=(output / "pyproject.toml").relative_to(output),
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
if __name__ == "__main__":
|
|
262
|
+
app()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "{{ package_name }}"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = []
|
|
6
|
+
|
|
7
|
+
packages = [
|
|
8
|
+
{ include = "{{ extension_app }}" },
|
|
9
|
+
{ include = "sites" },
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
exclude = ["**/test"]
|
|
13
|
+
|
|
14
|
+
[tool.poetry.scripts]
|
|
15
|
+
{{ site }} = "sites.{{ site }}.manage:main"
|
|
16
|
+
|
|
17
|
+
[tool.poetry.dependencies]
|
|
18
|
+
python = "^3.8"
|
|
19
|
+
{% if local_slm %}
|
|
20
|
+
igs-slm = { path = "{{ local_slm }}", develop = true }
|
|
21
|
+
#igs-slm = "^{{ slm_version }}"
|
|
22
|
+
{% else %}
|
|
23
|
+
igs-slm = "^{{ slm_version }}"
|
|
24
|
+
{% endif %}
|
|
25
|
+
|
|
26
|
+
[tool.poetry.group.dev.dependencies]
|
|
27
|
+
django-extensions = "^3.1.5"
|
|
28
|
+
ipython = "^8.12.2"
|
|
29
|
+
ipdb = "^0.12"
|
|
30
|
+
django-debug-toolbar = "^4.0.0"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["poetry-core>=1.0.0"]
|
|
35
|
+
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from split_settings.tools import include, optional
|
|
2
|
+
from slm.settings import resource, set_default, get_setting
|
|
3
|
+
|
|
4
|
+
set_default("SLM_ORG_NAME", "{{ organization }}")
|
|
5
|
+
include(resource("slm.settings", "root.py"))
|
|
6
|
+
include(optional('./validation.py'))
|
|
7
|
+
|
|
8
|
+
INSTALLED_APPS = [
|
|
9
|
+
"{{ extension_app }}",
|
|
10
|
+
{% if not include_map %}# {% endif %}"slm.map",
|
|
11
|
+
*get_setting("INSTALLED_APPS", [])
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
ROOT_URLCONF = "sites.{{ site }}.urls"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is the local Django configuration for the development configuration of your SLM
|
|
3
|
+
project.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from split_settings.tools import (
|
|
7
|
+
include,
|
|
8
|
+
optional
|
|
9
|
+
)
|
|
10
|
+
from slm.settings import set_default
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
SITE_DIR = Path(__file__).resolve().parent
|
|
14
|
+
BASE_DIR = SITE_DIR
|
|
15
|
+
|
|
16
|
+
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
|
|
17
|
+
|
|
18
|
+
DEBUG = True
|
|
19
|
+
DJANGO_DEBUG_TOOLBAR = True
|
|
20
|
+
|
|
21
|
+
include('../base.py')
|
|
22
|
+
|
|
23
|
+
set_default("SILENCED_SYSTEM_CHECKS", []).extend([
|
|
24
|
+
"security.W004",
|
|
25
|
+
"security.W008",
|
|
26
|
+
"security.W018"
|
|
27
|
+
])
|
|
28
|
+
|
|
29
|
+
# Special configuration parameters for your local development instance should be
|
|
30
|
+
# placed here:
|
|
31
|
+
include(optional('local.py'))
|
|
32
|
+
|
|
33
|
+
set_default(
|
|
34
|
+
'DATABASES',
|
|
35
|
+
{
|
|
36
|
+
'default': {
|
|
37
|
+
'ENGINE': 'django.contrib.gis.db.backends.postgis',
|
|
38
|
+
'NAME': '{{ site }}',
|
|
39
|
+
'USER': 'postgres',
|
|
40
|
+
'PASSWORD': '',
|
|
41
|
+
'ATOMIC_REQUESTS': True,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
WSGI_APPLICATION = "sites.{{ site }}.develop.wsgi.application"
|
|
47
|
+
|
|
48
|
+
CACHES = {
|
|
49
|
+
'default': {
|
|
50
|
+
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
INSTALLED_APPS.insert(1, 'django_extensions')
|
|
55
|
+
|
|
56
|
+
SECURE_SSL_REDIRECT = False
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WSGI config for SLM production deployment.
|
|
3
|
+
|
|
4
|
+
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
5
|
+
|
|
6
|
+
For more information on this file, see
|
|
7
|
+
https://docs.djangoproject.com/en/stable/howto/deployment/wsgi/
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from django.core.wsgi import get_wsgi_application
|
|
13
|
+
|
|
14
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', "sites.{{ site }}.develop")
|
|
15
|
+
|
|
16
|
+
application = get_wsgi_application()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Load SLM in management mode and run management commands."""
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Use SLM_DEPLOYMENT environment variable to switch between deployments. In
|
|
7
|
+
# production you may want to just set this to "production" in your
|
|
8
|
+
# administrative user's shell profile
|
|
9
|
+
def main(default_settings: str = f"sites.{{ site }}.{os.environ.get('SLM_DEPLOYMENT', 'develop')}"):
|
|
10
|
+
"""Run administrative tasks."""
|
|
11
|
+
|
|
12
|
+
# SLM configures loggers differently when running management commands so we can
|
|
13
|
+
# distinguish logs on the server that were from requests or admin tasks. This
|
|
14
|
+
# environment variable is used to signal that the SLM runtime is in management
|
|
15
|
+
# mode.
|
|
16
|
+
if len(sys.argv) > 1 and sys.argv[1] != "runserver":
|
|
17
|
+
os.environ['SLM_MANAGEMENT_FLAG'] = 'ON'
|
|
18
|
+
|
|
19
|
+
# Django bootstraps off the settings file defined in this import path.
|
|
20
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', default_settings)
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from django.core.management import execute_from_command_line
|
|
24
|
+
except ImportError as exc:
|
|
25
|
+
raise ImportError(
|
|
26
|
+
"Couldn't import Django. Are you sure it's installed and "
|
|
27
|
+
"available on your PYTHONPATH environment variable? Did you "
|
|
28
|
+
"forget to activate a virtual environment?"
|
|
29
|
+
) from exc
|
|
30
|
+
execute_from_command_line(sys.argv)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
main()
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from split_settings.tools import include
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import getpass
|
|
4
|
+
|
|
5
|
+
WSGI_APPLICATION = "sites.{{ site }}.production.wsgi.application"
|
|
6
|
+
|
|
7
|
+
DEBUG = False
|
|
8
|
+
SITE_DIR = Path("{{ production_dir }}")
|
|
9
|
+
BASE_DIR = SITE_DIR
|
|
10
|
+
|
|
11
|
+
ALLOWED_HOSTS = [
|
|
12
|
+
'{{ netloc }}',
|
|
13
|
+
# in some production configurations you may need to add your server's ip address
|
|
14
|
+
# to this list
|
|
15
|
+
]
|
|
16
|
+
SLM_SITE_NAME = '{{ netloc }}'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
MEDIA_ROOT = SITE_DIR / 'media'
|
|
20
|
+
STATIC_ROOT = SITE_DIR / 'static'
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# This section deals with database connection. Alterations may need to be made for
|
|
24
|
+
# deployment. We recommend running a database locally and using postgres user
|
|
25
|
+
# authentication and disallowing any non-local connections. This means your database
|
|
26
|
+
# is as secure as the system user running your SLM deployment.
|
|
27
|
+
#
|
|
28
|
+
# You may of course, use any number of database settings or have multiple databases:
|
|
29
|
+
# https://docs.djangoproject.com/en/stable/ref/databases/
|
|
30
|
+
DATABASES = {
|
|
31
|
+
'default': {
|
|
32
|
+
'ENGINE': 'django.contrib.gis.db.backends.postgis',
|
|
33
|
+
'NAME': '{{ site }}',
|
|
34
|
+
'USER': getpass.getuser(), # if postgres is configured for user authentication
|
|
35
|
+
'ATOMIC_REQUESTS': True
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# The SLM uses geodjango. Unless gdal and geos are in standard locations on your production
|
|
40
|
+
# server you will have to set their paths explicitly here:
|
|
41
|
+
# https://docs.djangoproject.com/en/stable/ref/contrib/gis/install/geolibs/
|
|
42
|
+
# TODO
|
|
43
|
+
# GDAL_LIBRARY_PATH = "/path/to/libgdal.so"
|
|
44
|
+
# GEOS_LIBRARY_PATH = '/path/to/libgeos_c.so.1'
|
|
45
|
+
|
|
46
|
+
# Make sure debug toolbar is not run in production - it can expose secrets!
|
|
47
|
+
DJANGO_DEBUG_TOOLBAR = False
|
|
48
|
+
|
|
49
|
+
include('../base.py')
|
|
50
|
+
|
|
51
|
+
# ADMINS will receive email notifications when exceptions are encountered or 500 errors
|
|
52
|
+
# returned to user requests
|
|
53
|
+
ADMINS = [
|
|
54
|
+
#("Your Name", "Email Address")
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
# Change this setting if you would like the links serialized into site logs or geodesyml
|
|
58
|
+
# files to use a different domain than the one of this deployment.
|
|
59
|
+
# For example, IGS's SLM is running on https://slm.igs.org but our public facing downloads
|
|
60
|
+
# are from https://network.igs.org
|
|
61
|
+
# SLM_FILE_DOMAIN = 'https://{{ netloc }}'
|