plain.oauth 0.24.1__tar.gz → 0.24.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.
Files changed (40) hide show
  1. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/PKG-INFO +56 -24
  2. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/CHANGELOG.md +12 -0
  3. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/README.md +54 -22
  4. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/models.py +2 -2
  5. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/pyproject.toml +2 -2
  6. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/.gitignore +0 -0
  7. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/LICENSE +0 -0
  8. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/README.md +0 -0
  9. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/__init__.py +0 -0
  10. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/admin.py +0 -0
  11. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/config.py +0 -0
  12. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/default_settings.py +0 -0
  13. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/exceptions.py +0 -0
  14. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/migrations/0001_initial.py +0 -0
  15. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/migrations/__init__.py +0 -0
  16. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/providers.py +0 -0
  17. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/templates/oauth/callback.html +0 -0
  18. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/urls.py +0 -0
  19. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/plain/oauth/views.py +0 -0
  20. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/provider_examples/__init__.py +0 -0
  21. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/provider_examples/bitbucket.py +0 -0
  22. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/provider_examples/github.py +0 -0
  23. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/provider_examples/gitlab.py +0 -0
  24. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/settings.py +0 -0
  25. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/templates/base.html +0 -0
  26. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/templates/index.html +0 -0
  27. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/templates/login.html +0 -0
  28. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/urls.py +0 -0
  29. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/users/migrations/0001_initial.py +0 -0
  30. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/users/migrations/__init__.py +0 -0
  31. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/app/users/models.py +0 -0
  32. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/provider_tests/__init__.py +0 -0
  33. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/provider_tests/test_github.py +0 -0
  34. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/providers/__init__.py +0 -0
  35. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/providers/bitbucket.py +0 -0
  36. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/providers/github.py +0 -0
  37. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/providers/gitlab.py +0 -0
  38. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/test_backends.py +0 -0
  39. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/test_checks.py +0 -0
  40. {plain_oauth-0.24.1 → plain_oauth-0.24.2}/tests/test_providers.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.oauth
3
- Version: 0.24.1
4
- Summary: OAuth login and API access for Plain.
3
+ Version: 0.24.2
4
+ Summary: Let users log in with OAuth providers.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-Expression: BSD-3-Clause
7
7
  License-File: LICENSE
@@ -14,7 +14,19 @@ Description-Content-Type: text/markdown
14
14
 
15
15
  # plain.oauth
16
16
 
17
- Let users log in with OAuth providers.
17
+ **Let users log in with OAuth providers.**
18
+
19
+ - [Overview](#overview)
20
+ - [Usage](#usage)
21
+ - [Basic setup example](#basic-setup-example)
22
+ - [Handling OAuth errors](#handling-oauth-errors)
23
+ - [Connecting and disconnecting OAuth accounts](#connecting-and-disconnecting-oauth-accounts)
24
+ - [Using a saved access token](#using-a-saved-access-token)
25
+ - [Using the Django system check](#using-the-django-system-check)
26
+ - [FAQs](#faqs)
27
+ - [Installation](#installation)
28
+
29
+ ## Overview
18
30
 
19
31
  [Watch on YouTube (3 mins) →](https://www.youtube.com/watch?v=UxbxBa6AFsU)
20
32
 
@@ -31,11 +43,9 @@ There are three OAuth flows that it makes possible:
31
43
 
32
44
  ## Usage
33
45
 
34
- Install the package from PyPi:
46
+ ### Basic setup example
35
47
 
36
- ```sh
37
- pip install plain-oauth
38
- ```
48
+ Here's a complete example showing how to set up OAuth login with GitHub:
39
49
 
40
50
  Add `plain.oauth` to your `INSTALLED_PACKAGES` in `settings.py`:
41
51
 
@@ -46,19 +56,24 @@ INSTALLED_PACKAGES = [
46
56
  ]
47
57
  ```
48
58
 
49
- In your `urls.py`, include `plain.oauth.urls`:
59
+ In your `urls.py`, include the [`OAuthRouter`](./urls.py#OAuthRouter):
50
60
 
51
61
  ```python
52
- urlpatterns = [
53
- path("oauth/", include("plain.oauth.urls")),
54
- ...
55
- ]
62
+ from plain.oauth.urls import OAuthRouter
63
+ from plain.urls import Router, include
64
+
65
+ class AppRouter(Router):
66
+ namespace = ""
67
+ urls = [
68
+ include("oauth/", OAuthRouter),
69
+ # ...
70
+ ]
56
71
  ```
57
72
 
58
73
  Then run migrations:
59
74
 
60
75
  ```sh
61
- python manage.py migrate plain.oauth
76
+ plain migrate plain.oauth
62
77
  ```
63
78
 
64
79
  Create a new OAuth provider ([or copy one from our examples](https://github.com/forgepackages/plain-oauth/tree/master/provider_examples)):
@@ -70,12 +85,12 @@ import requests
70
85
  from plain.oauth.providers import OAuthProvider, OAuthToken, OAuthUser
71
86
 
72
87
 
73
- class ExampleOAuthProvider(OAuthProvider):
74
- authorization_url = "https://example.com/login/oauth/authorize"
88
+ class GitHubOAuthProvider(OAuthProvider):
89
+ authorization_url = "https://github.com/login/oauth/authorize"
75
90
 
76
91
  def get_oauth_token(self, *, code, request):
77
92
  response = requests.post(
78
- "https://example.com/login/oauth/token",
93
+ "https://github.com/login/oauth/access_token",
79
94
  headers={
80
95
  "Accept": "application/json",
81
96
  },
@@ -93,7 +108,7 @@ class ExampleOAuthProvider(OAuthProvider):
93
108
 
94
109
  def get_oauth_user(self, *, oauth_token):
95
110
  response = requests.get(
96
- "https://example.com/api/user",
111
+ "https://api.github.com/user",
97
112
  headers={
98
113
  "Accept": "application/json",
99
114
  "Authorization": f"token {oauth_token.access_token}",
@@ -150,8 +165,6 @@ your OAuth callback will be something like `https://example.com/oauth/{provider}
150
165
 
151
166
  That's pretty much it!
152
167
 
153
- ## Advanced usage
154
-
155
168
  ### Handling OAuth errors
156
169
 
157
170
  The most common error you'll run into is if an existing user clicks a login button,
@@ -216,7 +229,7 @@ Hello {{ request.user }}!
216
229
  {% endblock %}
217
230
  ```
218
231
 
219
- The `get_provider_keys` function can help populate the list of options:
232
+ The [`get_provider_keys`](./providers.py#get_provider_keys) function can help populate the list of options:
220
233
 
221
234
  ```python
222
235
  from plain.oauth.providers import get_provider_keys
@@ -255,12 +268,12 @@ This library comes with a Django system check to ensure you don't _remove_ a pro
255
268
  You do need to specify the `--database` for this to run when using the check command by itself:
256
269
 
257
270
  ```sh
258
- python manage.py check --database default
271
+ plain check --database default
259
272
  ```
260
273
 
261
274
  ## FAQs
262
275
 
263
- ### How is this different from [Django OAuth libraries](https://djangopackages.org/grids/g/oauth/)?
276
+ #### How is this different from [Django OAuth libraries](https://djangopackages.org/grids/g/oauth/)?
264
277
 
265
278
  The short answer is that _it does less_.
266
279
 
@@ -279,7 +292,7 @@ and the implications for doing it one way or another.
279
292
  The other popular OAuth libraries have similar issues,
280
293
  and I think their _weight_ outweighs their usefulness for 80% of the use cases.
281
294
 
282
- ### Why aren't providers included in the library itself?
295
+ #### Why aren't providers included in the library itself?
283
296
 
284
297
  One thing you'll notice is that we don't have a long list of pre-configured providers in this library.
285
298
  Instead, we have some examples (which you can usually just copy, paste, and use) and otherwise encourage you to wire up the provider yourself.
@@ -302,7 +315,7 @@ You don't need to try to run changes through us or wait for an upstream update.
302
315
  You're welcome to contribute an example to this repo,
303
316
  and there won't be an expectation that it "works perfectly for every use case until the end of time".
304
317
 
305
- ### Redirect/callback URL mismatch in local development?
318
+ #### Redirect/callback URL mismatch in local development?
306
319
 
307
320
  If you're doing local development through a proxy/tunnel like [ngrok](https://ngrok.com/),
308
321
  then the callback URL might be automatically built as `http` instead of `https`.
@@ -312,3 +325,22 @@ This is the Django setting you're probably looking for:
312
325
  ```python
313
326
  HTTPS_PROXY_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
314
327
  ```
328
+
329
+ ## Installation
330
+
331
+ Install the `plain.oauth` package from [PyPI](https://pypi.org/project/plain.oauth/):
332
+
333
+ ```bash
334
+ uv add plain.oauth
335
+ ```
336
+
337
+ After installation, follow the basic setup example in the [Usage](#usage) section above to:
338
+
339
+ 1. Add `plain.oauth` to your `INSTALLED_PACKAGES`
340
+ 2. Include the OAuth router in your URLs
341
+ 3. Run migrations
342
+ 4. Create an OAuth provider class
343
+ 5. Configure OAuth settings
344
+ 6. Add login buttons to your templates
345
+
346
+ For a complete working example, see the [Basic setup example](#basic-setup-example) which shows how to set up GitHub OAuth login.
@@ -1,5 +1,17 @@
1
1
  # plain-oauth changelog
2
2
 
3
+ ## [0.24.2](https://github.com/dropseed/plain/releases/plain-oauth@0.24.2) (2025-08-05)
4
+
5
+ ### What's changed
6
+
7
+ - Updated documentation to use `plain` commands instead of `python manage.py` references ([8071854](https://github.com/dropseed/plain/commit/8071854d61))
8
+ - Improved README with better structure, table of contents, and more comprehensive examples ([4ebecd1](https://github.com/dropseed/plain/commit/4ebecd1856))
9
+ - Fixed router setup documentation in URLs section ([48caf10](https://github.com/dropseed/plain/commit/48caf105da))
10
+
11
+ ### Upgrade instructions
12
+
13
+ - No changes required
14
+
3
15
  ## [0.24.1](https://github.com/dropseed/plain/releases/plain-oauth@0.24.1) (2025-07-23)
4
16
 
5
17
  ### What's changed
@@ -1,6 +1,18 @@
1
1
  # plain.oauth
2
2
 
3
- Let users log in with OAuth providers.
3
+ **Let users log in with OAuth providers.**
4
+
5
+ - [Overview](#overview)
6
+ - [Usage](#usage)
7
+ - [Basic setup example](#basic-setup-example)
8
+ - [Handling OAuth errors](#handling-oauth-errors)
9
+ - [Connecting and disconnecting OAuth accounts](#connecting-and-disconnecting-oauth-accounts)
10
+ - [Using a saved access token](#using-a-saved-access-token)
11
+ - [Using the Django system check](#using-the-django-system-check)
12
+ - [FAQs](#faqs)
13
+ - [Installation](#installation)
14
+
15
+ ## Overview
4
16
 
5
17
  [Watch on YouTube (3 mins) →](https://www.youtube.com/watch?v=UxbxBa6AFsU)
6
18
 
@@ -17,11 +29,9 @@ There are three OAuth flows that it makes possible:
17
29
 
18
30
  ## Usage
19
31
 
20
- Install the package from PyPi:
32
+ ### Basic setup example
21
33
 
22
- ```sh
23
- pip install plain-oauth
24
- ```
34
+ Here's a complete example showing how to set up OAuth login with GitHub:
25
35
 
26
36
  Add `plain.oauth` to your `INSTALLED_PACKAGES` in `settings.py`:
27
37
 
@@ -32,19 +42,24 @@ INSTALLED_PACKAGES = [
32
42
  ]
33
43
  ```
34
44
 
35
- In your `urls.py`, include `plain.oauth.urls`:
45
+ In your `urls.py`, include the [`OAuthRouter`](./urls.py#OAuthRouter):
36
46
 
37
47
  ```python
38
- urlpatterns = [
39
- path("oauth/", include("plain.oauth.urls")),
40
- ...
41
- ]
48
+ from plain.oauth.urls import OAuthRouter
49
+ from plain.urls import Router, include
50
+
51
+ class AppRouter(Router):
52
+ namespace = ""
53
+ urls = [
54
+ include("oauth/", OAuthRouter),
55
+ # ...
56
+ ]
42
57
  ```
43
58
 
44
59
  Then run migrations:
45
60
 
46
61
  ```sh
47
- python manage.py migrate plain.oauth
62
+ plain migrate plain.oauth
48
63
  ```
49
64
 
50
65
  Create a new OAuth provider ([or copy one from our examples](https://github.com/forgepackages/plain-oauth/tree/master/provider_examples)):
@@ -56,12 +71,12 @@ import requests
56
71
  from plain.oauth.providers import OAuthProvider, OAuthToken, OAuthUser
57
72
 
58
73
 
59
- class ExampleOAuthProvider(OAuthProvider):
60
- authorization_url = "https://example.com/login/oauth/authorize"
74
+ class GitHubOAuthProvider(OAuthProvider):
75
+ authorization_url = "https://github.com/login/oauth/authorize"
61
76
 
62
77
  def get_oauth_token(self, *, code, request):
63
78
  response = requests.post(
64
- "https://example.com/login/oauth/token",
79
+ "https://github.com/login/oauth/access_token",
65
80
  headers={
66
81
  "Accept": "application/json",
67
82
  },
@@ -79,7 +94,7 @@ class ExampleOAuthProvider(OAuthProvider):
79
94
 
80
95
  def get_oauth_user(self, *, oauth_token):
81
96
  response = requests.get(
82
- "https://example.com/api/user",
97
+ "https://api.github.com/user",
83
98
  headers={
84
99
  "Accept": "application/json",
85
100
  "Authorization": f"token {oauth_token.access_token}",
@@ -136,8 +151,6 @@ your OAuth callback will be something like `https://example.com/oauth/{provider}
136
151
 
137
152
  That's pretty much it!
138
153
 
139
- ## Advanced usage
140
-
141
154
  ### Handling OAuth errors
142
155
 
143
156
  The most common error you'll run into is if an existing user clicks a login button,
@@ -202,7 +215,7 @@ Hello {{ request.user }}!
202
215
  {% endblock %}
203
216
  ```
204
217
 
205
- The `get_provider_keys` function can help populate the list of options:
218
+ The [`get_provider_keys`](./providers.py#get_provider_keys) function can help populate the list of options:
206
219
 
207
220
  ```python
208
221
  from plain.oauth.providers import get_provider_keys
@@ -241,12 +254,12 @@ This library comes with a Django system check to ensure you don't _remove_ a pro
241
254
  You do need to specify the `--database` for this to run when using the check command by itself:
242
255
 
243
256
  ```sh
244
- python manage.py check --database default
257
+ plain check --database default
245
258
  ```
246
259
 
247
260
  ## FAQs
248
261
 
249
- ### How is this different from [Django OAuth libraries](https://djangopackages.org/grids/g/oauth/)?
262
+ #### How is this different from [Django OAuth libraries](https://djangopackages.org/grids/g/oauth/)?
250
263
 
251
264
  The short answer is that _it does less_.
252
265
 
@@ -265,7 +278,7 @@ and the implications for doing it one way or another.
265
278
  The other popular OAuth libraries have similar issues,
266
279
  and I think their _weight_ outweighs their usefulness for 80% of the use cases.
267
280
 
268
- ### Why aren't providers included in the library itself?
281
+ #### Why aren't providers included in the library itself?
269
282
 
270
283
  One thing you'll notice is that we don't have a long list of pre-configured providers in this library.
271
284
  Instead, we have some examples (which you can usually just copy, paste, and use) and otherwise encourage you to wire up the provider yourself.
@@ -288,7 +301,7 @@ You don't need to try to run changes through us or wait for an upstream update.
288
301
  You're welcome to contribute an example to this repo,
289
302
  and there won't be an expectation that it "works perfectly for every use case until the end of time".
290
303
 
291
- ### Redirect/callback URL mismatch in local development?
304
+ #### Redirect/callback URL mismatch in local development?
292
305
 
293
306
  If you're doing local development through a proxy/tunnel like [ngrok](https://ngrok.com/),
294
307
  then the callback URL might be automatically built as `http` instead of `https`.
@@ -298,3 +311,22 @@ This is the Django setting you're probably looking for:
298
311
  ```python
299
312
  HTTPS_PROXY_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
300
313
  ```
314
+
315
+ ## Installation
316
+
317
+ Install the `plain.oauth` package from [PyPI](https://pypi.org/project/plain.oauth/):
318
+
319
+ ```bash
320
+ uv add plain.oauth
321
+ ```
322
+
323
+ After installation, follow the basic setup example in the [Usage](#usage) section above to:
324
+
325
+ 1. Add `plain.oauth` to your `INSTALLED_PACKAGES`
326
+ 2. Include the OAuth router in your URLs
327
+ 3. Run migrations
328
+ 4. Create an OAuth provider class
329
+ 5. Configure OAuth settings
330
+ 6. Add login buttons to your templates
331
+
332
+ For a complete working example, see the [Basic setup example](#basic-setup-example) which shows how to set up GitHub OAuth login.
@@ -160,7 +160,7 @@ class OAuthConnection(models.Model):
160
160
  A system check for ensuring that provider_keys in the database are also present in settings.
161
161
 
162
162
  Note that the --database flag is required for this to work:
163
- python manage.py check --database default
163
+ plain check --database default
164
164
  """
165
165
  errors = super().check(**kwargs)
166
166
 
@@ -175,7 +175,7 @@ class OAuthConnection(models.Model):
175
175
  cls.objects.values_list("provider_key", flat=True).distinct()
176
176
  )
177
177
  except (OperationalError, ProgrammingError):
178
- # Check runs on manage.py migrate, and the table may not exist yet
178
+ # Check runs on plain migrate, and the table may not exist yet
179
179
  # or it may not be installed on the particular database intentionally
180
180
  return errors
181
181
 
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "plain.oauth"
3
- version = "0.24.1"
4
- description = "OAuth login and API access for Plain."
3
+ version = "0.24.2"
4
+ description = "Let users log in with OAuth providers."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  license = "BSD-3-Clause"
7
7
  readme = "README.md"
File without changes
File without changes
File without changes