plain.oauth 0.20.0__py3-none-any.whl → 0.22.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.
@@ -0,0 +1,11 @@
1
+ # plain-oauth changelog
2
+
3
+ ## [0.22.0](https://github.com/dropseed/plain/releases/plain-oauth@0.22.0) (2025-06-23)
4
+
5
+ ### What's changed
6
+
7
+ - Updated `OAuthConnection.check()` to accept a single `database` argument instead of the older `databases` list, matching the new single `DATABASE` setting used across the Plain stack ([d346d81](https://github.com/dropseed/plain/commit/d346d81))
8
+
9
+ ### Upgrade instructions
10
+
11
+ - No changes required.
plain/oauth/README.md CHANGED
@@ -89,10 +89,12 @@ class ExampleOAuthProvider(OAuthProvider):
89
89
  data = response.json()
90
90
  return OAuthUser(
91
91
  # The provider ID is required
92
- id=data["id"],
93
- # And you can populate any of your User model fields with additional kwargs
94
- email=data["email"],
95
- username=data["username"],
92
+ provider_id=data["id"],
93
+ # Populate your User model fields using the user_model_fields dict
94
+ user_model_fields={
95
+ "email": data["email"],
96
+ "username": data["username"],
97
+ },
96
98
  )
97
99
  ```
98
100
 
plain/oauth/models.py CHANGED
@@ -76,7 +76,7 @@ class OAuthConnection(models.Model):
76
76
  self.refresh_token_expires_at = oauth_token.refresh_token_expires_at
77
77
 
78
78
  def set_user_fields(self, oauth_user: "OAuthUser"):
79
- self.provider_user_id = oauth_user.id
79
+ self.provider_user_id = oauth_user.provider_id
80
80
 
81
81
  def access_token_expired(self) -> bool:
82
82
  return (
@@ -97,7 +97,7 @@ class OAuthConnection(models.Model):
97
97
  try:
98
98
  connection = cls.objects.get(
99
99
  provider_key=provider_key,
100
- provider_user_id=oauth_user.id,
100
+ provider_user_id=oauth_user.provider_id,
101
101
  )
102
102
  connection.set_token_fields(oauth_token)
103
103
  connection.save()
@@ -137,7 +137,7 @@ class OAuthConnection(models.Model):
137
137
  connection = cls.objects.get(
138
138
  user=user,
139
139
  provider_key=provider_key,
140
- provider_user_id=oauth_user.id,
140
+ provider_user_id=oauth_user.provider_id,
141
141
  )
142
142
  except cls.DoesNotExist:
143
143
  # Create our own instance (not using get_or_create)
@@ -145,7 +145,7 @@ class OAuthConnection(models.Model):
145
145
  connection = cls(
146
146
  user=user,
147
147
  provider_key=provider_key,
148
- provider_user_id=oauth_user.id,
148
+ provider_user_id=oauth_user.provider_id,
149
149
  )
150
150
 
151
151
  connection.set_user_fields(oauth_user)
@@ -164,34 +164,31 @@ class OAuthConnection(models.Model):
164
164
  """
165
165
  errors = super().check(**kwargs)
166
166
 
167
- databases = kwargs.get("databases", None)
168
- if not databases:
167
+ database = kwargs.get("database", False)
168
+ if not database:
169
169
  return errors
170
170
 
171
171
  from .providers import get_provider_keys
172
172
 
173
- for database in databases:
174
- try:
175
- keys_in_db = set(
176
- cls.objects.using(database)
177
- .values_list("provider_key", flat=True)
178
- .distinct()
179
- )
180
- except (OperationalError, ProgrammingError):
181
- # Check runs on manage.py migrate, and the table may not exist yet
182
- # or it may not be installed on the particular database intentionally
183
- continue
184
-
185
- keys_in_settings = set(get_provider_keys())
186
-
187
- if keys_in_db - keys_in_settings:
188
- errors.append(
189
- Error(
190
- "The following OAuth providers are in the database but not in the settings: {}".format(
191
- ", ".join(keys_in_db - keys_in_settings)
192
- ),
193
- id="plain.oauth.E001",
194
- )
173
+ try:
174
+ keys_in_db = set(
175
+ cls.objects.values_list("provider_key", flat=True).distinct()
176
+ )
177
+ except (OperationalError, ProgrammingError):
178
+ # Check runs on manage.py migrate, and the table may not exist yet
179
+ # or it may not be installed on the particular database intentionally
180
+ return errors
181
+
182
+ keys_in_settings = set(get_provider_keys())
183
+
184
+ if keys_in_db - keys_in_settings:
185
+ errors.append(
186
+ Error(
187
+ "The following OAuth providers are in the database but not in the settings: {}".format(
188
+ ", ".join(keys_in_db - keys_in_settings)
189
+ ),
190
+ id="plain.oauth.E001",
195
191
  )
192
+ )
196
193
 
197
194
  return errors
plain/oauth/providers.py CHANGED
@@ -24,8 +24,8 @@ class OAuthToken:
24
24
  *,
25
25
  access_token: str,
26
26
  refresh_token: str = "",
27
- access_token_expires_at: datetime.datetime = None,
28
- refresh_token_expires_at: datetime.datetime = None,
27
+ access_token_expires_at: datetime.datetime | None = None,
28
+ refresh_token_expires_at: datetime.datetime | None = None,
29
29
  ):
30
30
  self.access_token = access_token
31
31
  self.refresh_token = refresh_token
@@ -34,16 +34,16 @@ class OAuthToken:
34
34
 
35
35
 
36
36
  class OAuthUser:
37
- def __init__(self, *, id: str, **user_model_fields: dict):
38
- self.id = id # ID on the provider's system
39
- self.user_model_fields = user_model_fields
37
+ def __init__(self, *, provider_id: str, user_model_fields: dict | None = None):
38
+ self.provider_id = provider_id # ID on the provider's system
39
+ self.user_model_fields = user_model_fields or {}
40
40
 
41
41
  def __str__(self):
42
42
  if "email" in self.user_model_fields:
43
43
  return self.user_model_fields["email"]
44
44
  if "username" in self.user_model_fields:
45
45
  return self.user_model_fields["username"]
46
- return str(self.id)
46
+ return str(self.provider_id)
47
47
 
48
48
 
49
49
  class OAuthProvider:
@@ -181,7 +181,7 @@ class OAuthProvider:
181
181
  redirect_url = self.get_login_redirect_url(request=request)
182
182
  return self.get_redirect_response(redirect_url)
183
183
 
184
- def login(self, *, request: HttpRequest, user: Any) -> Response:
184
+ def login(self, *, request: HttpRequest, user: Any) -> None:
185
185
  auth_login(request=request, user=user)
186
186
 
187
187
  def get_login_redirect_url(self, *, request: HttpRequest) -> str:
plain/oauth/views.py CHANGED
@@ -39,8 +39,9 @@ class OAuthCallbackView(TemplateView):
39
39
  logger.exception("OAuth error")
40
40
  self.oauth_error = e
41
41
 
42
- # Return a regular template response with the error
43
- return 400, super().get()
42
+ response = super().get()
43
+ response.status_code = 400
44
+ return response
44
45
 
45
46
  def get_template_context(self) -> dict:
46
47
  context = super().get_template_context()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.oauth
3
- Version: 0.20.0
3
+ Version: 0.22.0
4
4
  Summary: OAuth login and API access for Plain.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-Expression: BSD-3-Clause
@@ -103,10 +103,12 @@ class ExampleOAuthProvider(OAuthProvider):
103
103
  data = response.json()
104
104
  return OAuthUser(
105
105
  # The provider ID is required
106
- id=data["id"],
107
- # And you can populate any of your User model fields with additional kwargs
108
- email=data["email"],
109
- username=data["username"],
106
+ provider_id=data["id"],
107
+ # Populate your User model fields using the user_model_fields dict
108
+ user_model_fields={
109
+ "email": data["email"],
110
+ "username": data["username"],
111
+ },
110
112
  )
111
113
  ```
112
114
 
@@ -1,13 +1,14 @@
1
- plain/oauth/README.md,sha256=9_l9lOSndGBG31mD3oteT8UJMeonuCKdBreLQhUO70E,9900
1
+ plain/oauth/CHANGELOG.md,sha256=MjX5AOMH3NglFSfsdkEq1Wjh081JiCbRQCeZSyfpSw0,431
2
+ plain/oauth/README.md,sha256=N8getAUUhLX6P4mg-5P0V41gk5EKBGb8v904OfP2Z9E,9961
2
3
  plain/oauth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
4
  plain/oauth/admin.py,sha256=rqrGRRUVxOlG9wiuXtndIyQxd1VT67cvFy6qWo7LF-Q,1278
4
5
  plain/oauth/config.py,sha256=0Q4IILBKQbIaxqeL9WRTH5Cka-BO3c3SOj1AdQIAJgc,167
5
6
  plain/oauth/default_settings.py,sha256=dlN1J9vSOjjxPNLp-0qe-cLTqwM4E69ZAx_8lpxMhaM,28
6
7
  plain/oauth/exceptions.py,sha256=yoZsq8XgzstuwbE2ihoet0nzpw_sVZgDrwUauh6hhUs,546
7
- plain/oauth/models.py,sha256=ceSw9AKZMXffE4ZKZLxIbOlSyndTCHL22GCuSF3Hpmk,6880
8
- plain/oauth/providers.py,sha256=F5w1ZE0iEF8QZT4cdO6L7v5p2zHxby5_n-f6J0MM12E,7729
8
+ plain/oauth/models.py,sha256=T8VqqxeYGC4xKRVzUKAnc0OU3GN0otDAShDS6CPJhJs,6754
9
+ plain/oauth/providers.py,sha256=YDftJUMyyfXgsDCkyTNxGwrbwXAowL0Hg6KrwrAN5S0,7793
9
10
  plain/oauth/urls.py,sha256=FYzpQwhvZdcat8n3f7RyA-1Q21finKb8JEyakSOjXXg,696
10
- plain/oauth/views.py,sha256=I27UHQ-MgWVFRoeQUIsZZ81u2V8JXGJ6R3m2TO1lc8U,2408
11
+ plain/oauth/views.py,sha256=J2NCa37YediBTi82CfRlmsb45hFT6gWN6zMaFHhsDMM,2410
11
12
  plain/oauth/migrations/0001_initial.py,sha256=B9Finbn7ijEIUbkDy_B7UsKQLfMWaXd0Kx3oZrUENWc,1753
12
13
  plain/oauth/migrations/0002_alter_oauthconnection_options_and_more.py,sha256=3Mb0IU9KDRQfog0PjVbzuNv_AxCs7UVHnA0F263AKNo,581
13
14
  plain/oauth/migrations/0003_alter_oauthconnection_access_token_and_more.py,sha256=FyLfwxc2pRzF-CbdRFQRRSQTOCxc9l1womgStygm_lo,629
@@ -17,7 +18,7 @@ plain/oauth/migrations/0006_remove_oauthconnection_unique_oauth_provider_user_id
17
18
  plain/oauth/migrations/0007_alter_oauthconnection_provider_key_and_more.py,sha256=B_LW6xG1o_uA13tqUs0KniXl1JBNbQu4wMh2pW8rq5I,675
18
19
  plain/oauth/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
20
  plain/oauth/templates/oauth/callback.html,sha256=4CJG0oAN0xYjw2IPkjaL7B4hwlf9um9LI4CTu50E-yE,173
20
- plain_oauth-0.20.0.dist-info/METADATA,sha256=oBC0SBDaGuX3RV27Wfa-VHBymwrHRLqfjoImzOvKfIM,10304
21
- plain_oauth-0.20.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
- plain_oauth-0.20.0.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
23
- plain_oauth-0.20.0.dist-info/RECORD,,
21
+ plain_oauth-0.22.0.dist-info/METADATA,sha256=Nq5PH0dTgYbkounjfFRfcTo3Nn22M3Fw6x1krqb4kPY,10365
22
+ plain_oauth-0.22.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ plain_oauth-0.22.0.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
24
+ plain_oauth-0.22.0.dist-info/RECORD,,