user-auth-client 0.1.0__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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
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.
@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.4
2
+ Name: user-auth-client
3
+ Version: 0.1.0
4
+ Summary: Python client for user authentication: signup, login, reset password, and profile.
5
+ Author-email: Your Name <your.email@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/user-auth-client
8
+ Project-URL: Documentation, https://github.com/yourusername/user-auth-client#readme
9
+ Project-URL: Repository, https://github.com/yourusername/user-auth-client
10
+ Keywords: auth,login,signup,password-reset,profile,api-client
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: requests>=2.28.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7.0; extra == "dev"
27
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
28
+ Provides-Extra: django
29
+ Provides-Extra: fastapi
30
+ Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
31
+ Provides-Extra: flask
32
+ Requires-Dist: flask>=2.0.0; extra == "flask"
33
+ Provides-Extra: all
34
+ Requires-Dist: fastapi>=0.100.0; extra == "all"
35
+ Requires-Dist: flask>=2.0.0; extra == "all"
36
+ Dynamic: license-file
37
+
38
+ # User Auth Client
39
+
40
+ Python client for user authentication: **signup**, **login**, **reset password**, and **get profile**. Designed to work with any REST auth API and ready to publish on PyPI.
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install user-auth-client
46
+ ```
47
+
48
+ For framework integrations (optional):
49
+
50
+ ```bash
51
+ pip install user-auth-client[django] # Django
52
+ pip install user-auth-client[fastapi] # FastAPI
53
+ pip install user-auth-client[flask] # Flask
54
+ pip install user-auth-client[all] # FastAPI + Flask
55
+ ```
56
+
57
+ ## Quick start
58
+
59
+ ```python
60
+ from user_auth_client import AuthClient, SignupData, LoginData
61
+
62
+ client = AuthClient(base_url="https://your-api.example.com")
63
+
64
+ # Sign up
65
+ client.signup(SignupData(email="user@example.com", password="secret", username="jane"))
66
+
67
+ # Log in (stores token automatically if API returns access_token)
68
+ client.login(LoginData(email="user@example.com", password="secret"))
69
+
70
+ # Get profile (uses stored token)
71
+ profile = client.get_profile()
72
+ print(profile.email, profile.username)
73
+
74
+ # Reset password
75
+ client.reset_password("user@example.com")
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Django
81
+
82
+ Use the client in views with the request's `Authorization: Bearer <token>` header.
83
+
84
+ ```bash
85
+ pip install user-auth-client[django]
86
+ ```
87
+
88
+ **settings.py:**
89
+ ```python
90
+ AUTH_API_URL = "https://your-auth-api.com"
91
+ ```
92
+
93
+ **views.py:**
94
+ ```python
95
+ from django.http import JsonResponse
96
+ from django.conf import settings
97
+ from user_auth_client.django import get_client_from_request, get_current_user
98
+
99
+ def login_view(request):
100
+ from user_auth_client import AuthClient, LoginData
101
+ client = AuthClient(base_url=settings.AUTH_API_URL)
102
+ data = client.login(LoginData(email=request.POST["email"], password=request.POST["password"]))
103
+ return JsonResponse(data)
104
+
105
+ def profile_view(request):
106
+ user = get_current_user(request, settings.AUTH_API_URL)
107
+ if not user:
108
+ return JsonResponse({"error": "Unauthorized"}, status=401)
109
+ return JsonResponse({"email": user.email, "username": user.username})
110
+ ```
111
+
112
+ ---
113
+
114
+ ## FastAPI
115
+
116
+ Use dependency injection to get an `AuthClient` and the current user.
117
+
118
+ ```bash
119
+ pip install user-auth-client[fastapi]
120
+ ```
121
+
122
+ ```python
123
+ from fastapi import Depends
124
+ from user_auth_client import AuthClient
125
+ from user_auth_client.fastapi import auth_client_depends, get_current_user_depends
126
+ from user_auth_client.models import UserProfile
127
+
128
+ BASE_URL = "https://your-auth-api.com"
129
+ get_client = auth_client_depends(BASE_URL)
130
+ get_user = get_current_user_depends(BASE_URL)
131
+
132
+ @app.post("/auth/signup")
133
+ def signup(client: AuthClient = Depends(get_client)):
134
+ return {"ok": True}
135
+
136
+ @app.get("/profile")
137
+ def profile(user: UserProfile = Depends(get_user)):
138
+ return {"email": user.email, "id": user.id}
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Flask
144
+
145
+ Attach the client and current user with `init_app`, or use helpers per view.
146
+
147
+ ```bash
148
+ pip install user-auth-client[flask]
149
+ ```
150
+
151
+ **Option A – init_app (g.auth_client, g.current_user):**
152
+ ```python
153
+ from flask import Flask, g
154
+ from user_auth_client.flask import init_app
155
+
156
+ app = Flask(__name__)
157
+ app.config["AUTH_API_URL"] = "https://your-auth-api.com"
158
+ init_app(app)
159
+
160
+ @app.route("/profile")
161
+ def profile():
162
+ if g.current_user is None:
163
+ return {"error": "Unauthorized"}, 401
164
+ return {"email": g.current_user.email}
165
+ ```
166
+
167
+ **Option B – per-view helper:**
168
+ ```python
169
+ from user_auth_client.flask import get_current_user
170
+
171
+ @app.route("/me")
172
+ def me():
173
+ user = get_current_user(app.config["AUTH_API_URL"])
174
+ if not user:
175
+ return {"error": "Unauthorized"}, 401
176
+ return {"email": user.email}
177
+ ```
178
+
179
+ ---
180
+
181
+ ## API reference
182
+
183
+ ### `AuthClient(base_url, timeout=30.0, headers=None)`
184
+
185
+ - **base_url** – Base URL of your auth API (e.g. `https://api.example.com`).
186
+ - **timeout** – Request timeout in seconds.
187
+ - **headers** – Optional default headers for every request.
188
+
189
+ ### Methods
190
+
191
+ | Method | Description |
192
+ |--------|-------------|
193
+ | `signup(data: SignupData)` | Register a new user. Returns API response dict. |
194
+ | `login(data: LoginData)` | Log in with email/password. Sets token if response contains `access_token`. |
195
+ | `reset_password(email: str)` | Request password reset for the given email. |
196
+ | `get_profile() -> UserProfile` | Get current user profile (requires token). |
197
+ | `set_token(token: str)` | Set bearer token manually. |
198
+ | `clear_token()` | Clear stored token. |
199
+
200
+ ### Models
201
+
202
+ - **SignupData** – `email`, `password`, optional `username`, optional `extra` dict.
203
+ - **LoginData** – `email`, `password`.
204
+ - **UserProfile** – `id`, `email`, `username`, `raw` (full response dict).
205
+
206
+ ### Exceptions
207
+
208
+ - `AuthClientError` – Base error; has `message` and optional `status_code`.
209
+ - `AuthClientConnectionError` – Network/connection failure.
210
+ - `AuthClientAuthError` – Auth failure (401/403).
211
+
212
+ ### Example with custom token
213
+
214
+ ```python
215
+ # If your login endpoint returns a different key:
216
+ resp = client.login(LoginData(email="u@x.com", password="pwd"))
217
+ client.set_token(resp["token"]) # or resp["jwt"], etc.
218
+
219
+ profile = client.get_profile()
220
+ ```
221
+
222
+ ## Expected API shape
223
+
224
+ The client assumes your backend exposes REST endpoints like:
225
+
226
+ | Action | Method | Path | Body (JSON) |
227
+ |--------|--------|------|--------------|
228
+ | Signup | POST | `/auth/signup` | `email`, `password`, optional `username` |
229
+ | Login | POST | `/auth/login` | `email`, `password` |
230
+ | Reset password | POST | `/auth/reset-password` | `email` |
231
+ | Get profile | GET | `/auth/profile` | — (Bearer token) |
232
+
233
+ Login response may include `access_token`; if present, the client stores it for `get_profile()`. You can also call `set_token()` after login with a different key.
234
+
235
+ ## Development
236
+
237
+ ```bash
238
+ git clone https://github.com/yourusername/user-auth-client
239
+ cd user-auth-client
240
+ pip install -e ".[dev]"
241
+ pytest
242
+ ```
243
+
244
+ ## Publishing to PyPI
245
+
246
+ 1. Install build and twine:
247
+ `pip install build twine`
248
+ 2. Build:
249
+ `python -m build`
250
+ 3. Upload (use PyPI token):
251
+ `twine upload dist/*`
252
+
253
+ Update `pyproject.toml` (version, `authors`, `urls`) and `README` links before publishing.
254
+
255
+ ## License
256
+
257
+ MIT
@@ -0,0 +1,220 @@
1
+ # User Auth Client
2
+
3
+ Python client for user authentication: **signup**, **login**, **reset password**, and **get profile**. Designed to work with any REST auth API and ready to publish on PyPI.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install user-auth-client
9
+ ```
10
+
11
+ For framework integrations (optional):
12
+
13
+ ```bash
14
+ pip install user-auth-client[django] # Django
15
+ pip install user-auth-client[fastapi] # FastAPI
16
+ pip install user-auth-client[flask] # Flask
17
+ pip install user-auth-client[all] # FastAPI + Flask
18
+ ```
19
+
20
+ ## Quick start
21
+
22
+ ```python
23
+ from user_auth_client import AuthClient, SignupData, LoginData
24
+
25
+ client = AuthClient(base_url="https://your-api.example.com")
26
+
27
+ # Sign up
28
+ client.signup(SignupData(email="user@example.com", password="secret", username="jane"))
29
+
30
+ # Log in (stores token automatically if API returns access_token)
31
+ client.login(LoginData(email="user@example.com", password="secret"))
32
+
33
+ # Get profile (uses stored token)
34
+ profile = client.get_profile()
35
+ print(profile.email, profile.username)
36
+
37
+ # Reset password
38
+ client.reset_password("user@example.com")
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Django
44
+
45
+ Use the client in views with the request's `Authorization: Bearer <token>` header.
46
+
47
+ ```bash
48
+ pip install user-auth-client[django]
49
+ ```
50
+
51
+ **settings.py:**
52
+ ```python
53
+ AUTH_API_URL = "https://your-auth-api.com"
54
+ ```
55
+
56
+ **views.py:**
57
+ ```python
58
+ from django.http import JsonResponse
59
+ from django.conf import settings
60
+ from user_auth_client.django import get_client_from_request, get_current_user
61
+
62
+ def login_view(request):
63
+ from user_auth_client import AuthClient, LoginData
64
+ client = AuthClient(base_url=settings.AUTH_API_URL)
65
+ data = client.login(LoginData(email=request.POST["email"], password=request.POST["password"]))
66
+ return JsonResponse(data)
67
+
68
+ def profile_view(request):
69
+ user = get_current_user(request, settings.AUTH_API_URL)
70
+ if not user:
71
+ return JsonResponse({"error": "Unauthorized"}, status=401)
72
+ return JsonResponse({"email": user.email, "username": user.username})
73
+ ```
74
+
75
+ ---
76
+
77
+ ## FastAPI
78
+
79
+ Use dependency injection to get an `AuthClient` and the current user.
80
+
81
+ ```bash
82
+ pip install user-auth-client[fastapi]
83
+ ```
84
+
85
+ ```python
86
+ from fastapi import Depends
87
+ from user_auth_client import AuthClient
88
+ from user_auth_client.fastapi import auth_client_depends, get_current_user_depends
89
+ from user_auth_client.models import UserProfile
90
+
91
+ BASE_URL = "https://your-auth-api.com"
92
+ get_client = auth_client_depends(BASE_URL)
93
+ get_user = get_current_user_depends(BASE_URL)
94
+
95
+ @app.post("/auth/signup")
96
+ def signup(client: AuthClient = Depends(get_client)):
97
+ return {"ok": True}
98
+
99
+ @app.get("/profile")
100
+ def profile(user: UserProfile = Depends(get_user)):
101
+ return {"email": user.email, "id": user.id}
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Flask
107
+
108
+ Attach the client and current user with `init_app`, or use helpers per view.
109
+
110
+ ```bash
111
+ pip install user-auth-client[flask]
112
+ ```
113
+
114
+ **Option A – init_app (g.auth_client, g.current_user):**
115
+ ```python
116
+ from flask import Flask, g
117
+ from user_auth_client.flask import init_app
118
+
119
+ app = Flask(__name__)
120
+ app.config["AUTH_API_URL"] = "https://your-auth-api.com"
121
+ init_app(app)
122
+
123
+ @app.route("/profile")
124
+ def profile():
125
+ if g.current_user is None:
126
+ return {"error": "Unauthorized"}, 401
127
+ return {"email": g.current_user.email}
128
+ ```
129
+
130
+ **Option B – per-view helper:**
131
+ ```python
132
+ from user_auth_client.flask import get_current_user
133
+
134
+ @app.route("/me")
135
+ def me():
136
+ user = get_current_user(app.config["AUTH_API_URL"])
137
+ if not user:
138
+ return {"error": "Unauthorized"}, 401
139
+ return {"email": user.email}
140
+ ```
141
+
142
+ ---
143
+
144
+ ## API reference
145
+
146
+ ### `AuthClient(base_url, timeout=30.0, headers=None)`
147
+
148
+ - **base_url** – Base URL of your auth API (e.g. `https://api.example.com`).
149
+ - **timeout** – Request timeout in seconds.
150
+ - **headers** – Optional default headers for every request.
151
+
152
+ ### Methods
153
+
154
+ | Method | Description |
155
+ |--------|-------------|
156
+ | `signup(data: SignupData)` | Register a new user. Returns API response dict. |
157
+ | `login(data: LoginData)` | Log in with email/password. Sets token if response contains `access_token`. |
158
+ | `reset_password(email: str)` | Request password reset for the given email. |
159
+ | `get_profile() -> UserProfile` | Get current user profile (requires token). |
160
+ | `set_token(token: str)` | Set bearer token manually. |
161
+ | `clear_token()` | Clear stored token. |
162
+
163
+ ### Models
164
+
165
+ - **SignupData** – `email`, `password`, optional `username`, optional `extra` dict.
166
+ - **LoginData** – `email`, `password`.
167
+ - **UserProfile** – `id`, `email`, `username`, `raw` (full response dict).
168
+
169
+ ### Exceptions
170
+
171
+ - `AuthClientError` – Base error; has `message` and optional `status_code`.
172
+ - `AuthClientConnectionError` – Network/connection failure.
173
+ - `AuthClientAuthError` – Auth failure (401/403).
174
+
175
+ ### Example with custom token
176
+
177
+ ```python
178
+ # If your login endpoint returns a different key:
179
+ resp = client.login(LoginData(email="u@x.com", password="pwd"))
180
+ client.set_token(resp["token"]) # or resp["jwt"], etc.
181
+
182
+ profile = client.get_profile()
183
+ ```
184
+
185
+ ## Expected API shape
186
+
187
+ The client assumes your backend exposes REST endpoints like:
188
+
189
+ | Action | Method | Path | Body (JSON) |
190
+ |--------|--------|------|--------------|
191
+ | Signup | POST | `/auth/signup` | `email`, `password`, optional `username` |
192
+ | Login | POST | `/auth/login` | `email`, `password` |
193
+ | Reset password | POST | `/auth/reset-password` | `email` |
194
+ | Get profile | GET | `/auth/profile` | — (Bearer token) |
195
+
196
+ Login response may include `access_token`; if present, the client stores it for `get_profile()`. You can also call `set_token()` after login with a different key.
197
+
198
+ ## Development
199
+
200
+ ```bash
201
+ git clone https://github.com/yourusername/user-auth-client
202
+ cd user-auth-client
203
+ pip install -e ".[dev]"
204
+ pytest
205
+ ```
206
+
207
+ ## Publishing to PyPI
208
+
209
+ 1. Install build and twine:
210
+ `pip install build twine`
211
+ 2. Build:
212
+ `python -m build`
213
+ 3. Upload (use PyPI token):
214
+ `twine upload dist/*`
215
+
216
+ Update `pyproject.toml` (version, `authors`, `urls`) and `README` links before publishing.
217
+
218
+ ## License
219
+
220
+ MIT
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "user-auth-client"
7
+ version = "0.1.0"
8
+ description = "Python client for user authentication: signup, login, reset password, and profile."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ authors = [{ name = "Your Name", email = "your.email@example.com" }]
12
+ keywords = ["auth", "login", "signup", "password-reset", "profile", "api-client"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.8",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ ]
25
+ requires-python = ">=3.8"
26
+ dependencies = [
27
+ "requests>=2.28.0",
28
+ ]
29
+
30
+ [project.optional-dependencies]
31
+ dev = [
32
+ "pytest>=7.0",
33
+ "pytest-cov>=4.0",
34
+ ]
35
+ django = []
36
+ fastapi = [
37
+ "fastapi>=0.100.0",
38
+ ]
39
+ flask = [
40
+ "flask>=2.0.0",
41
+ ]
42
+ all = [
43
+ "fastapi>=0.100.0",
44
+ "flask>=2.0.0",
45
+ ]
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/yourusername/user-auth-client"
49
+ Documentation = "https://github.com/yourusername/user-auth-client#readme"
50
+ Repository = "https://github.com/yourusername/user-auth-client"
51
+
52
+ [tool.setuptools.packages.find]
53
+ where = ["src"]
54
+
55
+ [tool.setuptools.package-dir]
56
+ "" = "src"
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+
61
+ [tool.setuptools.package-data]
62
+ "*" = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ """User authentication client: signup, login, reset password, get profile."""
2
+
3
+ from user_auth_client.client import AuthClient
4
+ from user_auth_client.exceptions import (
5
+ AuthClientError,
6
+ AuthClientConnectionError,
7
+ AuthClientAuthError,
8
+ )
9
+ from user_auth_client.models import UserProfile, SignupData, LoginData
10
+
11
+ __version__ = "0.1.0"
12
+ __all__ = [
13
+ "AuthClient",
14
+ "AuthClientError",
15
+ "AuthClientConnectionError",
16
+ "AuthClientAuthError",
17
+ "UserProfile",
18
+ "SignupData",
19
+ "LoginData",
20
+ "__version__",
21
+ ]
@@ -0,0 +1,13 @@
1
+ """Extract Bearer token from Authorization header."""
2
+
3
+ from typing import Optional
4
+
5
+
6
+ def get_bearer_token(authorization: Optional[str]) -> Optional[str]:
7
+ """Return token from 'Bearer <token>' or None."""
8
+ if not authorization or not isinstance(authorization, str):
9
+ return None
10
+ parts = authorization.strip().split()
11
+ if len(parts) == 2 and parts[0].lower() == "bearer":
12
+ return parts[1] or None
13
+ return None