plain 0.4.1__py3-none-any.whl → 0.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plain/cli/cli.py +36 -13
- plain/csrf/middleware.py +23 -40
- plain/forms/fields.py +2 -3
- plain/forms/forms.py +2 -1
- plain/http/request.py +5 -5
- plain/internal/handlers/base.py +13 -1
- plain/internal/middleware/headers.py +19 -0
- plain/internal/middleware/https.py +36 -0
- plain/{middleware/common.py → internal/middleware/slash.py} +2 -25
- plain/preflight/security/base.py +5 -174
- plain/preflight/security/csrf.py +1 -5
- plain/runtime/README.md +0 -4
- plain/runtime/__init__.py +13 -15
- plain/runtime/global_settings.py +38 -55
- plain/runtime/user_settings.py +226 -217
- plain/signing.py +5 -23
- plain/test/client.py +17 -17
- plain/utils/timezone.py +2 -23
- plain/views/base.py +4 -0
- {plain-0.4.1.dist-info → plain-0.11.0.dist-info}/METADATA +2 -2
- {plain-0.4.1.dist-info → plain-0.11.0.dist-info}/RECORD +25 -27
- {plain-0.4.1.dist-info → plain-0.11.0.dist-info}/WHEEL +1 -1
- plain/middleware/README.md +0 -3
- plain/middleware/clickjacking.py +0 -52
- plain/middleware/gzip.py +0 -64
- plain/middleware/security.py +0 -64
- /plain/{middleware → internal/middleware}/__init__.py +0 -0
- {plain-0.4.1.dist-info → plain-0.11.0.dist-info}/LICENSE +0 -0
- {plain-0.4.1.dist-info → plain-0.11.0.dist-info}/entry_points.txt +0 -0
plain/runtime/__init__.py
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
import importlib.metadata
|
2
2
|
import sys
|
3
|
-
from
|
3
|
+
from importlib.metadata import entry_points
|
4
4
|
from pathlib import Path
|
5
5
|
|
6
|
-
from
|
7
|
-
|
8
|
-
from .user_settings import LazySettings
|
6
|
+
from .user_settings import Settings
|
9
7
|
|
10
8
|
try:
|
11
9
|
__version__ = importlib.metadata.version("plain")
|
@@ -16,9 +14,8 @@ except importlib.metadata.PackageNotFoundError:
|
|
16
14
|
# Made available without setup or settings
|
17
15
|
APP_PATH = Path.cwd() / "app"
|
18
16
|
|
19
|
-
|
20
17
|
# from plain.runtime import settings
|
21
|
-
settings =
|
18
|
+
settings = Settings()
|
22
19
|
|
23
20
|
|
24
21
|
class AppPathNotFound(RuntimeError):
|
@@ -30,6 +27,11 @@ def setup():
|
|
30
27
|
Configure the settings (this happens as a side effect of accessing the
|
31
28
|
first setting), configure logging and populate the app registry.
|
32
29
|
"""
|
30
|
+
|
31
|
+
# Packages can hook into the setup process through an entrypoint.
|
32
|
+
for entry_point in entry_points().select(group="plain.setup"):
|
33
|
+
entry_point.load()()
|
34
|
+
|
33
35
|
from plain.logs import configure_logging
|
34
36
|
from plain.packages import packages
|
35
37
|
|
@@ -38,15 +40,11 @@ def setup():
|
|
38
40
|
"No app directory found. Are you sure you're in a Plain project?"
|
39
41
|
)
|
40
42
|
|
41
|
-
# Automatically put the
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if app_env := environ.get("PLAIN_ENV", ""):
|
47
|
-
load_dotenv(f".env.{app_env}")
|
48
|
-
else:
|
49
|
-
load_dotenv(".env")
|
43
|
+
# Automatically put the project dir on the Python path
|
44
|
+
# which doesn't otherwise happen when you run `plain` commands.
|
45
|
+
# This makes "app.<module>" imports and relative imports work.
|
46
|
+
if APP_PATH.parent not in sys.path:
|
47
|
+
sys.path.insert(0, APP_PATH.parent.as_posix())
|
50
48
|
|
51
49
|
configure_logging(settings.LOGGING)
|
52
50
|
|
plain/runtime/global_settings.py
CHANGED
@@ -20,23 +20,50 @@ ALLOWED_HOSTS: list[str] = []
|
|
20
20
|
|
21
21
|
# Local time zone for this installation. All choices can be found here:
|
22
22
|
# https://en.wikipedia.org/wiki/List_of_tz_zones_by_name (although not all
|
23
|
-
# systems may support all possibilities).
|
24
|
-
#
|
25
|
-
TIME_ZONE = "
|
26
|
-
|
27
|
-
# If you set this to True, Plain will use timezone-aware datetimes.
|
28
|
-
USE_TZ = True
|
23
|
+
# systems may support all possibilities). This is interpreted as the default
|
24
|
+
# user time zone.
|
25
|
+
TIME_ZONE: str = "UTC"
|
29
26
|
|
30
27
|
# Default charset to use for all Response objects, if a MIME type isn't
|
31
28
|
# manually specified. It's used to construct the Content-Type header.
|
32
29
|
DEFAULT_CHARSET = "utf-8"
|
33
30
|
|
34
31
|
# List of strings representing installed packages.
|
35
|
-
INSTALLED_PACKAGES: list = []
|
32
|
+
INSTALLED_PACKAGES: list[str] = []
|
36
33
|
|
37
34
|
# Whether to append trailing slashes to URLs.
|
38
35
|
APPEND_SLASH = True
|
39
36
|
|
37
|
+
# Default headers for all responses.
|
38
|
+
DEFAULT_RESPONSE_HEADERS = {
|
39
|
+
# "Content-Security-Policy": "default-src 'self'",
|
40
|
+
# https://hstspreload.org/
|
41
|
+
# "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
|
42
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
43
|
+
"Referrer-Policy": "same-origin",
|
44
|
+
"X-Content-Type-Options": "nosniff",
|
45
|
+
"X-Frame-Options": "DENY",
|
46
|
+
}
|
47
|
+
|
48
|
+
# Whether to redirect all non-HTTPS requests to HTTPS.
|
49
|
+
HTTPS_REDIRECT_ENABLED = True
|
50
|
+
HTTPS_REDIRECT_EXEMPT = []
|
51
|
+
HTTPS_REDIRECT_HOST = None
|
52
|
+
|
53
|
+
# If your Plain app is behind a proxy that sets a header to specify secure
|
54
|
+
# connections, AND that proxy ensures that user-submitted headers with the
|
55
|
+
# same name are ignored (so that people can't spoof it), set this value to
|
56
|
+
# a tuple of (header_name, header_value). For any requests that come in with
|
57
|
+
# that header/value, request.is_https() will return True.
|
58
|
+
# WARNING! Only set this if you fully understand what you're doing. Otherwise,
|
59
|
+
# you may be opening yourself up to a security risk.
|
60
|
+
HTTPS_PROXY_HEADER = None
|
61
|
+
|
62
|
+
# Whether to use the X-Forwarded-Host and X-Forwarded-Port headers
|
63
|
+
# when determining the host and port for the request.
|
64
|
+
USE_X_FORWARDED_HOST = False
|
65
|
+
USE_X_FORWARDED_PORT = False
|
66
|
+
|
40
67
|
# A secret key for this particular Plain installation. Used in secret-key
|
41
68
|
# hashing algorithms. Set this in your settings, or Plain will complain
|
42
69
|
# loudly.
|
@@ -46,7 +73,7 @@ SECRET_KEY: str
|
|
46
73
|
# secret key rotation.
|
47
74
|
SECRET_KEY_FALLBACKS: list[str] = []
|
48
75
|
|
49
|
-
ROOT_URLCONF = "urls"
|
76
|
+
ROOT_URLCONF = "app.urls"
|
50
77
|
|
51
78
|
# List of upload handler classes to be applied in order.
|
52
79
|
FILE_UPLOAD_HANDLERS = [
|
@@ -75,34 +102,9 @@ DATA_UPLOAD_MAX_NUMBER_FILES = 100
|
|
75
102
|
# (i.e. "/tmp" on *nix systems).
|
76
103
|
FILE_UPLOAD_TEMP_DIR = None
|
77
104
|
|
78
|
-
# The numeric mode to set newly-uploaded files to. The value should be a mode
|
79
|
-
# you'd pass directly to os.chmod; see
|
80
|
-
# https://docs.python.org/library/os.html#files-and-directories.
|
81
|
-
FILE_UPLOAD_PERMISSIONS = 0o644
|
82
|
-
|
83
|
-
# The numeric mode to assign to newly-created directories, when uploading files.
|
84
|
-
# The value should be a mode as you'd pass to os.chmod;
|
85
|
-
# see https://docs.python.org/library/os.html#files-and-directories.
|
86
|
-
FILE_UPLOAD_DIRECTORY_PERMISSIONS = None
|
87
|
-
|
88
|
-
# Default X-Frame-Options header value
|
89
|
-
X_FRAME_OPTIONS = "DENY"
|
90
|
-
|
91
|
-
USE_X_FORWARDED_HOST = False
|
92
|
-
USE_X_FORWARDED_PORT = False
|
93
|
-
|
94
105
|
# User-defined overrides for error views by status code
|
95
106
|
HTTP_ERROR_VIEWS: dict[int] = {}
|
96
107
|
|
97
|
-
# If your Plain app is behind a proxy that sets a header to specify secure
|
98
|
-
# connections, AND that proxy ensures that user-submitted headers with the
|
99
|
-
# same name are ignored (so that people can't spoof it), set this value to
|
100
|
-
# a tuple of (header_name, header_value). For any requests that come in with
|
101
|
-
# that header/value, request.is_secure() will return True.
|
102
|
-
# WARNING! Only set this if you fully understand what you're doing. Otherwise,
|
103
|
-
# you may be opening yourself up to a security risk.
|
104
|
-
SECURE_PROXY_SSL_HEADER = None
|
105
|
-
|
106
108
|
##############
|
107
109
|
# MIDDLEWARE #
|
108
110
|
##############
|
@@ -110,18 +112,13 @@ SECURE_PROXY_SSL_HEADER = None
|
|
110
112
|
# List of middleware to use. Order is important; in the request phase, these
|
111
113
|
# middleware will be applied in the order given, and in the response
|
112
114
|
# phase the middleware will be applied in reverse order.
|
113
|
-
MIDDLEWARE = [
|
114
|
-
"plain.middleware.security.SecurityMiddleware",
|
115
|
-
"plain.middleware.common.CommonMiddleware",
|
116
|
-
"plain.csrf.middleware.CsrfViewMiddleware",
|
117
|
-
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
|
118
|
-
]
|
115
|
+
MIDDLEWARE: list[str] = []
|
119
116
|
|
120
117
|
###########
|
121
118
|
# SIGNING #
|
122
119
|
###########
|
123
120
|
|
124
|
-
|
121
|
+
COOKIE_SIGNING_BACKEND = "plain.signing.TimestampSigner"
|
125
122
|
|
126
123
|
########
|
127
124
|
# CSRF #
|
@@ -132,12 +129,11 @@ CSRF_COOKIE_NAME = "csrftoken"
|
|
132
129
|
CSRF_COOKIE_AGE = 60 * 60 * 24 * 7 * 52
|
133
130
|
CSRF_COOKIE_DOMAIN = None
|
134
131
|
CSRF_COOKIE_PATH = "/"
|
135
|
-
CSRF_COOKIE_SECURE =
|
132
|
+
CSRF_COOKIE_SECURE = True
|
136
133
|
CSRF_COOKIE_HTTPONLY = False
|
137
134
|
CSRF_COOKIE_SAMESITE = "Lax"
|
138
135
|
CSRF_HEADER_NAME = "HTTP_X_CSRFTOKEN"
|
139
136
|
CSRF_TRUSTED_ORIGINS: list[str] = []
|
140
|
-
CSRF_USE_SESSIONS = False
|
141
137
|
|
142
138
|
###########
|
143
139
|
# LOGGING #
|
@@ -167,19 +163,6 @@ ASSETS_BASE_URL: str = ""
|
|
167
163
|
# message, but Plain will not stop you from e.g. running server.
|
168
164
|
SILENCED_PREFLIGHT_CHECKS = []
|
169
165
|
|
170
|
-
#######################
|
171
|
-
# SECURITY MIDDLEWARE #
|
172
|
-
#######################
|
173
|
-
SECURE_CONTENT_TYPE_NOSNIFF = True
|
174
|
-
SECURE_CROSS_ORIGIN_OPENER_POLICY = "same-origin"
|
175
|
-
SECURE_HSTS_INCLUDE_SUBDOMAINS = False
|
176
|
-
SECURE_HSTS_PRELOAD = False
|
177
|
-
SECURE_HSTS_SECONDS = 0
|
178
|
-
SECURE_REDIRECT_EXEMPT = []
|
179
|
-
SECURE_REFERRER_POLICY = "same-origin"
|
180
|
-
SECURE_SSL_HOST = None
|
181
|
-
SECURE_SSL_REDIRECT = False
|
182
|
-
|
183
166
|
#############
|
184
167
|
# Templates #
|
185
168
|
#############
|