├── .env-example
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── dependabot.yml
└── workflows
│ ├── pythonapp.yml
│ └── pythonpublish.yml
├── .gitignore
├── LICENSE
├── MANIFEST.in
├── README.md
├── codecov.yml
├── craft
├── makefile
├── pyproject.toml
├── pytest.ini
├── requirements.txt
├── setup.cfg
├── setup.py
├── src
├── __init__.py
└── backup
│ ├── Backup.py
│ ├── __init__.py
│ ├── commands
│ ├── BackupRunCommand.py
│ └── __init__.py
│ ├── config
│ └── backup.py
│ ├── mailables
│ ├── Backup.py
│ └── __init__.py
│ └── providers
│ ├── BackupProvider.py
│ └── __init__.py
├── tests
├── __init__.py
├── integrations
│ ├── Kernel.py
│ ├── app
│ │ ├── __init__.py
│ │ ├── controllers
│ │ │ ├── WelcomeController.py
│ │ │ └── __init__.py
│ │ ├── middlewares
│ │ │ ├── AuthenticationMiddleware.py
│ │ │ ├── VerifyCsrfToken.py
│ │ │ └── __init__.py
│ │ └── models
│ │ │ └── User.py
│ ├── config
│ │ ├── __init__.py
│ │ ├── application.py
│ │ ├── auth.py
│ │ ├── broadcast.py
│ │ ├── cache.py
│ │ ├── database.py
│ │ ├── exceptions.py
│ │ ├── filesystem.py
│ │ ├── mail.py
│ │ ├── notification.py
│ │ ├── providers.py
│ │ ├── queue.py
│ │ └── session.py
│ ├── databases
│ │ ├── migrations
│ │ │ ├── 2021_01_09_033202_create_password_reset_table.py
│ │ │ └── 2021_01_09_043202_create_users_table.py
│ │ └── seeds
│ │ │ ├── __init__.py
│ │ │ ├── database_seeder.py
│ │ │ └── user_table_seeder.py
│ ├── resources
│ │ ├── css
│ │ │ └── app.css
│ │ └── js
│ │ │ ├── app.js
│ │ │ └── bootstrap.js
│ ├── routes
│ │ └── web.py
│ ├── storage
│ │ ├── .gitignore
│ │ └── public
│ │ │ ├── favicon.ico
│ │ │ ├── logo.png
│ │ │ └── robots.txt
│ └── templates
│ │ ├── __init__.py
│ │ ├── base.html
│ │ ├── errors
│ │ ├── 403.html
│ │ ├── 404.html
│ │ └── 500.html
│ │ ├── maintenance.html
│ │ └── welcome.html
└── unit
│ ├── __init__.py
│ └── test_package.py
└── wsgi.py
/.env-example:
--------------------------------------------------------------------------------
1 | APP_DEBUG=True
2 | APP_ENV=development
3 | APP_KEY=plyUWY8iZnEH9_8WrVjl-LS3B8aRtHK9UAB35fGAq0M=
4 | DB_CONFIG_PATH=tests/integrations/config/database
5 | DB_CONNECTION=sqlite
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "weekly"
8 |
9 | # Maintain dependencies for cookiecutter repo
10 | - package-ecosystem: "pip"
11 | directory: "/"
12 | schedule:
13 | interval: "weekly"
14 | # Allow up to 10 open pull requests for pip dependencies
15 | open-pull-requests-limit: 10
16 |
--------------------------------------------------------------------------------
/.github/workflows/pythonapp.yml:
--------------------------------------------------------------------------------
1 | name: Test Application
2 |
3 | on:
4 | pull_request:
5 | branches: [master]
6 | push:
7 | branches: [master]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | strategy:
13 | matrix:
14 | python-version: ["3.7", "3.8", "3.9", "3.10"]
15 | name: Python ${{ matrix.python-version }}
16 | steps:
17 | - uses: actions/checkout@v4
18 | - name: Set up Python ${{ matrix.python-version }}
19 | uses: actions/setup-python@v4
20 | with:
21 | python-version: ${{ matrix.python-version }}
22 | - name: Install dependencies
23 | run: |
24 | make init
25 | - name: Test with pytest and Build coverage
26 | run: |
27 | make coverage
28 | - name: Upload coverage
29 | uses: codecov/codecov-action@v3
30 | with:
31 | token: ${{ secrets.CODECOV_TOKEN }}
32 | fail_ci_if_error: false
33 |
34 | lint:
35 | runs-on: ubuntu-latest
36 | name: Lint
37 | steps:
38 | - uses: actions/checkout@v4
39 | - name: Set up Python 3.8
40 | uses: actions/setup-python@v4
41 | with:
42 | python-version: 3.8
43 | - name: Intall Flake8
44 | run: |
45 | pip install flake8
46 | - name: Lint
47 | run: make lint
48 |
--------------------------------------------------------------------------------
/.github/workflows/pythonpublish.yml:
--------------------------------------------------------------------------------
1 | name: Upload Python Package
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | jobs:
8 | deploy:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v4
12 | - name: Set up Python
13 | uses: actions/setup-python@v4
14 | with:
15 | python-version: "3.x"
16 | - name: Install dependencies
17 | run: |
18 | make init
19 | - name: Publish only packages passing test
20 | run: |
21 | make test
22 | - name: Build and publish
23 | env:
24 | TWINE_USERNAME: __token__
25 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
26 | run: |
27 | make publish
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | venv
2 | venv2
3 | .vscode
4 | .idea/
5 | build/
6 | .pypirc
7 | .coverage
8 | coverage.xml
9 | .pytest_*
10 | **/*__pycache__*
11 | **/*.DS_Store*
12 | **.pyc
13 | dist
14 | .env
15 | *.db
16 | src/masonite_backup.egg-info
17 | storage
18 | *.gz
19 | *.zip
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022, Yubaraj Shrestha
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/MANIFEST.in
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | # Masonite Backup
18 |
19 | Backup solution for Masonite.
20 |
21 | ### Features
22 |
23 | - [x] Backup Database
24 | - [x] Backup Files
25 | - [x] Store Backup Locally in the filesystem
26 | - [x] Email Backup
27 | - [x] Store Backup in other Masonite Supported Storage Drivers [s3]
28 |
29 |
30 | ### Installation
31 |
32 | ```bash
33 | pip install masonite-backup
34 | ```
35 |
36 | ### Configuration
37 |
38 | Add BackupProvider to your project in `config/providers.py`:
39 |
40 | ```python
41 | # config/providers.py
42 | # ...
43 | from backup import BackupProvider
44 |
45 | # ...
46 | PROVIDERS = [
47 | # ...
48 | # Third Party Providers
49 | BackupProvider,
50 | # ...
51 | ]
52 | ```
53 |
54 | Then you can publish the package resources (if needed) by doing:
55 |
56 | ```bash
57 | python craft package:publish backup
58 | ```
59 |
60 | ### Usage
61 |
62 | Once you publish the package resources, you can use the `backup` command to backup your database and files. Before that if you want to configure options of backup then you can do that by updating `config/backup.py` configuration file.
63 |
64 | ```python
65 | # config/backup.py
66 |
67 | FILENAME = "backup"
68 | DIRECTORY = "backup"
69 | SOURCE = {
70 | "root": base_path(),
71 | "excludes": [
72 | ".git",
73 | "storage",
74 | "venv",
75 | "node_modules",
76 | "__pycache__",
77 | # add more...
78 | ],
79 | }
80 |
81 | S3_BACKUP = False # Whether or not to backup to S3.
82 | EMAIL_BACKUP = False # Whether or not to email the backup.
83 | EMAIL_BACKUP_TO = "" # The email address to send the backup to.
84 | EMAIL_SUBJECT = "System Backup" # The email subject.
85 | ```
86 | > Note: Make sure you have `EMAIL_BACKUP` set to `True` and `EMAIL_BACKUP_TO` set to a valid email address, to send the backup via email. Also don't forget to setup SMTP in `config/mail.py` configuration file or in `.env` file. In case you want to backup to S3, then make sure you have `S3_BACKUP` set to `True` and S3 storage configuration.
87 |
88 | ```sh
89 | MAIL_DRIVER=smtp
90 | MAIL_FROM=
91 | MAIL_HOST=
92 | MAIL_PORT=
93 | MAIL_USERNAME=
94 | MAIL_PASSWORD=
95 |
96 | AWS_CLIENT=
97 | AWS_SECRET=
98 | AWS_BUCKET=
99 | AWS_REGION=
100 | ```
101 |
102 | **Backup Database and Files**
103 |
104 | ```bash
105 | python craft backup:run
106 | ```
107 |
108 | **Backup Database Only**
109 |
110 | ```bash
111 | python craft backup:run --only-db
112 | ```
113 |
114 | **Backup Files Only**
115 |
116 | ```bash
117 | python craft backup:run --only-files
118 | ```
119 |
120 | ## License
121 |
122 | Backup is open-sourced software licensed under the [MIT license](LICENSE).
123 |
124 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | require_ci_to_pass: no
3 |
4 | github_checks: false
5 |
6 | coverage:
7 | precision: 2
8 | round: down
9 | range: "70...100"
10 |
11 | parsers:
12 | gcov:
13 | branch_detection:
14 | conditional: yes
15 | loop: yes
16 | method: no
17 | macro: no
18 |
19 | comment:
20 | layout: "footer"
21 | behavior: default
22 | require_changes: no
23 |
--------------------------------------------------------------------------------
/craft:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Craft Command.
3 | This module is really used for backup only if the masonite CLI cannot import this for you.
4 | This can be used by running "python craft". This module is not ran when the CLI can
5 | successfully import commands for you.
6 | """
7 |
8 | from wsgi import application
9 |
10 | if __name__ == '__main__':
11 | application.make('commands').run()
12 |
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 | .PHONY: help
2 | help: ## Show this help
3 | @egrep -h '\s##\s' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
4 |
5 | init: ## Install package dependencies
6 | cp .env-example .env
7 | pip install --upgrade pip
8 | # install test project and package dependencies
9 | pip install -r requirements.txt
10 | # install package and dev dependencies (see setup.py)
11 | pip install '.[dev]'
12 | test: ## Run package tests
13 | python -m pytest tests
14 | ci: ## [CI] Run package tests and lint
15 | make test
16 | make lint
17 | lint: ## Run code linting
18 | python -m flake8 .
19 | format: ## Format code with Black
20 | black src
21 | coverage: ## Run package tests and upload coverage reports
22 | python -m pytest --cov-report term --cov-report xml --cov=src/masonite/backup tests
23 | publish: ## Publish package to pypi
24 | python setup.py sdist bdist_wheel
25 | twine upload dist/*
26 | rm -fr build dist .egg src/masonite_backup.egg-info
27 | pypirc: ## Copy the template .pypirc in the repo to your home directory
28 | cp .pypirc ~/.pypirc
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length = 99
3 | target-version = ['py38']
4 | include = '\.pyi?$'
5 | exclude = '''
6 | /(
7 | \.git
8 | \.github
9 | \.vscode
10 | | \.venv
11 | | docs
12 | | node_modules
13 | | tests/integrations/templates
14 | )/
15 | '''
16 |
17 | [tool.isort]
18 | profile = "black"
19 | multi_line_output = 3
20 | include_trailing_comma = true
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | filterwarnings =
3 | ignore::DeprecationWarning
4 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | masonite>=4,<5
2 | masonite-orm>=2,<3
3 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [flake8]
2 | exclude =
3 | .git,
4 | .github,
5 | .vscode,
6 | __pycache__,
7 | templates,
8 | node_modules,
9 | venv
10 | max-complexity = 10
11 | max-line-length = 99
12 |
13 | omit =
14 | */config/*
15 | setup.py
16 | */stubs/*
17 | wsgi.py
18 | tests/
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 | with open("README.md", "r") as fh:
4 | long_description = fh.read()
5 |
6 | setup(
7 | name="masonite-backup",
8 | # Versions should comply with PEP440. For a discussion on single-sourcing
9 | # the version across setup.py and the project code, see
10 | # https://packaging.python.org/en/latest/single_source_version.html
11 | version="0.0.4",
12 | packages=[
13 | "backup",
14 | "backup.commands",
15 | "backup.mailables",
16 | "backup.providers",
17 | "backup.config",
18 | ],
19 | package_dir={"": "src"},
20 | description="Backup solution for Masonite.",
21 | long_description=long_description,
22 | long_description_content_type="text/markdown",
23 | # The project's main homepage.
24 | url="https://github.com/py-package/masonite-backup",
25 | # Author details
26 | author="Yubaraj Shrestha",
27 | author_email="yubaraj@pypackage.com",
28 | # Choose your license
29 | license="MIT license",
30 | # If your package should include things you specify in your MANIFEST.in file
31 | # Use this option if your package needs to include files that are not python files
32 | # like html templates or css files
33 | include_package_data=True,
34 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
35 | classifiers=[
36 | # How mature is this project? Common values are
37 | # 3 - Alpha
38 | # 4 - Beta
39 | # 5 - Production/Stable
40 | "Development Status :: 4 - Beta",
41 | # Indicate who your project is intended for
42 | "Intended Audience :: Developers",
43 | "Topic :: Software Development :: Build Tools",
44 | "Environment :: Web Environment",
45 | # Pick your license as you wish (should match "license" above)
46 | "License :: OSI Approved :: MIT License",
47 | "Operating System :: OS Independent",
48 | # Specify the Python versions you support here. In particular, ensure
49 | # that you indicate whether you support Python 2, Python 3 or both.
50 | "Programming Language :: Python :: 3.6",
51 | "Programming Language :: Python :: 3.7",
52 | "Programming Language :: Python :: 3.8",
53 | "Programming Language :: Python :: 3.9",
54 | "Topic :: Internet :: WWW/HTTP",
55 | "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
56 | "Topic :: Internet :: WWW/HTTP :: WSGI",
57 | "Topic :: Software Development :: Libraries :: Application Frameworks",
58 | "Topic :: Software Development :: Libraries :: Python Modules",
59 | # List package on masonite packages website
60 | "Framework :: Masonite",
61 | ],
62 | # What does your project relate to?
63 | keywords="Masonite, Python, Development",
64 | # List run-time dependencies here. These will be installed by pip when
65 | # your project is installed. For an analysis of "install_requires" vs pip's
66 | # requirements files see:
67 | # https://packaging.python.org/en/latest/requirements.html
68 | install_requires=["masonite>=4.0,<5.0"],
69 | # List additional groups of dependencies here (e.g. development
70 | # dependencies). You can install these using the following syntax,
71 | # for example:
72 | # $ pip install -e .[dev,test]
73 | # $ pip install your-package[dev,test]
74 | extras_require={
75 | "dev": [
76 | "black",
77 | "flake8",
78 | "coverage",
79 | "pytest",
80 | "pytest-cov",
81 | "twine>=1.5.0",
82 | "wheel",
83 | ],
84 | },
85 | # If there are data files included in your packages that need to be
86 | # installed, specify them here. If using Python 2.6 or less, then these
87 | # have to be included in MANIFEST.in as well.
88 | package_data={
89 | # 'templates/index.html': [],
90 | },
91 | )
92 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/src/__init__.py
--------------------------------------------------------------------------------
/src/backup/Backup.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa F501
2 | import pathlib
3 | import shutil
4 | import tempfile
5 | from unittest.mock import patch
6 | from masonite.configuration import config
7 | from shutil import make_archive
8 | from datetime import datetime
9 | from masonite.utils.location import base_path
10 | import subprocess
11 | import gzip
12 | from masonite.facades import Mail
13 | from .mailables.Backup import Backup as BackupMailable
14 |
15 |
16 | class Backup:
17 | def __init__(self, application) -> None:
18 | self.app = application
19 | self.backup_config = config("backup")
20 |
21 | self.db_file_path = None
22 | self.archive_file_path = None
23 |
24 | def accept(self, path):
25 | for pattern in self.backup_config.get("source").get("excludes"):
26 | if pattern in path:
27 | return False
28 | return True
29 |
30 | def database(self):
31 | """
32 | Backup the database.
33 | """
34 |
35 | db_config = config("database.databases")
36 | default = db_config.get("default")
37 | connection = db_config.get(default)
38 | driver = connection.get("driver")
39 |
40 | self.db_file_path = base_path(
41 | "{}.gz".format("database-" + str(datetime.timestamp(datetime.now())))
42 | )
43 |
44 | if driver == "sqlite":
45 | pass
46 | elif driver == "mysql":
47 | command_str = f"mysqldump -u {connection.get('user')} -p{connection.get('password')} {connection.get('database')}"
48 |
49 | elif driver == "postgres":
50 | command_str = f"pg_dump -U{connection.get('user')} -h{connection.get('host')} -p{connection.get('port')} -d{connection.get('database')}"
51 |
52 | elif driver == "mssql":
53 | command_str = f"sqlcmd -S{connection.get('host')} -U{connection.get('user')} -P{connection.get('port')} -d{connection.get('database')}"
54 |
55 | elif driver == "sqlserver":
56 | command_str = f"sqlcmd -S{connection.get('host')} -U{connection.get('user')} -P{connection.get('port')} -d{connection.get('database')}"
57 |
58 | elif driver == "oracle":
59 | command_str = f"sqlplus -S{connection.get('user')}/{connection.get('password')}@{connection.get('host')}:{connection.get('port')}/{connection.get('database')}"
60 |
61 | if command_str:
62 | with gzip.open(self.db_file_path, "wb") as f:
63 | popen = subprocess.Popen(
64 | [command_str],
65 | stdout=subprocess.PIPE,
66 | shell=True,
67 | universal_newlines=True,
68 | )
69 | for stdout_line in iter(popen.stdout.readline, ""):
70 | f.write(stdout_line.encode("utf-8"))
71 | popen.stdout.close()
72 | popen.wait()
73 | return self.db_file_path
74 |
75 | def files(self):
76 | """
77 | Backup the files.
78 | """
79 | filename = (
80 | self.backup_config.get("filename", "backup")
81 | + "-"
82 | + str(datetime.timestamp(datetime.now()))
83 | )
84 |
85 | output_dir = base_path("storage/backup")
86 |
87 | if not pathlib.Path(output_dir).exists():
88 | pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True)
89 |
90 | self.archive_file_path = pathlib.Path(output_dir).joinpath(filename)
91 |
92 | with tempfile.TemporaryDirectory() as tmp:
93 | shutil.copytree(
94 | self.backup_config.get("source").get("root"),
95 | pathlib.Path(tmp).joinpath("backup"),
96 | ignore=shutil.ignore_patterns(*self.backup_config.get("source").get("excludes")),
97 | )
98 |
99 | with patch("os.path.isfile", side_effect=self.accept):
100 | make_archive(self.archive_file_path, "zip", tmp)
101 |
102 | return f"{self.archive_file_path}.zip"
103 |
104 | def email(self, info):
105 | """
106 | Email the backup.
107 | """
108 |
109 | if not self.backup_config.get("email_backup", False):
110 | return
111 |
112 | info("Sending backup to email")
113 | if (
114 | self.archive_file_path != None
115 | and pathlib.Path(f"{self.archive_file_path}.zip").exists()
116 | ):
117 | Mail.mailable(
118 | BackupMailable().attach(f"System Backup.zip", f"{self.archive_file_path}.zip")
119 | ).send()
120 |
121 | if self.db_file_path != None and pathlib.Path(self.db_file_path).exists():
122 | ext = self.db_file_path.split(".")[-1]
123 | Mail.mailable(
124 | BackupMailable().attach(f"Database Backup.{ext}", self.db_file_path)
125 | ).send()
126 |
127 | def s3(self, info):
128 | """
129 | Upload the backup to S3.
130 | """
131 | if not self.backup_config.get("s3_backup", False):
132 | return
133 |
134 | info("Uploading backup to S3")
135 | if (
136 | self.archive_file_path != None
137 | and pathlib.Path(f"{self.archive_file_path}.zip").exists()
138 | ):
139 | self.app.make("storage").disk("s3").put(
140 | f"System Backup.zip", f"{self.archive_file_path}.zip"
141 | )
142 |
143 | if self.db_file_path != None and pathlib.Path(self.db_file_path).exists():
144 | ext = self.db_file_path.split(".")[-1]
145 | self.app.make("storage").disk("s3").put(f"Database Backup.{ext}", self.db_file_path)
146 |
147 | def cleanup(self):
148 | """
149 | Cleanup the backup files.
150 | """
151 | if self.archive_file_path != None and pathlib.Path(self.archive_file_path).exists():
152 | pathlib.Path(self.archive_file_path).unlink()
153 | if self.db_file_path != None and pathlib.Path(self.db_file_path).exists():
154 | pathlib.Path(self.db_file_path).unlink()
155 |
--------------------------------------------------------------------------------
/src/backup/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa F401
2 | from .providers.BackupProvider import BackupProvider
3 |
--------------------------------------------------------------------------------
/src/backup/commands/BackupRunCommand.py:
--------------------------------------------------------------------------------
1 | import os
2 | from masonite.commands import Command
3 |
4 |
5 | class BackupRunCommand(Command):
6 | """
7 | Start the backup process.
8 |
9 | backup:run
10 | {--filename : Backup filename}
11 | {--only-db : Backup database only}
12 | {--only-files : Backup files only}
13 | """
14 |
15 | def __init__(self, application):
16 | super().__init__()
17 | self.app = application
18 | self.database_file_path = None
19 | self.assets_file_path = None
20 |
21 | def handle(self):
22 | backup = self.app.make("backup")
23 |
24 | if not self.validate_options():
25 | return
26 |
27 | self.info("============ Backup starting ============")
28 |
29 | if self.option("only-db"):
30 | self.database_file_path = backup.database()
31 | elif self.option("only-files"):
32 | self.assets_file_path = backup.files()
33 | else:
34 | self.info("Backuping database...")
35 | self.database_file_path = backup.database()
36 | self.info("Backuping files...")
37 | self.assets_file_path = backup.files()
38 |
39 | # delete the database file
40 | os.remove(self.database_file_path)
41 | self.database_file_path = None
42 |
43 | backup.email(self.info)
44 | backup.s3(self.info)
45 | backup.cleanup()
46 |
47 | self.info("============ Backup complete ============")
48 |
49 | def validate_options(self):
50 | if self.option("only-db") and self.option("only-files"):
51 | self.error("You can only pass either files or database backup option.")
52 | return False
53 | return True
54 |
--------------------------------------------------------------------------------
/src/backup/commands/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa F401
2 | from .BackupRunCommand import BackupRunCommand
3 |
--------------------------------------------------------------------------------
/src/backup/config/backup.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa F501
2 | """Backup Settings"""
3 |
4 | from masonite.utils.location import base_path
5 |
6 | """
7 | |--------------------------------------------------------------------------
8 | | Masonite Backup
9 | |--------------------------------------------------------------------------
10 | |
11 | | This is the configuration file for the Masonite Backup package.
12 | |
13 | """
14 |
15 | FILENAME = "backup" # The filename of the backup file. (without the extension)
16 | DIRECTORY = "backup" # storage/backup
17 | SOURCE = {
18 | "root": base_path(),
19 | "excludes": [
20 | ".git",
21 | "storage",
22 | "venv",
23 | "node_modules",
24 | "__pycache__",
25 | ],
26 | }
27 | S3_BACKUP = False # Whether or not to backup in S3.
28 | EMAIL_BACKUP = False # Whether or not to email the backup.
29 | EMAIL_BACKUP_TO = "" # The email address to send the backup to.
30 | EMAIL_SUBJECT = "System Backup" # The email subject.
31 |
--------------------------------------------------------------------------------
/src/backup/mailables/Backup.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa F501
2 | from masonite.mail import Mailable
3 | from masonite.configuration import config
4 | from masonite.environment import env
5 |
6 |
7 | class Backup(Mailable):
8 | def build(self):
9 | backup_config = config("backup")
10 | email = backup_config.get("email_backup_to")
11 |
12 | if not email:
13 | raise Exception("No email address found in backup config.")
14 |
15 | return (
16 | self.to(email)
17 | .subject(backup_config.get("email_subject"))
18 | .from_(env("MAIL_FROM"))
19 | .html(
20 | """
21 |
22 |
Backup Complete
23 |
24 | Your backup has been completed and is now available for download.
Please, find the file attached here within.
25 |
26 |
Thanks,
Masonite Backup
27 |
28 | """
29 | )
30 | )
31 |
--------------------------------------------------------------------------------
/src/backup/mailables/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa F401
2 | from .Backup import Backup
3 |
--------------------------------------------------------------------------------
/src/backup/providers/BackupProvider.py:
--------------------------------------------------------------------------------
1 | """A BackupProvider Service Provider."""
2 |
3 | from masonite.packages import PackageProvider
4 | from ..Backup import Backup
5 | from ..commands import BackupRunCommand
6 |
7 |
8 | class BackupProvider(PackageProvider):
9 | def configure(self):
10 | """Register objects into the Service Container."""
11 | (self.root("backup").name("backup").config("config/backup.py", publish=True))
12 |
13 | def register(self):
14 | super().register()
15 |
16 | self.application.bind("backup", Backup(application=self.application))
17 | self.application.make("commands").add(BackupRunCommand(application=self.application))
18 |
19 | def boot(self):
20 | """Boots services required by the container."""
21 | pass
22 |
--------------------------------------------------------------------------------
/src/backup/providers/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa: E501
2 | from .BackupProvider import BackupProvider
3 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/__init__.py
--------------------------------------------------------------------------------
/tests/integrations/Kernel.py:
--------------------------------------------------------------------------------
1 | from masonite.foundation import response_handler
2 | from masonite.storage import StorageCapsule
3 | from masonite.auth import Sign
4 | from masonite.environment import LoadEnvironment
5 | from masonite.utils.structures import load
6 | from masonite.utils.location import base_path
7 | from masonite.middleware import (
8 | SessionMiddleware,
9 | EncryptCookies,
10 | LoadUserMiddleware,
11 | MaintenanceModeMiddleware,
12 | )
13 | from masonite.routes import Route
14 | from masonite.configuration.Configuration import Configuration
15 | from masonite.configuration import config
16 |
17 | from tests.integrations.app.middlewares import VerifyCsrfToken, AuthenticationMiddleware
18 |
19 |
20 | class Kernel:
21 |
22 | http_middleware = [MaintenanceModeMiddleware, EncryptCookies]
23 |
24 | route_middleware = {
25 | "web": [SessionMiddleware, LoadUserMiddleware, VerifyCsrfToken],
26 | "auth": [AuthenticationMiddleware],
27 | }
28 |
29 | def __init__(self, app):
30 | self.application = app
31 |
32 | def register(self):
33 | # Register routes
34 | self.load_environment()
35 | self.register_configurations()
36 | self.register_middleware()
37 | self.register_routes()
38 | self.register_database()
39 | self.register_templates()
40 | self.register_storage()
41 |
42 | def load_environment(self):
43 | LoadEnvironment()
44 |
45 | def register_configurations(self):
46 | # load configuration
47 | self.application.bind("config.location", "tests/integrations/config")
48 | configuration = Configuration(self.application)
49 | configuration.load()
50 | self.application.bind("config", configuration)
51 | key = config("application.key")
52 | self.application.bind("key", key)
53 | self.application.bind("sign", Sign(key))
54 | # set locations
55 | self.application.bind("resources.location", "tests/integrations/resources/")
56 | self.application.bind("controllers.location", "tests/integrations/app/controllers")
57 | self.application.bind("jobs.location", "tests/integrations/app/jobs")
58 | self.application.bind("providers.location", "tests/integrations/app/providers")
59 | self.application.bind("mailables.location", "tests/integrations/app/mailables")
60 | self.application.bind("listeners.location", "tests/integrations/app/listeners")
61 | self.application.bind("validation.location", "tests/integrations/app/validation")
62 | self.application.bind("notifications.location", "tests/integrations/app/notifications")
63 | self.application.bind("events.location", "tests/integrations/app/events")
64 | self.application.bind("tasks.location", "tests/integrations/app/tasks")
65 | self.application.bind("models.location", "tests/integrations/app/models")
66 | self.application.bind("observers.location", "tests/integrations/app/models/observers")
67 | self.application.bind("policies.location", "tests/integrations/app/policies")
68 | self.application.bind("commands.location", "tests/integrations/app/commands")
69 | self.application.bind("middlewares.location", "tests/integrations/app/middlewares")
70 |
71 | self.application.bind("server.runner", "masonite.commands.ServeCommand.main")
72 |
73 | def register_middleware(self):
74 | self.application.make("middleware").add(self.route_middleware).add(self.http_middleware)
75 |
76 | def register_routes(self):
77 | Route.set_controller_locations(self.application.make("controllers.location"))
78 | self.application.bind("routes.location", "tests/integrations/routes/web")
79 | self.application.make("router").add(
80 | Route.group(
81 | load(self.application.make("routes.location"), "ROUTES"), middleware=["web"]
82 | )
83 | )
84 |
85 | def register_database(self):
86 | from masoniteorm.query import QueryBuilder
87 |
88 | self.application.bind(
89 | "builder",
90 | QueryBuilder(connection_details=config("database.databases")),
91 | )
92 |
93 | self.application.bind("migrations.location", "tests/integrations/databases/migrations")
94 | self.application.bind("seeds.location", "tests/integrations/databases/seeds")
95 |
96 | self.application.bind("resolver", config("database.db"))
97 |
98 | def register_templates(self):
99 | self.application.bind("views.location", "tests/integrations/templates/")
100 |
101 | def register_storage(self):
102 | storage = StorageCapsule()
103 | storage.add_storage_assets(config("filesystem.staticfiles"))
104 | self.application.bind("storage_capsule", storage)
105 |
106 | self.application.set_response_handler(response_handler)
107 | self.application.use_storage_path(base_path("storage"))
108 |
--------------------------------------------------------------------------------
/tests/integrations/app/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/app/__init__.py
--------------------------------------------------------------------------------
/tests/integrations/app/controllers/WelcomeController.py:
--------------------------------------------------------------------------------
1 | """A WelcomeController Module."""
2 | from masonite.views import View
3 | from masonite.controllers import Controller
4 |
5 |
6 | class WelcomeController(Controller):
7 | """WelcomeController Controller Class."""
8 |
9 | def show(self, view: View):
10 | return view.render("welcome")
11 |
--------------------------------------------------------------------------------
/tests/integrations/app/controllers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/app/controllers/__init__.py
--------------------------------------------------------------------------------
/tests/integrations/app/middlewares/AuthenticationMiddleware.py:
--------------------------------------------------------------------------------
1 | from masonite.middleware import Middleware
2 |
3 |
4 | class AuthenticationMiddleware(Middleware):
5 | """Middleware to check if the user is logged in."""
6 |
7 | def before(self, request, response):
8 | if not request.user():
9 | return response.redirect(name="login")
10 | return request
11 |
12 | def after(self, request, response):
13 | return request
14 |
--------------------------------------------------------------------------------
/tests/integrations/app/middlewares/VerifyCsrfToken.py:
--------------------------------------------------------------------------------
1 | from masonite.middleware import VerifyCsrfToken as Middleware
2 |
3 |
4 | class VerifyCsrfToken(Middleware):
5 |
6 | exempt = []
7 |
--------------------------------------------------------------------------------
/tests/integrations/app/middlewares/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa: F401
2 | from .VerifyCsrfToken import VerifyCsrfToken
3 | from .AuthenticationMiddleware import AuthenticationMiddleware
4 |
--------------------------------------------------------------------------------
/tests/integrations/app/models/User.py:
--------------------------------------------------------------------------------
1 | """User Model."""
2 | from masoniteorm.models import Model
3 | from masoniteorm.scopes import SoftDeletesMixin
4 | from masonite.authentication import Authenticates
5 |
6 |
7 | class User(Model, SoftDeletesMixin, Authenticates):
8 | """User Model."""
9 |
10 | __fillable__ = ["name", "email", "password"]
11 | __hidden__ = ["password"]
12 | __auth__ = "email"
13 |
--------------------------------------------------------------------------------
/tests/integrations/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/config/__init__.py
--------------------------------------------------------------------------------
/tests/integrations/config/application.py:
--------------------------------------------------------------------------------
1 | from masonite.environment import env
2 |
3 |
4 | KEY = env("APP_KEY", "-RkDOqXojJIlsF_I8wWiUq_KRZ0PtGWTOZ676u5HtLg=")
5 |
6 | HASHING = {
7 | "default": env("HASHING_FUNCTION", "bcrypt"),
8 | "bcrypt": {"rounds": 10},
9 | "argon2": {"memory": 1024, "threads": 2, "time": 2},
10 | }
11 |
12 | APP_URL = env("APP_URL", "http://localhost:8000/")
13 |
--------------------------------------------------------------------------------
/tests/integrations/config/auth.py:
--------------------------------------------------------------------------------
1 | from tests.integrations.app.models.User import User
2 |
3 | GUARDS = {
4 | "default": "web",
5 | "web": {"model": User},
6 | "password_reset_table": "password_resets",
7 | "password_reset_expiration": 1440, # in minutes. 24 hours. None if disabled
8 | }
9 |
--------------------------------------------------------------------------------
/tests/integrations/config/broadcast.py:
--------------------------------------------------------------------------------
1 | from masonite.environment import env
2 |
3 |
4 | BROADCASTS = {
5 | "default": "pusher",
6 | "pusher": {
7 | "driver": "pusher",
8 | "client": env("PUSHER_CLIENT"),
9 | "app_id": env("PUSHER_APP_ID"),
10 | "secret": env("PUSHER_SECRET"),
11 | "cluster": env("PUSHER_CLUSTER"),
12 | "ssl": False,
13 | },
14 | }
15 |
--------------------------------------------------------------------------------
/tests/integrations/config/cache.py:
--------------------------------------------------------------------------------
1 | # from masonite.environment import env
2 |
3 |
4 | STORES = {
5 | "default": "local",
6 | "local": {
7 | "driver": "file",
8 | "location": "storage/framework/cache"
9 | #
10 | },
11 | "redis": {
12 | "driver": "redis",
13 | "host": "127.0.0.1",
14 | "port": "6379",
15 | "password": "",
16 | "name": "project_name",
17 | },
18 | "memcache": {
19 | "driver": "memcache",
20 | "host": "127.0.0.1",
21 | "port": "11211",
22 | "password": "",
23 | "name": "project_name",
24 | },
25 | }
26 |
--------------------------------------------------------------------------------
/tests/integrations/config/database.py:
--------------------------------------------------------------------------------
1 | from masonite.environment import LoadEnvironment, env
2 | from masoniteorm.connections import ConnectionResolver
3 |
4 | # Loads in the environment variables when this page is imported.
5 | LoadEnvironment()
6 |
7 | """
8 | The connections here don't determine the database but determine the "connection".
9 | They can be named whatever you want.
10 | """
11 | DATABASES = {
12 | "default": env("DB_CONNECTION", "sqlite"),
13 | "sqlite": {
14 | "driver": "sqlite",
15 | "database": env("SQLITE_DB_DATABASE", "masonite.sqlite3"),
16 | "prefix": "",
17 | "log_queries": env("DB_LOG"),
18 | },
19 | "mysql": {
20 | "driver": "mysql",
21 | "host": env("DB_HOST"),
22 | "user": env("DB_USERNAME"),
23 | "password": env("DB_PASSWORD"),
24 | "database": env("DB_DATABASE"),
25 | "port": env("DB_PORT"),
26 | "prefix": "",
27 | "grammar": "mysql",
28 | "options": {
29 | "charset": "utf8mb4",
30 | },
31 | "log_queries": env("DB_LOG"),
32 | },
33 | "postgres": {
34 | "driver": "postgres",
35 | "host": env("DB_HOST"),
36 | "user": env("DB_USERNAME"),
37 | "password": env("DB_PASSWORD"),
38 | "database": env("DB_DATABASE"),
39 | "port": env("DB_PORT"),
40 | "prefix": "",
41 | "grammar": "postgres",
42 | "log_queries": env("DB_LOG"),
43 | },
44 | "mssql": {
45 | "driver": "mssql",
46 | "host": env("MSSQL_DATABASE_HOST"),
47 | "user": env("MSSQL_DATABASE_USER"),
48 | "password": env("MSSQL_DATABASE_PASSWORD"),
49 | "database": env("MSSQL_DATABASE_DATABASE"),
50 | "port": env("MSSQL_DATABASE_PORT"),
51 | "prefix": "",
52 | "log_queries": env("DB_LOG"),
53 | },
54 | }
55 |
56 | DB = ConnectionResolver().set_connection_details(DATABASES)
57 |
--------------------------------------------------------------------------------
/tests/integrations/config/exceptions.py:
--------------------------------------------------------------------------------
1 | HANDLERS = {"stack_overflow": True, "solutions": True}
2 |
--------------------------------------------------------------------------------
/tests/integrations/config/filesystem.py:
--------------------------------------------------------------------------------
1 | from masonite.environment import env
2 | from masonite.utils.location import base_path
3 |
4 |
5 | DISKS = {
6 | "default": "local",
7 | "local": {
8 | "driver": "file",
9 | "path": base_path("tests/integrations/storage/framework/filesystem")
10 | },
11 | "s3": {
12 | "driver": "s3",
13 | "client": env("AWS_CLIENT"),
14 | "secret": env("AWS_SECRET"),
15 | "bucket": env("AWS_BUCKET"),
16 | },
17 | }
18 |
19 | STATICFILES = {
20 | # folder # template alias
21 | 'tests/integrations/storage/static': 'static/',
22 | 'tests/integrations/storage/compiled': 'assets/',
23 | 'tests/integrations/storage/public': '/',
24 | }
25 |
--------------------------------------------------------------------------------
/tests/integrations/config/mail.py:
--------------------------------------------------------------------------------
1 | from masonite.environment import env
2 |
3 |
4 | FROM_EMAIL = env("MAIL_FROM", "no-reply@masonite.com")
5 |
6 | DRIVERS = {
7 | "default": env("MAIL_DRIVER", "terminal"),
8 | "smtp": {
9 | "host": env("MAIL_HOST"),
10 | "port": env("MAIL_PORT"),
11 | "username": env("MAIL_USERNAME"),
12 | "password": env("MAIL_PASSWORD"),
13 | "from": FROM_EMAIL,
14 | },
15 | "mailgun": {
16 | "domain": env("MAILGUN_DOMAIN"),
17 | "secret": env("MAILGUN_SECRET"),
18 | "from": FROM_EMAIL,
19 | },
20 | "terminal": {
21 | "from": FROM_EMAIL,
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/tests/integrations/config/notification.py:
--------------------------------------------------------------------------------
1 | from masonite.environment import env
2 |
3 |
4 | DRIVERS = {
5 | "slack": {
6 | "token": env("SLACK_TOKEN", ""), # used for API mode
7 | "webhook": env("SLACK_WEBHOOK", ""), # used for webhook mode
8 | },
9 | "vonage": {
10 | "key": env("VONAGE_KEY", ""),
11 | "secret": env("VONAGE_SECRET", ""),
12 | "sms_from": env("VONAGE_SMS_FROM", "+33000000000"),
13 | },
14 | "database": {
15 | "connection": "sqlite",
16 | "table": "notifications",
17 | },
18 | }
19 |
20 | DRY = False
21 |
--------------------------------------------------------------------------------
/tests/integrations/config/providers.py:
--------------------------------------------------------------------------------
1 | from masonite.providers import (
2 | RouteProvider,
3 | FrameworkProvider,
4 | ViewProvider,
5 | WhitenoiseProvider,
6 | ExceptionProvider,
7 | MailProvider,
8 | SessionProvider,
9 | QueueProvider,
10 | CacheProvider,
11 | EventProvider,
12 | StorageProvider,
13 | HelpersProvider,
14 | BroadcastProvider,
15 | AuthenticationProvider,
16 | AuthorizationProvider,
17 | HashServiceProvider,
18 | ORMProvider,
19 | )
20 |
21 |
22 | from masonite.scheduling.providers import ScheduleProvider
23 | from masonite.notification.providers import NotificationProvider
24 | from masonite.validation.providers import ValidationProvider
25 |
26 | # register local package
27 | from src.backup import BackupProvider
28 |
29 |
30 | PROVIDERS = [
31 | FrameworkProvider,
32 | HelpersProvider,
33 | RouteProvider,
34 | ViewProvider,
35 | WhitenoiseProvider,
36 | ExceptionProvider,
37 | MailProvider,
38 | NotificationProvider,
39 | SessionProvider,
40 | CacheProvider,
41 | QueueProvider,
42 | ScheduleProvider,
43 | EventProvider,
44 | StorageProvider,
45 | BroadcastProvider,
46 | HashServiceProvider,
47 | AuthenticationProvider,
48 | ValidationProvider,
49 | AuthorizationProvider,
50 | ORMProvider
51 | ]
52 |
53 | PROVIDERS += [BackupProvider]
54 |
--------------------------------------------------------------------------------
/tests/integrations/config/queue.py:
--------------------------------------------------------------------------------
1 | # from masonite.environment import env
2 |
3 |
4 | DRIVERS = {
5 | "default": "async",
6 | "database": {
7 | "connection": "sqlite",
8 | "table": "jobs",
9 | "failed_table": "failed_jobs",
10 | "attempts": 3,
11 | "poll": 5,
12 | },
13 | "redis": {
14 | #
15 | },
16 | "amqp": {
17 | "username": "guest",
18 | "password": "guest",
19 | "port": "5672",
20 | "vhost": "",
21 | "host": "localhost",
22 | "channel": "default",
23 | "queue": "masonite4",
24 | },
25 | "async": {
26 | "blocking": True,
27 | "callback": "handle",
28 | "mode": "threading",
29 | "workers": 1,
30 | },
31 | }
32 |
--------------------------------------------------------------------------------
/tests/integrations/config/session.py:
--------------------------------------------------------------------------------
1 | # from masonite.environment import env
2 |
3 |
4 | DRIVERS = {
5 | "default": "cookie",
6 | "cookie": {},
7 | }
8 |
--------------------------------------------------------------------------------
/tests/integrations/databases/migrations/2021_01_09_033202_create_password_reset_table.py:
--------------------------------------------------------------------------------
1 | from masoniteorm.migrations import Migration
2 |
3 |
4 | class CreatePasswordResetTable(Migration):
5 | def up(self):
6 | """Run the migrations."""
7 | with self.schema.create("password_resets") as table:
8 | table.string("email").unique()
9 | table.string("token")
10 | table.datetime("expires_at").nullable()
11 | table.datetime("created_at")
12 |
13 | def down(self):
14 | """Revert the migrations."""
15 | self.schema.drop("password_resets")
16 |
--------------------------------------------------------------------------------
/tests/integrations/databases/migrations/2021_01_09_043202_create_users_table.py:
--------------------------------------------------------------------------------
1 | from masoniteorm.migrations import Migration
2 |
3 |
4 | class CreateUsersTable(Migration):
5 | def up(self):
6 | """Run the migrations."""
7 | with self.schema.create("users") as table:
8 | table.increments("id")
9 | table.string("name")
10 | table.string("email").unique()
11 | table.string("password")
12 | table.string("second_password").nullable()
13 | table.string("remember_token").nullable()
14 | table.string("phone").nullable()
15 | table.timestamp("verified_at").nullable()
16 | table.timestamps()
17 | table.soft_deletes()
18 |
19 | def down(self):
20 | """Revert the migrations."""
21 | self.schema.drop("users")
22 |
--------------------------------------------------------------------------------
/tests/integrations/databases/seeds/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/databases/seeds/__init__.py
--------------------------------------------------------------------------------
/tests/integrations/databases/seeds/database_seeder.py:
--------------------------------------------------------------------------------
1 | """Base Database Seeder Module."""
2 | from masoniteorm.seeds import Seeder
3 |
4 | from .user_table_seeder import UserTableSeeder
5 |
6 |
7 | class DatabaseSeeder(Seeder):
8 | def run(self):
9 | """Run the database seeds."""
10 | self.call(UserTableSeeder)
11 |
--------------------------------------------------------------------------------
/tests/integrations/databases/seeds/user_table_seeder.py:
--------------------------------------------------------------------------------
1 | """UserTableSeeder Seeder."""
2 | from masoniteorm.seeds import Seeder
3 | from masonite.facades import Hash
4 |
5 | from tests.integrations.app.models.User import User
6 |
7 |
8 | class UserTableSeeder(Seeder):
9 | def run(self):
10 | """Run the database seeds."""
11 | User.create(
12 | {
13 | "name": "Joe",
14 | "email": "user@example.com",
15 | "password": Hash.make("secret"),
16 | "phone": "+123456789",
17 | }
18 | )
19 |
--------------------------------------------------------------------------------
/tests/integrations/resources/css/app.css:
--------------------------------------------------------------------------------
1 | /* Put your CSS here */
2 |
--------------------------------------------------------------------------------
/tests/integrations/resources/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | require("./bootstrap.js")
3 |
--------------------------------------------------------------------------------
/tests/integrations/resources/js/bootstrap.js:
--------------------------------------------------------------------------------
1 | /**
2 | * We'll load the axios HTTP library which allows us to easily issue requests
3 | * to our Masonite back-end. This library automatically handles sending the
4 | * CSRF token as a header based on the value of the "XSRF" token cookie.
5 | */
6 |
7 | window.axios = require('axios');
8 |
9 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
10 |
11 | /**
12 | * Next we will register the CSRF Token as a common header with Axios so that
13 | * all outgoing HTTP requests automatically have it attached. This is just
14 | * a simple convenience so we don't have to attach every token manually.
15 | */
16 |
17 | let token = document.head.querySelector('meta[name="csrf-token"]');
18 |
19 | if (token) {
20 | window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
21 | } else {
22 | console.error('CSRF token not found: https://docs.masoniteproject.com/features/csrf#ajax-vue-axios');
23 | }
24 |
--------------------------------------------------------------------------------
/tests/integrations/routes/web.py:
--------------------------------------------------------------------------------
1 | from masonite.routes import Route
2 |
3 | ROUTES = [Route.get("/", "WelcomeController@show")]
4 |
--------------------------------------------------------------------------------
/tests/integrations/storage/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/storage/.gitignore
--------------------------------------------------------------------------------
/tests/integrations/storage/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/storage/public/favicon.ico
--------------------------------------------------------------------------------
/tests/integrations/storage/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/storage/public/logo.png
--------------------------------------------------------------------------------
/tests/integrations/storage/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
--------------------------------------------------------------------------------
/tests/integrations/templates/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/integrations/templates/__init__.py
--------------------------------------------------------------------------------
/tests/integrations/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {% block title %}Masonite 4{% endblock %}
9 |
10 |
14 | {% block head %}
15 |
16 | {% endblock %}
17 |
18 |
19 | {% block content %}{% endblock %}
20 | {% block js %}
21 |
22 | {% endblock %}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tests/integrations/templates/errors/403.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Permission Denied
9 |
10 |
11 |
12 |
13 | {% block content %}
14 |
15 |
Oops looks like you don't have access to this page !
16 |
17 | {% endblock %}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tests/integrations/templates/errors/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Page Not Found
9 |
10 |
11 |
12 |
13 | {% block content %}
14 |
15 |
Oops this page does not exist !
16 |
17 | {% endblock %}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tests/integrations/templates/errors/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Error 500
9 |
10 |
11 |
12 |
13 | {% block content %}
14 |
15 |
Oops an error happened !
16 |
17 | {% endblock %}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tests/integrations/templates/maintenance.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Server Maintenance
9 |
10 |
11 |
12 |
13 | {% block content %}
14 |
15 |
Sorry, this site is currently down for maintenance.
16 |
17 | {% endblock %}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/tests/integrations/templates/welcome.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% block title %}Welcome on Masonite 4{% endblock %}
3 |
4 | {% block content %}
5 |
34 | {% endblock %}
--------------------------------------------------------------------------------
/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/py-package/masonite-backup/089031213f024093f7b117338c1fbae03a2015cb/tests/unit/__init__.py
--------------------------------------------------------------------------------
/tests/unit/test_package.py:
--------------------------------------------------------------------------------
1 | from masonite.tests import TestCase
2 |
3 |
4 | class TestBackup(TestCase):
5 |
6 | def test_example(self):
7 | self.assertTrue(True)
8 |
--------------------------------------------------------------------------------
/wsgi.py:
--------------------------------------------------------------------------------
1 | from masonite.foundation import Application, Kernel
2 | from tests.integrations.config.providers import PROVIDERS
3 | from tests.integrations.Kernel import Kernel as ApplicationKernel
4 |
5 |
6 | """Start The Application Instance."""
7 | application = Application("tests/integrations")
8 |
9 | """Now Bind important providers needed to make the framework work."""
10 | application.register_providers(Kernel, ApplicationKernel)
11 |
12 | """Now Bind important application specific providers needed to make the application work."""
13 | application.add_providers(*PROVIDERS)
14 |
--------------------------------------------------------------------------------