From 40a4fe974fa81ef18a90c2e4dbeb6e7a88e6a0c8 Mon Sep 17 00:00:00 2001 From: App Generator <51070104+app-generator@users.noreply.github.com> Date: Tue, 6 Jun 2023 11:03:31 +0300 Subject: [PATCH] Codebase Update --- .dockerignore | 5 + .env | 14 + .gitignore | 36 + Dockerfile | 24 + README.md | 254 +- apps/__init__.py | 48 + apps/authentication/__init__.py | 12 + apps/authentication/forms.py | 31 + apps/authentication/models.py | 57 + apps/authentication/oauth.py | 58 + apps/authentication/routes.py | 133 + apps/authentication/util.py | 34 + apps/config.py | 59 + apps/home/__init__.py | 12 + apps/home/routes.py | 54 + apps/static/assets/css/black-dashboard.css | 13329 ++++++++++++++++ .../static/assets/css/black-dashboard.css.map | 1 + .../static/assets/css/black-dashboard.min.css | 22 + apps/static/assets/css/nucleo-icons.css | 550 + apps/static/assets/css/theme-switcher.css | 58 + apps/static/assets/demo/demo.css | 63 + apps/static/assets/demo/demo.js | 742 + apps/static/assets/fonts/nucleo.eot | Bin 0 -> 26524 bytes apps/static/assets/fonts/nucleo.ttf | Bin 0 -> 26364 bytes apps/static/assets/fonts/nucleo.woff | Bin 0 -> 15168 bytes apps/static/assets/fonts/nucleo.woff2 | Bin 0 -> 12616 bytes apps/static/assets/img/12345.png | Bin 0 -> 1682267 bytes apps/static/assets/img/anime3.png | Bin 0 -> 37930 bytes apps/static/assets/img/anime6.png | Bin 0 -> 39891 bytes apps/static/assets/img/apple-icon.png | Bin 0 -> 2446 bytes apps/static/assets/img/bg5.jpg | Bin 0 -> 213199 bytes apps/static/assets/img/default-avatar.png | Bin 0 -> 2864 bytes apps/static/assets/img/emilyz.jpg | Bin 0 -> 86218 bytes apps/static/assets/img/favicon.png | Bin 0 -> 2761 bytes apps/static/assets/img/header.jpg | Bin 0 -> 670266 bytes apps/static/assets/img/img_3115.jpg | Bin 0 -> 38381 bytes apps/static/assets/img/james.jpg | Bin 0 -> 74556 bytes apps/static/assets/img/mike.jpg | Bin 0 -> 76654 bytes apps/static/assets/img/now-logo.png | Bin 0 -> 8172 bytes apps/static/assets/js/black-dashboard.js | 255 + apps/static/assets/js/black-dashboard.js.map | 1 + apps/static/assets/js/black-dashboard.min.js | 2 + apps/static/assets/js/core/bootstrap.min.js | 6 + apps/static/assets/js/core/jquery.min.js | 4 + apps/static/assets/js/core/popper.min.js | 4 + .../assets/js/plugins/bootstrap-notify.js | 432 + apps/static/assets/js/plugins/chartjs.min.js | 10 + .../plugins/perfect-scrollbar.jquery.min.js | 6 + apps/static/assets/js/themeSettings.js | 148 + apps/static/assets/scss/black-dashboard.scss | 102 + .../assets/scss/black-dashboard/_buttons.scss | 1 + .../scss/black-dashboard/_typography.scss | 1 + .../black-dashboard/bootstrap/_alert.scss | 51 + .../black-dashboard/bootstrap/_badge.scss | 54 + .../bootstrap/_breadcrumb.scss | 41 + .../bootstrap/_button-group.scss | 163 + .../black-dashboard/bootstrap/_buttons.scss | 137 + .../scss/black-dashboard/bootstrap/_card.scss | 289 + .../black-dashboard/bootstrap/_carousel.scss | 197 + .../black-dashboard/bootstrap/_close.scss | 41 + .../scss/black-dashboard/bootstrap/_code.scss | 48 + .../bootstrap/_custom-forms.scss | 507 + .../black-dashboard/bootstrap/_dropdown.scss | 191 + .../black-dashboard/bootstrap/_forms.scss | 330 + .../black-dashboard/bootstrap/_functions.scss | 86 + .../scss/black-dashboard/bootstrap/_grid.scss | 52 + .../black-dashboard/bootstrap/_images.scss | 42 + .../bootstrap/_input-group.scss | 193 + .../black-dashboard/bootstrap/_jumbotron.scss | 17 + .../bootstrap/_list-group.scss | 149 + .../black-dashboard/bootstrap/_media.scss | 8 + .../black-dashboard/bootstrap/_mixins.scss | 47 + .../black-dashboard/bootstrap/_modal.scss | 229 + .../scss/black-dashboard/bootstrap/_nav.scss | 120 + .../black-dashboard/bootstrap/_navbar.scss | 294 + .../bootstrap/_pagination.scss | 73 + .../black-dashboard/bootstrap/_popover.scss | 171 + .../black-dashboard/bootstrap/_print.scss | 141 + .../black-dashboard/bootstrap/_progress.scss | 43 + .../black-dashboard/bootstrap/_reboot.scss | 483 + .../scss/black-dashboard/bootstrap/_root.scss | 19 + .../black-dashboard/bootstrap/_spinners.scss | 55 + .../black-dashboard/bootstrap/_tables.scss | 185 + .../black-dashboard/bootstrap/_toasts.scss | 44 + .../black-dashboard/bootstrap/_tooltip.scss | 115 + .../bootstrap/_transitions.scss | 20 + .../scss/black-dashboard/bootstrap/_type.scss | 125 + .../black-dashboard/bootstrap/_utilities.scss | 17 + .../black-dashboard/bootstrap/_variables.scss | 1123 ++ .../bootstrap/bootstrap-grid.scss | 29 + .../bootstrap/bootstrap-reboot.scss | 12 + .../black-dashboard/bootstrap/bootstrap.scss | 44 + .../bootstrap/mixins/_alert.scss | 13 + .../bootstrap/mixins/_background-variant.scss | 21 + .../bootstrap/mixins/_badge.scss | 17 + .../bootstrap/mixins/_border-radius.scss | 63 + .../bootstrap/mixins/_box-shadow.scss | 20 + .../bootstrap/mixins/_breakpoints.scss | 123 + .../bootstrap/mixins/_buttons.scss | 107 + .../bootstrap/mixins/_caret.scss | 62 + .../bootstrap/mixins/_clearfix.scss | 7 + .../bootstrap/mixins/_deprecate.scss | 10 + .../bootstrap/mixins/_float.scss | 14 + .../bootstrap/mixins/_forms.scss | 192 + .../bootstrap/mixins/_gradients.scss | 45 + .../bootstrap/mixins/_grid-framework.scss | 66 + .../bootstrap/mixins/_grid.scss | 51 + .../bootstrap/mixins/_hover.scss | 37 + .../bootstrap/mixins/_image.scss | 36 + .../bootstrap/mixins/_list-group.scss | 21 + .../bootstrap/mixins/_lists.scss | 7 + .../bootstrap/mixins/_nav-divider.scss | 10 + .../bootstrap/mixins/_pagination.scss | 22 + .../bootstrap/mixins/_reset-text.scss | 17 + .../bootstrap/mixins/_resize.scss | 6 + .../bootstrap/mixins/_screen-reader.scss | 33 + .../bootstrap/mixins/_size.scss | 7 + .../bootstrap/mixins/_table-row.scss | 39 + .../bootstrap/mixins/_text-emphasis.scss | 16 + .../bootstrap/mixins/_text-hide.scss | 11 + .../bootstrap/mixins/_text-truncate.scss | 8 + .../bootstrap/mixins/_transition.scss | 16 + .../bootstrap/mixins/_visibility.scss | 8 + .../bootstrap/utilities/_align.scss | 8 + .../bootstrap/utilities/_background.scss | 19 + .../bootstrap/utilities/_borders.scss | 75 + .../bootstrap/utilities/_clearfix.scss | 3 + .../bootstrap/utilities/_display.scss | 26 + .../bootstrap/utilities/_embed.scss | 39 + .../bootstrap/utilities/_flex.scss | 51 + .../bootstrap/utilities/_float.scss | 11 + .../bootstrap/utilities/_overflow.scss | 5 + .../bootstrap/utilities/_position.scss | 32 + .../bootstrap/utilities/_screenreaders.scss | 11 + .../bootstrap/utilities/_shadows.scss | 6 + .../bootstrap/utilities/_sizing.scss | 20 + .../bootstrap/utilities/_spacing.scss | 73 + .../bootstrap/utilities/_stretched-link.scss | 19 + .../bootstrap/utilities/_text.scss | 72 + .../bootstrap/utilities/_visibility.scss | 13 + .../bootstrap/vendor/_rfs.scss | 204 + .../scss/black-dashboard/custom/_alerts.scss | 89 + .../scss/black-dashboard/custom/_buttons.scss | 238 + .../scss/black-dashboard/custom/_card.scss | 232 + .../custom/_checkboxes-radio.scss | 154 + .../black-dashboard/custom/_dropdown.scss | 359 + .../custom/_example-pages.scss | 256 + .../black-dashboard/custom/_fixed-plugin.scss | 324 + .../scss/black-dashboard/custom/_footer.scss | 94 + .../scss/black-dashboard/custom/_forms.scss | 133 + .../black-dashboard/custom/_functions.scss | 23 + .../scss/black-dashboard/custom/_images.scss | 7 + .../black-dashboard/custom/_input-group.scss | 343 + .../scss/black-dashboard/custom/_misc.scss | 229 + .../scss/black-dashboard/custom/_mixins.scss | 15 + .../scss/black-dashboard/custom/_modal.scss | 161 + .../scss/black-dashboard/custom/_navbar.scss | 413 + .../scss/black-dashboard/custom/_rtl.scss | 215 + .../custom/_sidebar-and-main-panel.scss | 884 + .../scss/black-dashboard/custom/_tables.scss | 191 + .../scss/black-dashboard/custom/_type.scss | 174 + .../black-dashboard/custom/_utilities.scss | 9 + .../black-dashboard/custom/_variables.scss | 993 ++ .../custom/_white-content.scss | 299 + .../custom/cards/_card-chart.scss | 73 + .../custom/cards/_card-map.scss | 3 + .../custom/cards/_card-plain.scss | 16 + .../custom/cards/_card-task.scss | 30 + .../custom/cards/_card-user.scss | 77 + .../black-dashboard/custom/mixins/_alert.scss | 14 + .../custom/mixins/_background-variant.scss | 18 + .../custom/mixins/_badges.scss | 15 + .../custom/mixins/_buttons.scss | 343 + .../custom/mixins/_dropdown.scss | 26 + .../black-dashboard/custom/mixins/_forms.scss | 127 + .../black-dashboard/custom/mixins/_icon.scss | 4 + .../custom/mixins/_inputs.scss | 234 + .../custom/mixins/_modals.scss | 15 + .../custom/mixins/_page-header.scss | 7 + .../custom/mixins/_popovers.scss | 41 + .../custom/mixins/_vendor-prefixes.scss | 202 + .../custom/mixins/_wizard.scss | 26 + .../custom/mixins/opacity.scss | 8 + .../custom/utilities/_backgrounds.scss | 42 + .../custom/utilities/_floating.scss | 54 + .../custom/utilities/_helper.scss | 62 + .../custom/utilities/_position.scss | 19 + .../custom/utilities/_shadows.scss | 10 + .../custom/utilities/_sizing.scss | 5 + .../custom/utilities/_spacing.scss | 105 + .../custom/utilities/_text.scss | 40 + .../custom/utilities/_transform.scss | 8 + .../_plugin-animate-bootstrap-notify.scss | 227 + .../vendor/_plugin-perfect-scrollbar.scss | 116 + .../plugins/_plugin-perfect-scrollbar.scss | 116 + apps/templates/.gitkeep | 0 apps/templates/accounts/login.html | 108 + apps/templates/accounts/register.html | 97 + apps/templates/home/icons.html | 630 + apps/templates/home/index.html | 406 + apps/templates/home/login.html | 60 + apps/templates/home/map.html | 37 + apps/templates/home/notifications.html | 135 + apps/templates/home/page-403.html | 47 + apps/templates/home/page-404.html | 47 + apps/templates/home/page-500.html | 47 + apps/templates/home/register.html | 70 + apps/templates/home/rtl.html | 392 + apps/templates/home/tables.html | 277 + apps/templates/home/typography.html | 156 + apps/templates/home/user.html | 159 + apps/templates/includes/fixed-plugin.html | 35 + .../templates/includes/footer-fullscreen.html | 7 + apps/templates/includes/footer.html | 19 + .../includes/navigation-fullscreen.html | 36 + apps/templates/includes/navigation-rtl.html | 83 + apps/templates/includes/navigation.html | 95 + apps/templates/includes/scripts.html | 17 + apps/templates/includes/sidebar-rtl.html | 72 + apps/templates/includes/sidebar.html | 72 + apps/templates/layouts/base-fullscreen.html | 68 + apps/templates/layouts/base-rtl.html | 71 + apps/templates/layouts/base.html | 69 + docker-compose.yml | 27 + env.sample | 22 + gulpfile.js | 72 + gunicorn-cfg.py | 11 + nginx/appseed-app.conf | 15 + package.json | 38 + requirements.txt | 18 + run.py | 40 + 231 files changed, 35693 insertions(+), 125 deletions(-) create mode 100644 .dockerignore create mode 100644 .env create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 apps/__init__.py create mode 100644 apps/authentication/__init__.py create mode 100644 apps/authentication/forms.py create mode 100644 apps/authentication/models.py create mode 100644 apps/authentication/oauth.py create mode 100644 apps/authentication/routes.py create mode 100644 apps/authentication/util.py create mode 100644 apps/config.py create mode 100644 apps/home/__init__.py create mode 100644 apps/home/routes.py create mode 100644 apps/static/assets/css/black-dashboard.css create mode 100644 apps/static/assets/css/black-dashboard.css.map create mode 100644 apps/static/assets/css/black-dashboard.min.css create mode 100644 apps/static/assets/css/nucleo-icons.css create mode 100644 apps/static/assets/css/theme-switcher.css create mode 100644 apps/static/assets/demo/demo.css create mode 100644 apps/static/assets/demo/demo.js create mode 100644 apps/static/assets/fonts/nucleo.eot create mode 100644 apps/static/assets/fonts/nucleo.ttf create mode 100644 apps/static/assets/fonts/nucleo.woff create mode 100644 apps/static/assets/fonts/nucleo.woff2 create mode 100644 apps/static/assets/img/12345.png create mode 100644 apps/static/assets/img/anime3.png create mode 100644 apps/static/assets/img/anime6.png create mode 100644 apps/static/assets/img/apple-icon.png create mode 100644 apps/static/assets/img/bg5.jpg create mode 100644 apps/static/assets/img/default-avatar.png create mode 100644 apps/static/assets/img/emilyz.jpg create mode 100644 apps/static/assets/img/favicon.png create mode 100644 apps/static/assets/img/header.jpg create mode 100644 apps/static/assets/img/img_3115.jpg create mode 100644 apps/static/assets/img/james.jpg create mode 100644 apps/static/assets/img/mike.jpg create mode 100644 apps/static/assets/img/now-logo.png create mode 100644 apps/static/assets/js/black-dashboard.js create mode 100644 apps/static/assets/js/black-dashboard.js.map create mode 100644 apps/static/assets/js/black-dashboard.min.js create mode 100644 apps/static/assets/js/core/bootstrap.min.js create mode 100644 apps/static/assets/js/core/jquery.min.js create mode 100644 apps/static/assets/js/core/popper.min.js create mode 100644 apps/static/assets/js/plugins/bootstrap-notify.js create mode 100644 apps/static/assets/js/plugins/chartjs.min.js create mode 100644 apps/static/assets/js/plugins/perfect-scrollbar.jquery.min.js create mode 100644 apps/static/assets/js/themeSettings.js create mode 100644 apps/static/assets/scss/black-dashboard.scss create mode 100644 apps/static/assets/scss/black-dashboard/_buttons.scss create mode 100644 apps/static/assets/scss/black-dashboard/_typography.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_alert.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_badge.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_breadcrumb.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_button-group.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_buttons.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_card.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_carousel.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_close.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_code.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_custom-forms.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_dropdown.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_forms.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_functions.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_grid.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_images.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_input-group.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_jumbotron.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_list-group.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_media.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_mixins.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_modal.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_nav.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_navbar.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_pagination.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_popover.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_print.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_progress.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_reboot.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_root.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_spinners.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_tables.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_toasts.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_tooltip.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_transitions.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_type.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_utilities.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/_variables.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/bootstrap-grid.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/bootstrap-reboot.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/bootstrap.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_alert.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_background-variant.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_badge.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_border-radius.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_box-shadow.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_breakpoints.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_buttons.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_caret.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_clearfix.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_deprecate.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_float.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_forms.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_gradients.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_grid-framework.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_grid.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_hover.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_image.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_list-group.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_lists.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_nav-divider.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_pagination.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_reset-text.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_resize.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_screen-reader.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_size.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_table-row.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_text-emphasis.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_text-hide.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_text-truncate.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_transition.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/mixins/_visibility.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_align.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_background.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_borders.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_clearfix.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_display.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_embed.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_flex.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_float.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_overflow.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_position.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_screenreaders.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_shadows.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_sizing.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_spacing.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_stretched-link.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_text.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/utilities/_visibility.scss create mode 100644 apps/static/assets/scss/black-dashboard/bootstrap/vendor/_rfs.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_alerts.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_buttons.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_card.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_checkboxes-radio.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_dropdown.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_example-pages.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_fixed-plugin.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_footer.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_forms.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_functions.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_images.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_input-group.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_misc.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_mixins.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_modal.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_navbar.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_rtl.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_sidebar-and-main-panel.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_tables.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_type.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_utilities.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_variables.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/_white-content.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/cards/_card-chart.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/cards/_card-map.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/cards/_card-plain.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/cards/_card-task.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/cards/_card-user.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_alert.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_background-variant.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_badges.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_buttons.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_dropdown.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_forms.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_icon.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_inputs.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_modals.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_page-header.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_popovers.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_vendor-prefixes.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/_wizard.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/mixins/opacity.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_backgrounds.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_floating.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_helper.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_position.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_shadows.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_sizing.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_spacing.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_text.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/utilities/_transform.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/vendor/_plugin-animate-bootstrap-notify.scss create mode 100644 apps/static/assets/scss/black-dashboard/custom/vendor/_plugin-perfect-scrollbar.scss create mode 100644 apps/static/assets/scss/black-dashboard/plugins/_plugin-perfect-scrollbar.scss create mode 100644 apps/templates/.gitkeep create mode 100644 apps/templates/accounts/login.html create mode 100644 apps/templates/accounts/register.html create mode 100644 apps/templates/home/icons.html create mode 100644 apps/templates/home/index.html create mode 100644 apps/templates/home/login.html create mode 100644 apps/templates/home/map.html create mode 100644 apps/templates/home/notifications.html create mode 100644 apps/templates/home/page-403.html create mode 100644 apps/templates/home/page-404.html create mode 100644 apps/templates/home/page-500.html create mode 100644 apps/templates/home/register.html create mode 100644 apps/templates/home/rtl.html create mode 100644 apps/templates/home/tables.html create mode 100644 apps/templates/home/typography.html create mode 100644 apps/templates/home/user.html create mode 100644 apps/templates/includes/fixed-plugin.html create mode 100644 apps/templates/includes/footer-fullscreen.html create mode 100644 apps/templates/includes/footer.html create mode 100644 apps/templates/includes/navigation-fullscreen.html create mode 100644 apps/templates/includes/navigation-rtl.html create mode 100644 apps/templates/includes/navigation.html create mode 100644 apps/templates/includes/scripts.html create mode 100644 apps/templates/includes/sidebar-rtl.html create mode 100644 apps/templates/includes/sidebar.html create mode 100644 apps/templates/layouts/base-fullscreen.html create mode 100644 apps/templates/layouts/base-rtl.html create mode 100644 apps/templates/layouts/base.html create mode 100644 docker-compose.yml create mode 100644 env.sample create mode 100644 gulpfile.js create mode 100644 gunicorn-cfg.py create mode 100644 nginx/appseed-app.conf create mode 100644 package.json create mode 100644 requirements.txt create mode 100644 run.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..72e294c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +__pycache__ +*.pyc +*.pyo +*.pyd \ No newline at end of file diff --git a/.env b/.env new file mode 100644 index 0000000..5c8316e --- /dev/null +++ b/.env @@ -0,0 +1,14 @@ +# True for development, False for production +DEBUG=True + +# Flask ENV +FLASK_APP=run.py +FLASK_ENV=development + +# Used for CDN (in production) +# No Slash at the end +ASSETS_ROOT=/static/assets + +# LOCAL 5001 FLask +# GITHUB_ID = +# GITHUB_SECRET = diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65f07c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# tests and coverage +*.pytest_cache +.coverage + +# database & logs +*.db +*.sqlite3 +*.log + +# venv +env +venv + +# other +.DS_Store + +# sphinx docs +_build +_static +_templates + +# javascript +package-lock.json +.vscode/symbols.json + +apps/static/assets/node_modules +apps/static/assets/yarn.lock +apps/static/assets/.temp + +migrations +node_modules +yarn.lock diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..77ce542 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM python:3.9 + +# set environment variables +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 +ENV FLASK_APP run.py +ENV DEBUG True + +COPY requirements.txt . + +# install python dependencies +RUN pip install --upgrade pip +RUN pip install --no-cache-dir -r requirements.txt + +COPY env.sample .env + +COPY . . + +RUN flask db init +RUN flask db migrate +RUN flask db upgrade + +# gunicorn +CMD ["gunicorn", "--config", "gunicorn-cfg.py", "run:app"] diff --git a/README.md b/README.md index e77a7b3..493f5f4 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,14 @@
-> Free product - **Flask Dashboard** starter project - Features: +> Features: -- Up-to-date [dependencies](./requirements.txt): **Flask 2.0.1** -- [SCSS compilation](#recompile-css) via **Gulp** -- UI Kit: **Black Dashboard** (Free Version) provided by **[Creative-Tim](https://www.creative-tim.com/)** -- Flask Codebase - provided by **[AppSeed](https://appseed.us/)** -- SQLite, PostgreSQL, SQLAlchemy ORM -- Alembic (DB schema migrations) -- Modular design with **Blueprints** -- Session-Based authentication (via **flask_login**) -- Forms validation -- Deployment scripts: Docker, Gunicorn / Nginx, Heroku +- ✅ `Up-to-date dependencies` +- ✅ Black Dashboard, BS4 Design +- ✅ `DB Tools`: SQLAlchemy ORM, `Flask-Migrate` (schema migrations) +- ✅ `Persistence`: SQLite (dev), MySql (prod) +- ✅ `Authentication`: Session Based, `OAuth` via Github +- ✅ `Deployment`: Docker, Page Compression (Flask-Minify)
@@ -57,66 +53,137 @@ $ cd black-dashboard-flask > Start the app in Docker ```bash -$ docker-compose pull # download dependencies -$ docker-compose build # local set up -$ docker-compose up -d # start the app +$ docker-compose up --build ``` -Visit `http://localhost:85` in your browser. The app should be up & running. +Visit `http://localhost:5085` in your browser. The app should be up & running.
-## Quick start +## Create/Edit `.env` file + +The meaning of each variable can be found below: + +- `DEBUG`: if `True` the app runs in develoment mode + - For production value `False` should be used +- `ASSETS_ROOT`: used in assets management + - default value: `/static/assets` +- `OAuth` via Github + - `GITHUB_ID`= + - `GITHUB_SECRET`= + +
+ +## Manual Build > UNZIP the sources or clone the private repository. After getting the code, open a terminal and navigate to the working directory, with product source code. +### 👉 Set Up for `Unix`, `MacOS` + +> Install modules via `VENV` + ```bash -$ # Get the code -$ git clone https://github.com/creativetimofficial/black-dashboard-flask.git -$ cd black-dashboard-flask -$ -$ # Virtualenv modules installation (Unix based systems) $ virtualenv env $ source env/bin/activate -$ -$ # Virtualenv modules installation (Windows based systems) -$ # virtualenv env -$ # .\env\Scripts\activate -$ -$ # Install modules - SQLite Database $ pip3 install -r requirements.txt -$ -$ # OR with PostgreSQL connector -$ # pip install -r requirements-pgsql.txt -$ -$ # Set the FLASK_APP environment variable -$ (Unix/Mac) export FLASK_APP=run.py -$ (Windows) set FLASK_APP=run.py -$ (Powershell) $env:FLASK_APP = ".\run.py" -$ -$ # Set up the DEBUG environment -$ # (Unix/Mac) export FLASK_ENV=development -$ # (Windows) set FLASK_ENV=development -$ # (Powershell) $env:FLASK_ENV = "development" -$ -$ # Start the application (development mode) -$ # --host=0.0.0.0 - expose the app on all network interfaces (default 127.0.0.1) -$ # --port=5000 - specify the app port (default 5000) -$ flask run --host=0.0.0.0 --port=5000 -$ -$ # Access the dashboard in browser: http://127.0.0.1:5000/ ``` -> Note: To use the app, please access the registration page and create a new user. After authentication, the app will unlock the private pages. +
+ +> Set Up Flask Environment + +```bash +$ export FLASK_APP=run.py +$ export FLASK_ENV=development +``` + +
+ +> Start the app + +```bash +$ flask run +// OR +$ flask run --cert=adhoc # For HTTPS server +``` + +At this point, the app runs at `http://127.0.0.1:5000/`. + +
+ +### 👉 Set Up for `Windows` + +> Install modules via `VENV` (windows) + +``` +$ virtualenv env +$ .\env\Scripts\activate +$ pip3 install -r requirements.txt +``` + +
+ +> Set Up Flask Environment + +```bash +$ # CMD +$ set FLASK_APP=run.py +$ set FLASK_ENV=development +$ +$ # Powershell +$ $env:FLASK_APP = ".\run.py" +$ $env:FLASK_ENV = "development" +``` + +
+ +> Start the app + +```bash +$ flask run +// OR +$ flask run --cert=adhoc # For HTTPS server +``` + +At this point, the app runs at `http://127.0.0.1:5000/`. + +
+ +## Recompile SCSS + +The SCSS/CSS files used to style the Ui are saved in the `apps/static/assets` directory. +In order to update the Ui colors (primary, secondary) this procedure needs to be followed. + +```bash +$ yarn # install modules +$ # # edit variables +$ vi apps/static/assets/scss/black-dashboard/custom/_variables.scss +$ gulp # SCSS to CSS translation +``` + +The `_variables.scss` content defines the `primary` and `secondary` colors: + +```scss +$default: #344675 !default; // EDIT for customization +$primary: #e14eca !default; // EDIT for customization +$secondary: #f4f5f7 !default; // EDIT for customization +$success: #00f2c3 !default; // EDIT for customization +$info: #1d8cf8 !default; // EDIT for customization +$warning: #ff8d72 !default; // EDIT for customization +$danger: #fd5d93 !default; // EDIT for customization +$black: #222a42 !default; // EDIT for customization +```
## Documentation + The documentation for the **Black Dashboard Flask** is hosted at our [website](https://demos.creative-tim.com/black-dashboard-flask/docs/1.0/getting-started/getting-started-flask.html).
## File Structure + Within the download you'll find the following directories and files: ```bash @@ -124,23 +191,23 @@ Within the download you'll find the following directories and files: | |-- apps/ | | - | |-- home/ # A simple app that serve HTML files - | | |-- routes.py # Define app routes + | |-- home/ # A simple app that serve HTML files + | | |-- routes.py # Define app routes | | - | |-- authentication/ # Handles auth routes (login and register) - | | |-- routes.py # Define authentication routes - | | |-- models.py # Defines models - | | |-- forms.py # Define auth forms (login and register) + | |-- authentication/ # Handles auth routes (login and register) + | | |-- routes.py # Define authentication routes + | | |-- models.py # Defines models + | | |-- forms.py # Define auth forms (login and register) | | | |-- static/ - | | |-- # CSS files, Javascripts files + | | |-- # CSS files, Javascripts files | | - | |-- templates/ # Templates used to render pages - | | |-- includes/ # HTML chunks and components - | | | |-- navigation.html # Top menu component - | | | |-- sidebar.html # Sidebar component - | | | |-- footer.html # App Footer - | | | |-- scripts.html # Scripts common to all pages + | |-- templates/ # Templates used to render pages + | | |-- includes/ # HTML chunks and components + | | | |-- navigation.html # Top menu component + | | | |-- sidebar.html # Sidebar component + | | | |-- footer.html # App Footer + | | | |-- scripts.html # Scripts common to all pages | | | | | |-- layouts/ # Master pages | | | |-- base-fullscreen.html # Used by Authentication pages @@ -158,15 +225,7 @@ Within the download you'll find the following directories and files: | config.py # Set up the app | __init__.py # Initialize the app | - |-- requirements.txt # Development modules - SQLite storage - |-- requirements-mysql.txt # Production modules - Mysql DMBS - |-- requirements-pqsql.txt # Production modules - PostgreSql DMBS - | - |-- Dockerfile # Deployment - |-- docker-compose.yml # Deployment - |-- gunicorn-cfg.py # Deployment - |-- nginx # Deployment - | |-- appseed-app.conf # Deployment + |-- requirements.txt # App Dependencies | |-- .env # Inject Configuration via Environment |-- run.py # Start the app - WSGI gateway @@ -176,61 +235,6 @@ Within the download you'll find the following directories and files:
-> The bootstrap flow - -- `run.py` loads the `.env` file -- Initialize the app using the specified profile: *Debug* or *Production* - - If env.DEBUG is set to *True* the SQLite storage is used - - If env.DEBUG is set to *False* the specified DB driver is used (MySql, PostgreSQL) -- Call the app factory method `create_app` defined in app/__init__.py -- Redirect the guest users to Login page -- Unlock the pages served by *home* blueprint for authenticated users - -
- -## Recompile CSS - -To recompile SCSS files, follow this setup: - -
- -**Step #1** - Install tools - -- [NodeJS](https://nodejs.org/en/) 12.x or higher -- [Gulp](https://gulpjs.com/) - globally - - `npm install -g gulp-cli` -- [Yarn](https://yarnpkg.com/) (optional) - -
- -**Step #2** - Change the working directory to `assets` folder - -```bash -$ cd apps/static/assets -``` - -
- -**Step #3** - Install modules (this will create a classic `node_modules` directory) - -```bash -$ npm install -// OR -$ yarn -``` - -
- -**Step #4** - Edit & Recompile SCSS files - -```bash -$ gulp scss -``` - -The generated file is saved in `static/assets/css` directory. - -
- ## Browser Support At present, we officially aim to support the last two versions of the following browsers: diff --git a/apps/__init__.py b/apps/__init__.py new file mode 100644 index 0000000..a6cfa41 --- /dev/null +++ b/apps/__init__.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from flask import Flask +from flask_login import LoginManager +from flask_sqlalchemy import SQLAlchemy +from importlib import import_module + + +db = SQLAlchemy() +login_manager = LoginManager() + + +def register_extensions(app): + db.init_app(app) + login_manager.init_app(app) + + +def register_blueprints(app): + for module_name in ('authentication', 'home'): + module = import_module('apps.{}.routes'.format(module_name)) + app.register_blueprint(module.blueprint) + + +def configure_database(app): + + @app.before_first_request + def initialize_database(): + db.create_all() + + @app.teardown_request + def shutdown_session(exception=None): + db.session.remove() + +from apps.authentication.oauth import github_blueprint + +def create_app(config): + app = Flask(__name__) + app.config.from_object(config) + register_extensions(app) + + app.register_blueprint(github_blueprint, url_prefix="/login") + + register_blueprints(app) + configure_database(app) + return app diff --git a/apps/authentication/__init__.py b/apps/authentication/__init__.py new file mode 100644 index 0000000..25243ec --- /dev/null +++ b/apps/authentication/__init__.py @@ -0,0 +1,12 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from flask import Blueprint + +blueprint = Blueprint( + 'authentication_blueprint', + __name__, + url_prefix='' +) diff --git a/apps/authentication/forms.py b/apps/authentication/forms.py new file mode 100644 index 0000000..89f43da --- /dev/null +++ b/apps/authentication/forms.py @@ -0,0 +1,31 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from flask_wtf import FlaskForm +from wtforms import StringField, PasswordField +from wtforms.validators import Email, DataRequired + +# login and registration + + +class LoginForm(FlaskForm): + username = StringField('Username', + id='username_login', + validators=[DataRequired()]) + password = PasswordField('Password', + id='pwd_login', + validators=[DataRequired()]) + + +class CreateAccountForm(FlaskForm): + username = StringField('Username', + id='username_create', + validators=[DataRequired()]) + email = StringField('Email', + id='email_create', + validators=[DataRequired(), Email()]) + password = PasswordField('Password', + id='pwd_create', + validators=[DataRequired()]) diff --git a/apps/authentication/models.py b/apps/authentication/models.py new file mode 100644 index 0000000..695a191 --- /dev/null +++ b/apps/authentication/models.py @@ -0,0 +1,57 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from flask_login import UserMixin + +from sqlalchemy.orm import relationship +from flask_dance.consumer.storage.sqla import OAuthConsumerMixin + +from apps import db, login_manager + +from apps.authentication.util import hash_pass + +class Users(db.Model, UserMixin): + + __tablename__ = 'Users' + + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(64), unique=True) + email = db.Column(db.String(64), unique=True) + password = db.Column(db.LargeBinary) + + oauth_github = db.Column(db.String(100), nullable=True) + + def __init__(self, **kwargs): + for property, value in kwargs.items(): + # depending on whether value is an iterable or not, we must + # unpack it's value (when **kwargs is request.form, some values + # will be a 1-element list) + if hasattr(value, '__iter__') and not isinstance(value, str): + # the ,= unpack of a singleton fails PEP8 (travis flake8 test) + value = value[0] + + if property == 'password': + value = hash_pass(value) # we need bytes here (not plain str) + + setattr(self, property, value) + + def __repr__(self): + return str(self.username) + + +@login_manager.user_loader +def user_loader(id): + return Users.query.filter_by(id=id).first() + + +@login_manager.request_loader +def request_loader(request): + username = request.form.get('username') + user = Users.query.filter_by(username=username).first() + return user if user else None + +class OAuth(OAuthConsumerMixin, db.Model): + user_id = db.Column(db.Integer, db.ForeignKey("Users.id", ondelete="cascade"), nullable=False) + user = db.relationship(Users) diff --git a/apps/authentication/oauth.py b/apps/authentication/oauth.py new file mode 100644 index 0000000..fa33165 --- /dev/null +++ b/apps/authentication/oauth.py @@ -0,0 +1,58 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +import os +from flask import current_app as app +from flask_login import current_user, login_user +from flask_dance.consumer import oauth_authorized +from flask_dance.contrib.github import github, make_github_blueprint +from flask_dance.consumer.storage.sqla import SQLAlchemyStorage +from flask_dance.contrib.twitter import twitter, make_twitter_blueprint +from sqlalchemy.orm.exc import NoResultFound +from apps.config import Config +from .models import Users, db, OAuth +from flask import redirect, url_for +from flask import flash + +github_blueprint = make_github_blueprint( + client_id=Config.GITHUB_ID, + client_secret=Config.GITHUB_SECRET, + scope = 'user', + storage=SQLAlchemyStorage( + OAuth, + db.session, + user=current_user, + user_required=False, + ), +) + +@oauth_authorized.connect_via(github_blueprint) +def github_logged_in(blueprint, token): + info = github.get("/user") + + if info.ok: + + account_info = info.json() + username = account_info["login"] + + query = Users.query.filter_by(oauth_github=username) + try: + + user = query.one() + login_user(user) + + except NoResultFound: + + # Save to db + user = Users() + user.username = '(gh)' + username + user.oauth_github = username + + # Save current user + db.session.add(user) + db.session.commit() + + login_user(user) + diff --git a/apps/authentication/routes.py b/apps/authentication/routes.py new file mode 100644 index 0000000..1b45390 --- /dev/null +++ b/apps/authentication/routes.py @@ -0,0 +1,133 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from flask import render_template, redirect, request, url_for +from flask_login import ( + current_user, + login_user, + logout_user +) + +from flask_dance.contrib.github import github + +from apps import db, login_manager +from apps.authentication import blueprint +from apps.authentication.forms import LoginForm, CreateAccountForm +from apps.authentication.models import Users + +from apps.authentication.util import verify_pass + + +@blueprint.route('/') +def route_default(): + return redirect(url_for('authentication_blueprint.login')) + +# Login & Registration + +@blueprint.route("/github") +def login_github(): + """ Github login """ + if not github.authorized: + return redirect(url_for("github.login")) + + res = github.get("/user") + return redirect(url_for('home_blueprint.index')) + +@blueprint.route('/login', methods=['GET', 'POST']) +def login(): + login_form = LoginForm(request.form) + if 'login' in request.form: + + # read form data + username = request.form['username'] + password = request.form['password'] + + # Locate user + user = Users.query.filter_by(username=username).first() + + # Check the password + if user and verify_pass(password, user.password): + + login_user(user) + return redirect(url_for('authentication_blueprint.route_default')) + + # Something (user or pass) is not ok + return render_template('accounts/login.html', + msg='Wrong user or password', + form=login_form) + + if not current_user.is_authenticated: + return render_template('accounts/login.html', + form=login_form) + return redirect(url_for('home_blueprint.index')) + + +@blueprint.route('/register', methods=['GET', 'POST']) +def register(): + create_account_form = CreateAccountForm(request.form) + if 'register' in request.form: + + username = request.form['username'] + email = request.form['email'] + + # Check usename exists + user = Users.query.filter_by(username=username).first() + if user: + return render_template('accounts/register.html', + msg='Username already registered', + success=False, + form=create_account_form) + + # Check email exists + user = Users.query.filter_by(email=email).first() + if user: + return render_template('accounts/register.html', + msg='Email already registered', + success=False, + form=create_account_form) + + # else we can create the user + user = Users(**request.form) + db.session.add(user) + db.session.commit() + + # Delete user from session + logout_user() + + return render_template('accounts/register.html', + msg='Account created successfully.', + success=True, + form=create_account_form) + + else: + return render_template('accounts/register.html', form=create_account_form) + + +@blueprint.route('/logout') +def logout(): + logout_user() + return redirect(url_for('authentication_blueprint.login')) + + +# Errors + +@login_manager.unauthorized_handler +def unauthorized_handler(): + return render_template('home/page-403.html'), 403 + + +@blueprint.errorhandler(403) +def access_forbidden(error): + return render_template('home/page-403.html'), 403 + + +@blueprint.errorhandler(404) +def not_found_error(error): + return render_template('home/page-404.html'), 404 + + +@blueprint.errorhandler(500) +def internal_error(error): + return render_template('home/page-500.html'), 500 diff --git a/apps/authentication/util.py b/apps/authentication/util.py new file mode 100644 index 0000000..9130da8 --- /dev/null +++ b/apps/authentication/util.py @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +import os +import hashlib +import binascii + +# Inspiration -> https://www.vitoshacademy.com/hashing-passwords-in-python/ + + +def hash_pass(password): + """Hash a password for storing.""" + + salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii') + pwdhash = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), + salt, 100000) + pwdhash = binascii.hexlify(pwdhash) + return (salt + pwdhash) # return bytes + + +def verify_pass(provided_password, stored_password): + """Verify a stored password against one provided by user""" + + stored_password = stored_password.decode('ascii') + salt = stored_password[:64] + stored_password = stored_password[64:] + pwdhash = hashlib.pbkdf2_hmac('sha512', + provided_password.encode('utf-8'), + salt.encode('ascii'), + 100000) + pwdhash = binascii.hexlify(pwdhash).decode('ascii') + return pwdhash == stored_password diff --git a/apps/config.py b/apps/config.py new file mode 100644 index 0000000..46cd31b --- /dev/null +++ b/apps/config.py @@ -0,0 +1,59 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +import os + +class Config(object): + + basedir = os.path.abspath(os.path.dirname(__file__)) + + # Set up the App SECRET_KEY + # SECRET_KEY = config('SECRET_KEY' , default='S#perS3crEt_007') + SECRET_KEY = os.getenv('SECRET_KEY', 'S#perS3crEt_007') + + # This will create a file in FOLDER + SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'db.sqlite3') + SQLALCHEMY_TRACK_MODIFICATIONS = False + + # Assets Management + ASSETS_ROOT = os.getenv('ASSETS_ROOT', '/static/assets') + + SOCIAL_AUTH_GITHUB = False + + GITHUB_ID = os.getenv('GITHUB_ID') + GITHUB_SECRET = os.getenv('GITHUB_SECRET') + + # Enable/Disable Github Social Login + if GITHUB_ID and GITHUB_SECRET: + SOCIAL_AUTH_GITHUB = True + +class ProductionConfig(Config): + DEBUG = False + + # Security + SESSION_COOKIE_HTTPONLY = True + REMEMBER_COOKIE_HTTPONLY = True + REMEMBER_COOKIE_DURATION = 3600 + + # PostgreSQL database + SQLALCHEMY_DATABASE_URI = '{}://{}:{}@{}:{}/{}'.format( + os.getenv('DB_ENGINE' , 'mysql'), + os.getenv('DB_USERNAME' , 'appseed_db_usr'), + os.getenv('DB_PASS' , 'pass'), + os.getenv('DB_HOST' , 'localhost'), + os.getenv('DB_PORT' , 3306), + os.getenv('DB_NAME' , 'appseed_db') + ) + + +class DebugConfig(Config): + DEBUG = True + + +# Load all possible configurations +config_dict = { + 'Production': ProductionConfig, + 'Debug' : DebugConfig +} diff --git a/apps/home/__init__.py b/apps/home/__init__.py new file mode 100644 index 0000000..dec76db --- /dev/null +++ b/apps/home/__init__.py @@ -0,0 +1,12 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from flask import Blueprint + +blueprint = Blueprint( + 'home_blueprint', + __name__, + url_prefix='' +) diff --git a/apps/home/routes.py b/apps/home/routes.py new file mode 100644 index 0000000..49ca9ba --- /dev/null +++ b/apps/home/routes.py @@ -0,0 +1,54 @@ +# -*- encoding: utf-8 -*- +""" +Copyright (c) 2019 - present AppSeed.us +""" + +from apps.home import blueprint +from flask import render_template, request +from flask_login import login_required +from jinja2 import TemplateNotFound + + +@blueprint.route('/index') +@login_required +def index(): + + return render_template('home/index.html', segment='index') + + +@blueprint.route('/