BmorricalDjangoWorkflows 2.0.2__tar.gz

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.
@@ -0,0 +1,268 @@
1
+ Metadata-Version: 2.4
2
+ Name: BmorricalDjangoWorkflows
3
+ Version: 2.0.2
4
+ Summary: Reusable Django Workflows
5
+ Home-page: https://github.com/Bmorrical/django-workflows
6
+ Author: Bradley Morrical
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Framework :: Django
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: Django>=4.0
13
+ Requires-Dist: djangorestframework>=3.14
14
+ Requires-Dist: requests>=2.31.0
15
+ Dynamic: author
16
+ Dynamic: classifier
17
+ Dynamic: description
18
+ Dynamic: description-content-type
19
+ Dynamic: home-page
20
+ Dynamic: license-file
21
+ Dynamic: requires-dist
22
+ Dynamic: requires-python
23
+ Dynamic: summary
24
+
25
+ # django-workflows
26
+
27
+ Reusable Django service helpers for common account flows:
28
+
29
+ - Registration and verification-code email flow
30
+ - Forgot-password code flow
31
+ - Reset-code validation and lockout handling
32
+ - Mailgun email utility with recipient validation
33
+
34
+ ## Installation
35
+
36
+ Install from PyPI:
37
+
38
+ ```bash
39
+ pip install BmorricalDjangoWorkflows==1.2.3
40
+ ```
41
+
42
+ In `requirements.txt`, pin it directly:
43
+
44
+ ```txt
45
+ BmorricalDjangoWorkflows==1.2.3
46
+ ```
47
+
48
+ Note: distribution name is `BmorricalDjangoWorkflows`, while imports remain under `django_workflows`.
49
+
50
+ ## Host Project Requirements
51
+
52
+ This package expects the host Django project to provide:
53
+
54
+ - A Django user model available through `django.contrib.auth.get_user_model()`
55
+ - A user meta model referenced by `WORKFLOWS["USER_META_MODEL"]`
56
+ - A user manager `create_user(...)` method that accepts `username`, because this package explicitly sets `username=email`
57
+
58
+ The user meta model should include at least:
59
+
60
+ - `user` relation
61
+ - `verify_code` field
62
+ - `verify_time` field
63
+ - `attempts` field
64
+
65
+ Optional (used if present):
66
+
67
+ - `force_password_reset`
68
+
69
+ ## Django Settings
70
+
71
+ Add a `WORKFLOWS` dict in your Django settings.
72
+
73
+ ```python
74
+ WORKFLOWS = {
75
+ # Required in most projects unless your model path matches the default.
76
+ "USER_META_MODEL": "users.models_user_meta.UserMeta",
77
+
78
+ # Optional settings with defaults shown.
79
+ "COMPANY_NAME": "My Company",
80
+ "ENABLE_MAILGUN": False,
81
+ "RESET_CODE_TTL_MINUTES": 10,
82
+ "MAX_VERIFY_ATTEMPTS": 3,
83
+ }
84
+ ```
85
+
86
+ Notes:
87
+
88
+ - `USER_META_MODEL` must be a dotted import path such as `myapp.models.UserMeta`.
89
+ - If `ENABLE_MAILGUN` is true, configure the Mailgun environment variables used by the mail service.
90
+
91
+ ## Mailgun Environment Variables
92
+
93
+ When mail sending is enabled, set:
94
+
95
+ - `MAILGUN_COMPANY_NAME`
96
+ - `MAILGUN_API_KEY`
97
+ - `MAILGUN_DOMAIN`
98
+ - `ENABLE_MAILGUN=true`
99
+
100
+ Optional:
101
+
102
+ - `MAILGUN_BCC_RECIPIENTS` as a comma-separated list
103
+
104
+ Example:
105
+
106
+ ```bash
107
+ MAILGUN_BCC_RECIPIENTS="audit@example.com,ops@example.com"
108
+ ```
109
+
110
+ If `MAILGUN_BCC_RECIPIENTS` is not set, no static BCC recipients are added.
111
+
112
+ ## Example Usage
113
+
114
+ ```python
115
+ from django_workflows.users.services.auth_flow import (
116
+ register_user_and_send_verification_email,
117
+ send_forgot_password_code,
118
+ verify_reset_code,
119
+ change_password,
120
+ )
121
+
122
+ result = register_user_and_send_verification_email(
123
+ email="person@example.com",
124
+ first_name="First",
125
+ last_name="Last",
126
+ password="example-password",
127
+ )
128
+
129
+ forgot = send_forgot_password_code("person@example.com")
130
+
131
+ verify = verify_reset_code(email="person@example.com", code="AB12CD")
132
+
133
+ changed = change_password(
134
+ email="person@example.com",
135
+ password="new-password",
136
+ password_verify="new-password",
137
+ )
138
+ ```
139
+
140
+ ### Direct Mailgun Usage
141
+
142
+ Attachment tuple shape:
143
+
144
+ - `(filename, file_bytes_or_file_object, mimetype)`
145
+
146
+ Example attachment entry:
147
+
148
+ - `("report.pdf", pdf_bytes, "application/pdf")`
149
+
150
+ ```python
151
+ from django_workflows.services.mailgun import send_mailgun_email
152
+
153
+ response = send_mailgun_email(
154
+ to=["primary@example.com", "secondary@example.com"],
155
+ subject="Welcome",
156
+ html="<p>Thanks for joining.</p>",
157
+ cc="manager@example.com",
158
+ bcc=["audit@example.com"],
159
+ attachments=[("report.pdf", pdf_bytes, "application/pdf")],
160
+ )
161
+
162
+ # Optional: explicit runtime override for enablement
163
+ send_mailgun_email(
164
+ to="user@example.com",
165
+ subject="Dry run",
166
+ html="<p>This will not send.</p>",
167
+ enabled=False,
168
+ )
169
+ ```
170
+
171
+ ## Local Development
172
+
173
+ Run tests:
174
+
175
+ ```bash
176
+ make test
177
+ ```
178
+
179
+ Run tests with coverage:
180
+
181
+ ```bash
182
+ make test-coverage
183
+ ```
184
+
185
+ CI runs tests on push and pull requests using [`.github/workflows/tests.yml`](.github/workflows/tests.yml).
186
+
187
+ ## Troubleshooting
188
+
189
+ ### ImproperlyConfigured for USER_META_MODEL
190
+
191
+ Error example:
192
+
193
+ ```text
194
+ WORKFLOWS['USER_META_MODEL'] must be a dotted path like 'myapp.models.UserMeta'.
195
+ ```
196
+
197
+ Fix:
198
+
199
+ - Set `WORKFLOWS["USER_META_MODEL"]` to a valid dotted import path.
200
+ - Verify the target model is importable by Django at runtime.
201
+
202
+ ### UserMeta field errors
203
+
204
+ If you see attribute errors around verification state, confirm your user meta model provides:
205
+
206
+ - `verify_code`
207
+ - `verify_time`
208
+ - `attempts`
209
+
210
+ ### Mailgun not sending
211
+
212
+ Check:
213
+
214
+ - `ENABLE_MAILGUN=true`
215
+ - `MAILGUN_API_KEY`
216
+ - `MAILGUN_DOMAIN`
217
+ - `MAILGUN_COMPANY_NAME`
218
+
219
+ ### No static BCC recipients applied
220
+
221
+ This is expected unless you set `MAILGUN_BCC_RECIPIENTS`.
222
+
223
+ ## Release
224
+
225
+ Create a release tag:
226
+
227
+ ```bash
228
+ ./release.sh 0.1.0
229
+ ```
230
+
231
+ After release, update the package version in your consuming application's dependency files.
232
+
233
+ Tag pushes like `v1.2.3` trigger [`.github/workflows/publish.yml`](.github/workflows/publish.yml), which publishes to PyPI.
234
+
235
+ ## Publishing To PyPI (Maintainer Steps)
236
+
237
+ 1. Check whether the target package name is available.
238
+
239
+ ```bash
240
+ curl -I https://pypi.org/pypi/BmorricalDjangoWorkflows/json
241
+ ```
242
+
243
+ If this returns 404, the name is usually available.
244
+
245
+ 2. Create a PyPI account: https://pypi.org/account/register/
246
+
247
+ 3. Create a PyPI API token: PyPI Account -> Account settings -> API tokens.
248
+
249
+ 4. Add repository secret in GitHub:
250
+
251
+ - Name: `PYPI_API_TOKEN`
252
+ - Value: your PyPI token (starts with `pypi-`)
253
+
254
+ 5. Bump and tag a release:
255
+
256
+ ```bash
257
+ ./release.sh 1.2.3
258
+ ```
259
+
260
+ 6. Confirm the workflow run succeeded and the package appears on PyPI.
261
+
262
+ 7. Update consuming applications:
263
+
264
+ ```txt
265
+ BmorricalDjangoWorkflows==1.2.3
266
+ ```
267
+
268
+ If upload fails because the name is already taken, change `name=` in [setup.py](setup.py), bump version, and release again.
@@ -0,0 +1,19 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ VERSION
5
+ setup.py
6
+ BmorricalDjangoWorkflows.egg-info/PKG-INFO
7
+ BmorricalDjangoWorkflows.egg-info/SOURCES.txt
8
+ BmorricalDjangoWorkflows.egg-info/dependency_links.txt
9
+ BmorricalDjangoWorkflows.egg-info/requires.txt
10
+ BmorricalDjangoWorkflows.egg-info/top_level.txt
11
+ django_workflows/__init__.py
12
+ django_workflows/services/__init__.py
13
+ django_workflows/services/mailgun.py
14
+ django_workflows/users/__init__.py
15
+ django_workflows/users/services/__init__.py
16
+ django_workflows/users/services/auth_flow.py
17
+ tests/__init__.py
18
+ tests/test_auth_flow.py
19
+ tests/test_mailgun.py
@@ -0,0 +1,3 @@
1
+ Django>=4.0
2
+ djangorestframework>=3.14
3
+ requests>=2.31.0
@@ -0,0 +1,2 @@
1
+ django_workflows
2
+ tests
@@ -0,0 +1,3 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Brad Morrical
@@ -0,0 +1,3 @@
1
+ include VERSION
2
+ include README.md
3
+ include LICENSE
@@ -0,0 +1,268 @@
1
+ Metadata-Version: 2.4
2
+ Name: BmorricalDjangoWorkflows
3
+ Version: 2.0.2
4
+ Summary: Reusable Django Workflows
5
+ Home-page: https://github.com/Bmorrical/django-workflows
6
+ Author: Bradley Morrical
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Framework :: Django
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: Django>=4.0
13
+ Requires-Dist: djangorestframework>=3.14
14
+ Requires-Dist: requests>=2.31.0
15
+ Dynamic: author
16
+ Dynamic: classifier
17
+ Dynamic: description
18
+ Dynamic: description-content-type
19
+ Dynamic: home-page
20
+ Dynamic: license-file
21
+ Dynamic: requires-dist
22
+ Dynamic: requires-python
23
+ Dynamic: summary
24
+
25
+ # django-workflows
26
+
27
+ Reusable Django service helpers for common account flows:
28
+
29
+ - Registration and verification-code email flow
30
+ - Forgot-password code flow
31
+ - Reset-code validation and lockout handling
32
+ - Mailgun email utility with recipient validation
33
+
34
+ ## Installation
35
+
36
+ Install from PyPI:
37
+
38
+ ```bash
39
+ pip install BmorricalDjangoWorkflows==1.2.3
40
+ ```
41
+
42
+ In `requirements.txt`, pin it directly:
43
+
44
+ ```txt
45
+ BmorricalDjangoWorkflows==1.2.3
46
+ ```
47
+
48
+ Note: distribution name is `BmorricalDjangoWorkflows`, while imports remain under `django_workflows`.
49
+
50
+ ## Host Project Requirements
51
+
52
+ This package expects the host Django project to provide:
53
+
54
+ - A Django user model available through `django.contrib.auth.get_user_model()`
55
+ - A user meta model referenced by `WORKFLOWS["USER_META_MODEL"]`
56
+ - A user manager `create_user(...)` method that accepts `username`, because this package explicitly sets `username=email`
57
+
58
+ The user meta model should include at least:
59
+
60
+ - `user` relation
61
+ - `verify_code` field
62
+ - `verify_time` field
63
+ - `attempts` field
64
+
65
+ Optional (used if present):
66
+
67
+ - `force_password_reset`
68
+
69
+ ## Django Settings
70
+
71
+ Add a `WORKFLOWS` dict in your Django settings.
72
+
73
+ ```python
74
+ WORKFLOWS = {
75
+ # Required in most projects unless your model path matches the default.
76
+ "USER_META_MODEL": "users.models_user_meta.UserMeta",
77
+
78
+ # Optional settings with defaults shown.
79
+ "COMPANY_NAME": "My Company",
80
+ "ENABLE_MAILGUN": False,
81
+ "RESET_CODE_TTL_MINUTES": 10,
82
+ "MAX_VERIFY_ATTEMPTS": 3,
83
+ }
84
+ ```
85
+
86
+ Notes:
87
+
88
+ - `USER_META_MODEL` must be a dotted import path such as `myapp.models.UserMeta`.
89
+ - If `ENABLE_MAILGUN` is true, configure the Mailgun environment variables used by the mail service.
90
+
91
+ ## Mailgun Environment Variables
92
+
93
+ When mail sending is enabled, set:
94
+
95
+ - `MAILGUN_COMPANY_NAME`
96
+ - `MAILGUN_API_KEY`
97
+ - `MAILGUN_DOMAIN`
98
+ - `ENABLE_MAILGUN=true`
99
+
100
+ Optional:
101
+
102
+ - `MAILGUN_BCC_RECIPIENTS` as a comma-separated list
103
+
104
+ Example:
105
+
106
+ ```bash
107
+ MAILGUN_BCC_RECIPIENTS="audit@example.com,ops@example.com"
108
+ ```
109
+
110
+ If `MAILGUN_BCC_RECIPIENTS` is not set, no static BCC recipients are added.
111
+
112
+ ## Example Usage
113
+
114
+ ```python
115
+ from django_workflows.users.services.auth_flow import (
116
+ register_user_and_send_verification_email,
117
+ send_forgot_password_code,
118
+ verify_reset_code,
119
+ change_password,
120
+ )
121
+
122
+ result = register_user_and_send_verification_email(
123
+ email="person@example.com",
124
+ first_name="First",
125
+ last_name="Last",
126
+ password="example-password",
127
+ )
128
+
129
+ forgot = send_forgot_password_code("person@example.com")
130
+
131
+ verify = verify_reset_code(email="person@example.com", code="AB12CD")
132
+
133
+ changed = change_password(
134
+ email="person@example.com",
135
+ password="new-password",
136
+ password_verify="new-password",
137
+ )
138
+ ```
139
+
140
+ ### Direct Mailgun Usage
141
+
142
+ Attachment tuple shape:
143
+
144
+ - `(filename, file_bytes_or_file_object, mimetype)`
145
+
146
+ Example attachment entry:
147
+
148
+ - `("report.pdf", pdf_bytes, "application/pdf")`
149
+
150
+ ```python
151
+ from django_workflows.services.mailgun import send_mailgun_email
152
+
153
+ response = send_mailgun_email(
154
+ to=["primary@example.com", "secondary@example.com"],
155
+ subject="Welcome",
156
+ html="<p>Thanks for joining.</p>",
157
+ cc="manager@example.com",
158
+ bcc=["audit@example.com"],
159
+ attachments=[("report.pdf", pdf_bytes, "application/pdf")],
160
+ )
161
+
162
+ # Optional: explicit runtime override for enablement
163
+ send_mailgun_email(
164
+ to="user@example.com",
165
+ subject="Dry run",
166
+ html="<p>This will not send.</p>",
167
+ enabled=False,
168
+ )
169
+ ```
170
+
171
+ ## Local Development
172
+
173
+ Run tests:
174
+
175
+ ```bash
176
+ make test
177
+ ```
178
+
179
+ Run tests with coverage:
180
+
181
+ ```bash
182
+ make test-coverage
183
+ ```
184
+
185
+ CI runs tests on push and pull requests using [`.github/workflows/tests.yml`](.github/workflows/tests.yml).
186
+
187
+ ## Troubleshooting
188
+
189
+ ### ImproperlyConfigured for USER_META_MODEL
190
+
191
+ Error example:
192
+
193
+ ```text
194
+ WORKFLOWS['USER_META_MODEL'] must be a dotted path like 'myapp.models.UserMeta'.
195
+ ```
196
+
197
+ Fix:
198
+
199
+ - Set `WORKFLOWS["USER_META_MODEL"]` to a valid dotted import path.
200
+ - Verify the target model is importable by Django at runtime.
201
+
202
+ ### UserMeta field errors
203
+
204
+ If you see attribute errors around verification state, confirm your user meta model provides:
205
+
206
+ - `verify_code`
207
+ - `verify_time`
208
+ - `attempts`
209
+
210
+ ### Mailgun not sending
211
+
212
+ Check:
213
+
214
+ - `ENABLE_MAILGUN=true`
215
+ - `MAILGUN_API_KEY`
216
+ - `MAILGUN_DOMAIN`
217
+ - `MAILGUN_COMPANY_NAME`
218
+
219
+ ### No static BCC recipients applied
220
+
221
+ This is expected unless you set `MAILGUN_BCC_RECIPIENTS`.
222
+
223
+ ## Release
224
+
225
+ Create a release tag:
226
+
227
+ ```bash
228
+ ./release.sh 0.1.0
229
+ ```
230
+
231
+ After release, update the package version in your consuming application's dependency files.
232
+
233
+ Tag pushes like `v1.2.3` trigger [`.github/workflows/publish.yml`](.github/workflows/publish.yml), which publishes to PyPI.
234
+
235
+ ## Publishing To PyPI (Maintainer Steps)
236
+
237
+ 1. Check whether the target package name is available.
238
+
239
+ ```bash
240
+ curl -I https://pypi.org/pypi/BmorricalDjangoWorkflows/json
241
+ ```
242
+
243
+ If this returns 404, the name is usually available.
244
+
245
+ 2. Create a PyPI account: https://pypi.org/account/register/
246
+
247
+ 3. Create a PyPI API token: PyPI Account -> Account settings -> API tokens.
248
+
249
+ 4. Add repository secret in GitHub:
250
+
251
+ - Name: `PYPI_API_TOKEN`
252
+ - Value: your PyPI token (starts with `pypi-`)
253
+
254
+ 5. Bump and tag a release:
255
+
256
+ ```bash
257
+ ./release.sh 1.2.3
258
+ ```
259
+
260
+ 6. Confirm the workflow run succeeded and the package appears on PyPI.
261
+
262
+ 7. Update consuming applications:
263
+
264
+ ```txt
265
+ BmorricalDjangoWorkflows==1.2.3
266
+ ```
267
+
268
+ If upload fails because the name is already taken, change `name=` in [setup.py](setup.py), bump version, and release again.