hyperpocket 0.1.10__py3-none-any.whl → 0.2.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.
- hyperpocket/__init__.py +4 -4
- hyperpocket/auth/__init__.py +12 -7
- hyperpocket/auth/calendly/oauth2_handler.py +24 -17
- hyperpocket/auth/calendly/oauth2_schema.py +3 -1
- hyperpocket/auth/context.py +2 -1
- hyperpocket/auth/github/oauth2_handler.py +13 -8
- hyperpocket/auth/github/token_handler.py +27 -21
- hyperpocket/auth/google/context.py +1 -3
- hyperpocket/auth/google/oauth2_context.py +1 -1
- hyperpocket/auth/google/oauth2_handler.py +22 -17
- hyperpocket/auth/gumloop/token_context.py +1 -4
- hyperpocket/auth/gumloop/token_handler.py +48 -20
- hyperpocket/auth/gumloop/token_schema.py +2 -1
- hyperpocket/auth/handler.py +21 -6
- hyperpocket/auth/linear/token_context.py +2 -5
- hyperpocket/auth/linear/token_handler.py +45 -21
- hyperpocket/auth/notion/context.py +2 -2
- hyperpocket/auth/notion/token_context.py +2 -4
- hyperpocket/auth/notion/token_handler.py +45 -21
- hyperpocket/auth/notion/token_schema.py +0 -1
- hyperpocket/auth/reddit/oauth2_handler.py +9 -10
- hyperpocket/auth/reddit/oauth2_schema.py +0 -2
- hyperpocket/auth/schema.py +4 -1
- hyperpocket/auth/slack/oauth2_context.py +3 -1
- hyperpocket/auth/slack/oauth2_handler.py +55 -35
- hyperpocket/auth/slack/token_context.py +2 -4
- hyperpocket/auth/slack/token_handler.py +42 -19
- hyperpocket/builtin.py +4 -2
- hyperpocket/cli/__main__.py +4 -2
- hyperpocket/cli/auth.py +59 -28
- hyperpocket/cli/codegen/auth/auth_context_template.py +3 -2
- hyperpocket/cli/codegen/auth/auth_token_context_template.py +3 -2
- hyperpocket/cli/codegen/auth/auth_token_handler_template.py +6 -5
- hyperpocket/cli/codegen/auth/auth_token_schema_template.py +3 -2
- hyperpocket/cli/codegen/auth/server_auth_template.py +3 -2
- hyperpocket/cli/pull.py +5 -5
- hyperpocket/config/__init__.py +3 -8
- hyperpocket/config/auth.py +3 -1
- hyperpocket/config/logger.py +20 -15
- hyperpocket/config/session.py +4 -2
- hyperpocket/config/settings.py +19 -2
- hyperpocket/futures/__init__.py +1 -1
- hyperpocket/futures/futurestore.py +3 -2
- hyperpocket/pocket_auth.py +171 -84
- hyperpocket/pocket_core.py +51 -33
- hyperpocket/pocket_main.py +122 -93
- hyperpocket/prompts.py +2 -2
- hyperpocket/repository/__init__.py +1 -1
- hyperpocket/repository/lock.py +47 -33
- hyperpocket/repository/lockfile.py +2 -2
- hyperpocket/repository/repository.py +1 -1
- hyperpocket/server/__init__.py +1 -1
- hyperpocket/server/auth/github.py +2 -1
- hyperpocket/server/auth/linear.py +1 -3
- hyperpocket/server/auth/notion.py +2 -5
- hyperpocket/server/auth/slack.py +1 -3
- hyperpocket/server/auth/token.py +17 -11
- hyperpocket/server/proxy.py +29 -13
- hyperpocket/server/server.py +75 -31
- hyperpocket/server/tool/dto/script.py +15 -10
- hyperpocket/server/tool/wasm.py +14 -11
- hyperpocket/session/__init__.py +6 -2
- hyperpocket/session/in_memory.py +44 -24
- hyperpocket/session/interface.py +42 -24
- hyperpocket/session/redis.py +48 -31
- hyperpocket/tool/__init__.py +10 -10
- hyperpocket/tool/function/__init__.py +1 -5
- hyperpocket/tool/function/annotation.py +11 -9
- hyperpocket/tool/function/tool.py +37 -27
- hyperpocket/tool/tool.py +59 -36
- hyperpocket/tool/wasm/__init__.py +1 -1
- hyperpocket/tool/wasm/browser.py +15 -10
- hyperpocket/tool/wasm/invoker.py +16 -16
- hyperpocket/tool/wasm/script.py +27 -14
- hyperpocket/tool/wasm/templates/__init__.py +22 -15
- hyperpocket/tool/wasm/templates/node.py +2 -2
- hyperpocket/tool/wasm/templates/python.py +2 -2
- hyperpocket/tool/wasm/tool.py +27 -14
- hyperpocket/tool_like.py +3 -3
- hyperpocket/util/__init__.py +1 -1
- hyperpocket/util/extract_func_param_desc_from_docstring.py +23 -7
- hyperpocket/util/find_all_leaf_class_in_package.py +4 -3
- hyperpocket/util/find_all_subclass_in_package.py +4 -2
- hyperpocket/util/flatten_json_schema.py +10 -6
- hyperpocket/util/function_to_model.py +33 -12
- hyperpocket/util/get_objects_from_subpackage.py +1 -1
- hyperpocket/util/json_schema_to_model.py +14 -5
- {hyperpocket-0.1.10.dist-info → hyperpocket-0.2.0.dist-info}/METADATA +11 -5
- hyperpocket-0.2.0.dist-info/RECORD +137 -0
- hyperpocket-0.1.10.dist-info/RECORD +0 -137
- {hyperpocket-0.1.10.dist-info → hyperpocket-0.2.0.dist-info}/WHEEL +0 -0
- {hyperpocket-0.1.10.dist-info → hyperpocket-0.2.0.dist-info}/entry_points.txt +0 -0
hyperpocket/__init__.py
CHANGED
hyperpocket/auth/__init__.py
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
from hyperpocket.auth.context import AuthContext
|
2
2
|
from hyperpocket.auth.handler import AuthHandlerInterface
|
3
3
|
from hyperpocket.auth.provider import AuthProvider
|
4
|
-
from hyperpocket.util.find_all_leaf_class_in_package import
|
4
|
+
from hyperpocket.util.find_all_leaf_class_in_package import (
|
5
|
+
find_all_leaf_class_in_package,
|
6
|
+
)
|
5
7
|
|
6
|
-
PREBUILT_AUTH_HANDLERS = find_all_leaf_class_in_package(
|
8
|
+
PREBUILT_AUTH_HANDLERS = find_all_leaf_class_in_package(
|
9
|
+
"hyperpocket.auth", AuthHandlerInterface
|
10
|
+
)
|
7
11
|
AUTH_CONTEXT_MAP = {
|
8
|
-
leaf.__name__: leaf
|
12
|
+
leaf.__name__: leaf
|
13
|
+
for leaf in find_all_leaf_class_in_package("hyperpocket.auth", AuthContext)
|
9
14
|
}
|
10
15
|
|
11
16
|
__all__ = [
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
"PREBUILT_AUTH_HANDLERS",
|
18
|
+
"AUTH_CONTEXT_MAP",
|
19
|
+
"AuthProvider",
|
20
|
+
"AuthHandlerInterface",
|
16
21
|
]
|
@@ -4,7 +4,10 @@ from urllib.parse import urlencode, urljoin
|
|
4
4
|
import httpx
|
5
5
|
|
6
6
|
from hyperpocket.auth.calendly.oauth2_context import CalendlyOAuth2AuthContext
|
7
|
-
from hyperpocket.auth.calendly.oauth2_schema import
|
7
|
+
from hyperpocket.auth.calendly.oauth2_schema import (
|
8
|
+
CalendlyOAuth2Request,
|
9
|
+
CalendlyOAuth2Response,
|
10
|
+
)
|
8
11
|
from hyperpocket.auth.context import AuthContext
|
9
12
|
from hyperpocket.auth.handler import AuthHandlerInterface, AuthProvider
|
10
13
|
from hyperpocket.config import config
|
@@ -16,7 +19,9 @@ class CalendlyOAuth2AuthHandler(AuthHandlerInterface):
|
|
16
19
|
_CALENDLY_TOKEN_URL = "https://auth.calendly.com/oauth/token"
|
17
20
|
|
18
21
|
name: str = "calendly-oauth2"
|
19
|
-
description: str =
|
22
|
+
description: str = (
|
23
|
+
"This handler is used to authenticate users using Calendly OAuth."
|
24
|
+
)
|
20
25
|
scoped: bool = False
|
21
26
|
|
22
27
|
@staticmethod
|
@@ -32,17 +37,17 @@ class CalendlyOAuth2AuthHandler(AuthHandlerInterface):
|
|
32
37
|
return set()
|
33
38
|
|
34
39
|
def prepare(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
self,
|
41
|
+
auth_req: CalendlyOAuth2Request,
|
42
|
+
thread_id: str,
|
43
|
+
profile: str,
|
44
|
+
future_uid: str,
|
45
|
+
*args,
|
46
|
+
**kwargs,
|
42
47
|
) -> str:
|
43
48
|
redirect_uri = urljoin(
|
44
|
-
config.public_base_url + "/",
|
45
|
-
f"{config.callback_url_rewrite_prefix}/auth/calendly/oauth2/callback",
|
49
|
+
config().public_base_url + "/",
|
50
|
+
f"{config().callback_url_rewrite_prefix}/auth/calendly/oauth2/callback",
|
46
51
|
)
|
47
52
|
auth_url = self._make_auth_url(auth_req, redirect_uri, future_uid)
|
48
53
|
|
@@ -58,7 +63,7 @@ class CalendlyOAuth2AuthHandler(AuthHandlerInterface):
|
|
58
63
|
return f"User needs to authenticate using the following URL: {auth_url}"
|
59
64
|
|
60
65
|
async def authenticate(
|
61
|
-
|
66
|
+
self, auth_req: CalendlyOAuth2Request, future_uid: str, *args, **kwargs
|
62
67
|
) -> AuthContext:
|
63
68
|
future_data = FutureStore.get_future(future_uid)
|
64
69
|
auth_code = await future_data.future
|
@@ -97,7 +102,7 @@ class CalendlyOAuth2AuthHandler(AuthHandlerInterface):
|
|
97
102
|
return CalendlyOAuth2AuthContext.from_calendly_oauth2_response(auth_response)
|
98
103
|
|
99
104
|
async def refresh(
|
100
|
-
|
105
|
+
self, auth_req: CalendlyOAuth2Request, context: AuthContext, *args, **kwargs
|
101
106
|
) -> AuthContext:
|
102
107
|
last_oauth2_resp: CalendlyOAuth2Response = context.detail
|
103
108
|
refresh_token = last_oauth2_resp.refresh_token
|
@@ -127,7 +132,9 @@ class CalendlyOAuth2AuthHandler(AuthHandlerInterface):
|
|
127
132
|
response = CalendlyOAuth2Response(**resp_json)
|
128
133
|
return CalendlyOAuth2AuthContext.from_calendly_oauth2_response(response)
|
129
134
|
|
130
|
-
def _make_auth_url(
|
135
|
+
def _make_auth_url(
|
136
|
+
self, auth_req: CalendlyOAuth2Request, redirect_uri: str, state: str
|
137
|
+
):
|
131
138
|
params = {
|
132
139
|
"client_id": auth_req.client_id,
|
133
140
|
"redirect_uri": redirect_uri,
|
@@ -137,10 +144,10 @@ class CalendlyOAuth2AuthHandler(AuthHandlerInterface):
|
|
137
144
|
return f"{self._CALENDLY_AUTH_URL}?{urlencode(params)}"
|
138
145
|
|
139
146
|
def make_request(
|
140
|
-
|
147
|
+
self, auth_scopes: Optional[list[str]] = None, **kwargs
|
141
148
|
) -> CalendlyOAuth2Request:
|
142
149
|
return CalendlyOAuth2Request(
|
143
150
|
auth_scopes=auth_scopes,
|
144
|
-
client_id=config.auth.calendly.client_id,
|
145
|
-
client_secret=config.auth.calendly.client_secret,
|
151
|
+
client_id=config().auth.calendly.client_id,
|
152
|
+
client_secret=config().auth.calendly.client_secret,
|
146
153
|
)
|
hyperpocket/auth/context.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
2
|
from datetime import datetime
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Optional
|
4
4
|
|
5
5
|
from pydantic import BaseModel, Field
|
6
6
|
|
@@ -9,6 +9,7 @@ class AuthContext(BaseModel, ABC):
|
|
9
9
|
"""
|
10
10
|
This class is used to define the interface of the authentication model.
|
11
11
|
"""
|
12
|
+
|
12
13
|
access_token: str = Field(description="user's access token")
|
13
14
|
description: str = Field(description="description of this authentication context")
|
14
15
|
expires_at: Optional[datetime] = Field(description="expiration datetime")
|
@@ -5,7 +5,10 @@ import httpx
|
|
5
5
|
|
6
6
|
from hyperpocket.auth.context import AuthContext
|
7
7
|
from hyperpocket.auth.github.oauth2_context import GitHubOAuth2AuthContext
|
8
|
-
from hyperpocket.auth.github.oauth2_schema import
|
8
|
+
from hyperpocket.auth.github.oauth2_schema import (
|
9
|
+
GitHubOAuth2Request,
|
10
|
+
GitHubOAuth2Response,
|
11
|
+
)
|
9
12
|
from hyperpocket.auth.handler import AuthHandlerInterface, AuthProvider
|
10
13
|
from hyperpocket.config import config
|
11
14
|
from hyperpocket.futures import FutureStore
|
@@ -41,8 +44,8 @@ class GitHubOAuth2AuthHandler(AuthHandlerInterface):
|
|
41
44
|
**kwargs,
|
42
45
|
) -> str:
|
43
46
|
redirect_uri = urljoin(
|
44
|
-
config.public_base_url + "/",
|
45
|
-
f"{config.callback_url_rewrite_prefix}/auth/github/oauth2/callback",
|
47
|
+
config().public_base_url + "/",
|
48
|
+
f"{config().callback_url_rewrite_prefix}/auth/github/oauth2/callback",
|
46
49
|
)
|
47
50
|
auth_url = self._make_auth_url(auth_req, redirect_uri, future_uid)
|
48
51
|
|
@@ -60,7 +63,7 @@ class GitHubOAuth2AuthHandler(AuthHandlerInterface):
|
|
60
63
|
async def authenticate(
|
61
64
|
self, auth_req: GitHubOAuth2Request, future_uid: str, *args, **kwargs
|
62
65
|
) -> AuthContext:
|
63
|
-
future_data = FutureStore.get_future(
|
66
|
+
future_data = FutureStore.get_future(future_uid)
|
64
67
|
auth_code = await future_data.future
|
65
68
|
|
66
69
|
async with httpx.AsyncClient() as client:
|
@@ -124,7 +127,9 @@ class GitHubOAuth2AuthHandler(AuthHandlerInterface):
|
|
124
127
|
response = GitHubOAuth2Response(**resp_json)
|
125
128
|
return GitHubOAuth2AuthContext.from_github_oauth2_response(response)
|
126
129
|
|
127
|
-
def _make_auth_url(
|
130
|
+
def _make_auth_url(
|
131
|
+
self, auth_req: GitHubOAuth2Request, redirect_uri: str, state: str
|
132
|
+
):
|
128
133
|
params = {
|
129
134
|
"client_id": auth_req.client_id,
|
130
135
|
"redirect_uri": redirect_uri,
|
@@ -132,12 +137,12 @@ class GitHubOAuth2AuthHandler(AuthHandlerInterface):
|
|
132
137
|
"state": state,
|
133
138
|
}
|
134
139
|
return f"{self._GITHUB_AUTH_URL}?{urlencode(params)}"
|
135
|
-
|
140
|
+
|
136
141
|
def make_request(
|
137
142
|
self, auth_scopes: Optional[list[str]] = None, **kwargs
|
138
143
|
) -> GitHubOAuth2Request:
|
139
144
|
return GitHubOAuth2Request(
|
140
145
|
auth_scopes=auth_scopes,
|
141
|
-
client_id=config.auth.github.client_id,
|
142
|
-
client_secret=config.auth.github.client_secret,
|
146
|
+
client_id=config().auth.github.client_id,
|
147
|
+
client_secret=config().auth.github.client_secret,
|
143
148
|
)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from typing import Optional
|
2
|
-
from urllib.parse import
|
2
|
+
from urllib.parse import urlencode, urljoin
|
3
3
|
|
4
|
-
from hyperpocket.auth import
|
4
|
+
from hyperpocket.auth import AuthHandlerInterface, AuthProvider
|
5
5
|
from hyperpocket.auth.context import AuthContext
|
6
6
|
from hyperpocket.auth.github.token_context import GitHubTokenAuthContext
|
7
7
|
from hyperpocket.auth.github.token_schema import GitHubTokenRequest, GitHubTokenResponse
|
@@ -17,7 +17,10 @@ class GitHubTokenAuthHandler(AuthHandlerInterface):
|
|
17
17
|
)
|
18
18
|
scoped: bool = False
|
19
19
|
|
20
|
-
_TOKEN_URL: str = urljoin(
|
20
|
+
_TOKEN_URL: str = urljoin(
|
21
|
+
config().public_base_url + "/",
|
22
|
+
f"{config().callback_url_rewrite_prefix}/auth/token",
|
23
|
+
)
|
21
24
|
|
22
25
|
@staticmethod
|
23
26
|
def provider() -> AuthProvider:
|
@@ -28,19 +31,21 @@ class GitHubTokenAuthHandler(AuthHandlerInterface):
|
|
28
31
|
return set()
|
29
32
|
|
30
33
|
def prepare(
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
self,
|
35
|
+
auth_req: AuthenticateRequest,
|
36
|
+
thread_id: str,
|
37
|
+
profile: str,
|
38
|
+
future_uid: str,
|
39
|
+
*args,
|
40
|
+
**kwargs,
|
38
41
|
) -> str:
|
39
42
|
redirect_uri = urljoin(
|
40
|
-
config.public_base_url + "/",
|
41
|
-
f"{config.callback_url_rewrite_prefix}/auth/github/token/callback",
|
43
|
+
config().public_base_url + "/",
|
44
|
+
f"{config().callback_url_rewrite_prefix}/auth/github/token/callback",
|
45
|
+
)
|
46
|
+
auth_url = self._make_auth_url(
|
47
|
+
auth_req=auth_req, redirect_uri=redirect_uri, state=future_uid
|
42
48
|
)
|
43
|
-
auth_url = self._make_auth_url(auth_req=auth_req, redirect_uri=redirect_uri, state=future_uid)
|
44
49
|
FutureStore.create_future(
|
45
50
|
future_uid,
|
46
51
|
data={
|
@@ -53,7 +58,7 @@ class GitHubTokenAuthHandler(AuthHandlerInterface):
|
|
53
58
|
return f"User needs to authenticate using the following URL: {auth_url}"
|
54
59
|
|
55
60
|
async def authenticate(
|
56
|
-
|
61
|
+
self, auth_req: GitHubTokenRequest, future_uid: str, *args, **kwargs
|
57
62
|
) -> GitHubTokenAuthContext:
|
58
63
|
future_data = FutureStore.get_future(future_uid)
|
59
64
|
access_token = await future_data.future
|
@@ -64,16 +69,17 @@ class GitHubTokenAuthHandler(AuthHandlerInterface):
|
|
64
69
|
return context
|
65
70
|
|
66
71
|
async def refresh(
|
67
|
-
|
72
|
+
self, auth_req: GitHubTokenRequest, context: AuthContext, *args, **kwargs
|
68
73
|
) -> AuthContext:
|
69
74
|
raise Exception("GitHub token doesn't support refresh")
|
70
75
|
|
71
|
-
def _make_auth_url(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
}
|
76
|
+
def _make_auth_url(
|
77
|
+
self, auth_req: GitHubTokenRequest, redirect_uri: str, state: str
|
78
|
+
):
|
79
|
+
params = {"redirect_uri": redirect_uri, "state": state}
|
76
80
|
return f"{self._TOKEN_URL}?{urlencode(params)}"
|
77
81
|
|
78
|
-
def make_request(
|
82
|
+
def make_request(
|
83
|
+
self, auth_scopes: Optional[list[str]] = None, **kwargs
|
84
|
+
) -> GitHubTokenRequest:
|
79
85
|
return GitHubTokenRequest()
|
@@ -5,9 +5,7 @@ class GoogleAuthContext(AuthContext):
|
|
5
5
|
_ACCESS_TOKEN_KEY: str = "GOOGLE_TOKEN"
|
6
6
|
|
7
7
|
def to_dict(self) -> dict[str, str]:
|
8
|
-
return {
|
9
|
-
self._ACCESS_TOKEN_KEY: self.access_token
|
10
|
-
}
|
8
|
+
return {self._ACCESS_TOKEN_KEY: self.access_token}
|
11
9
|
|
12
10
|
def to_profiled_dict(self, profile: str) -> dict[str, str]:
|
13
11
|
return {
|
@@ -12,7 +12,7 @@ class GoogleOAuth2AuthContext(GoogleAuthContext):
|
|
12
12
|
|
13
13
|
@classmethod
|
14
14
|
def from_google_oauth2_response(
|
15
|
-
|
15
|
+
cls, response: GoogleOAuth2Response
|
16
16
|
) -> "GoogleOAuth2AuthContext":
|
17
17
|
description = f"Google OAuth2 Context logged in with {response.scope} scopes"
|
18
18
|
now = datetime.now(tz=timezone.utc)
|
@@ -5,7 +5,10 @@ import httpx
|
|
5
5
|
|
6
6
|
from hyperpocket.auth.context import AuthContext
|
7
7
|
from hyperpocket.auth.google.oauth2_context import GoogleOAuth2AuthContext
|
8
|
-
from hyperpocket.auth.google.oauth2_schema import
|
8
|
+
from hyperpocket.auth.google.oauth2_schema import (
|
9
|
+
GoogleOAuth2Request,
|
10
|
+
GoogleOAuth2Response,
|
11
|
+
)
|
9
12
|
from hyperpocket.auth.handler import AuthHandlerInterface, AuthProvider
|
10
13
|
from hyperpocket.config import config
|
11
14
|
from hyperpocket.futures import FutureStore
|
@@ -32,17 +35,17 @@ class GoogleOAuth2AuthHandler(AuthHandlerInterface):
|
|
32
35
|
return set()
|
33
36
|
|
34
37
|
def prepare(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
self,
|
39
|
+
auth_req: GoogleOAuth2Request,
|
40
|
+
thread_id: str,
|
41
|
+
profile: str,
|
42
|
+
future_uid: str,
|
43
|
+
*args,
|
44
|
+
**kwargs,
|
42
45
|
) -> str:
|
43
46
|
redirect_uri = urljoin(
|
44
|
-
config.public_base_url + "/",
|
45
|
-
f"{config.callback_url_rewrite_prefix}/auth/google/oauth2/callback",
|
47
|
+
config().public_base_url + "/",
|
48
|
+
f"{config().callback_url_rewrite_prefix}/auth/google/oauth2/callback",
|
46
49
|
)
|
47
50
|
auth_url = self._make_auth_url(auth_req, redirect_uri, future_uid)
|
48
51
|
|
@@ -58,9 +61,9 @@ class GoogleOAuth2AuthHandler(AuthHandlerInterface):
|
|
58
61
|
return f"User needs to authenticate using the following URL: {auth_url}"
|
59
62
|
|
60
63
|
async def authenticate(
|
61
|
-
|
64
|
+
self, auth_req: GoogleOAuth2Request, future_uid: str, *args, **kwargs
|
62
65
|
) -> AuthContext:
|
63
|
-
future_data = FutureStore.get_future(
|
66
|
+
future_data = FutureStore.get_future(future_uid)
|
64
67
|
auth_code = await future_data.future
|
65
68
|
|
66
69
|
async with httpx.AsyncClient() as client:
|
@@ -83,7 +86,7 @@ class GoogleOAuth2AuthHandler(AuthHandlerInterface):
|
|
83
86
|
return GoogleOAuth2AuthContext.from_google_oauth2_response(auth_response)
|
84
87
|
|
85
88
|
async def refresh(
|
86
|
-
|
89
|
+
self, auth_req: GoogleOAuth2Request, context: AuthContext, *args, **kwargs
|
87
90
|
) -> AuthContext:
|
88
91
|
google_context: GoogleOAuth2AuthContext = context
|
89
92
|
last_oauth2_resp: GoogleOAuth2Response = google_context.detail
|
@@ -116,7 +119,9 @@ class GoogleOAuth2AuthHandler(AuthHandlerInterface):
|
|
116
119
|
response = GoogleOAuth2Response(**resp_json)
|
117
120
|
return GoogleOAuth2AuthContext.from_google_oauth2_response(response)
|
118
121
|
|
119
|
-
def _make_auth_url(
|
122
|
+
def _make_auth_url(
|
123
|
+
self, auth_req: GoogleOAuth2Request, redirect_uri: str, state: str
|
124
|
+
):
|
120
125
|
params = {
|
121
126
|
"client_id": auth_req.client_id,
|
122
127
|
"redirect_uri": redirect_uri,
|
@@ -128,10 +133,10 @@ class GoogleOAuth2AuthHandler(AuthHandlerInterface):
|
|
128
133
|
return f"{self._GOOGLE_AUTH_URL}?{urlencode(params)}"
|
129
134
|
|
130
135
|
def make_request(
|
131
|
-
|
136
|
+
self, auth_scopes: Optional[list[str]] = None, **kwargs
|
132
137
|
) -> GoogleOAuth2Request:
|
133
138
|
return GoogleOAuth2Request(
|
134
139
|
auth_scopes=auth_scopes,
|
135
|
-
client_id=config.auth.google.client_id,
|
136
|
-
client_secret=config.auth.google.client_secret,
|
140
|
+
client_id=config().auth.google.client_id,
|
141
|
+
client_secret=config().auth.google.client_secret,
|
137
142
|
)
|
@@ -3,13 +3,10 @@ from hyperpocket.auth.gumloop.token_schema import GumloopTokenResponse
|
|
3
3
|
|
4
4
|
|
5
5
|
class GumLoopTokenContext(GumLoopContext):
|
6
|
-
|
7
6
|
@classmethod
|
8
7
|
def from_gumloop_token_response(cls, response: GumloopTokenResponse):
|
9
8
|
description = "Gumloop Token Context logged in"
|
10
9
|
|
11
10
|
return cls(
|
12
|
-
access_token=response.access_token,
|
13
|
-
description=description,
|
14
|
-
expires_at=None
|
11
|
+
access_token=response.access_token, description=description, expires_at=None
|
15
12
|
)
|
@@ -1,9 +1,12 @@
|
|
1
1
|
from typing import Optional
|
2
|
-
from urllib.parse import
|
2
|
+
from urllib.parse import urlencode, urljoin
|
3
3
|
|
4
|
-
from hyperpocket.auth import
|
4
|
+
from hyperpocket.auth import AuthContext, AuthHandlerInterface, AuthProvider
|
5
5
|
from hyperpocket.auth.gumloop.token_context import GumLoopTokenContext
|
6
|
-
from hyperpocket.auth.gumloop.token_schema import
|
6
|
+
from hyperpocket.auth.gumloop.token_schema import (
|
7
|
+
GumloopTokenRequest,
|
8
|
+
GumloopTokenResponse,
|
9
|
+
)
|
7
10
|
from hyperpocket.auth.schema import AuthenticateRequest
|
8
11
|
from hyperpocket.config import config
|
9
12
|
from hyperpocket.futures import FutureStore
|
@@ -11,10 +14,15 @@ from hyperpocket.futures import FutureStore
|
|
11
14
|
|
12
15
|
class GumloopTokenAuthHandler(AuthHandlerInterface):
|
13
16
|
name: str = "gumloop-token"
|
14
|
-
description: str =
|
17
|
+
description: str = (
|
18
|
+
"This handler is used to authenticate users using the gumloop token"
|
19
|
+
)
|
15
20
|
scoped: bool = False
|
16
21
|
|
17
|
-
_TOKEN_URL = urljoin(
|
22
|
+
_TOKEN_URL = urljoin(
|
23
|
+
config().public_base_url + "/",
|
24
|
+
f"{config().callback_url_rewrite_prefix}/auth/token",
|
25
|
+
)
|
18
26
|
|
19
27
|
@staticmethod
|
20
28
|
def provider() -> AuthProvider:
|
@@ -28,25 +36,41 @@ class GumloopTokenAuthHandler(AuthHandlerInterface):
|
|
28
36
|
def recommended_scopes() -> set[str]:
|
29
37
|
return set()
|
30
38
|
|
31
|
-
def make_request(
|
39
|
+
def make_request(
|
40
|
+
self, auth_scopes: Optional[list[str]] = None, **kwargs
|
41
|
+
) -> AuthenticateRequest:
|
32
42
|
return GumloopTokenRequest()
|
33
43
|
|
34
|
-
def prepare(
|
35
|
-
|
44
|
+
def prepare(
|
45
|
+
self,
|
46
|
+
auth_req: AuthenticateRequest,
|
47
|
+
thread_id: str,
|
48
|
+
profile: str,
|
49
|
+
future_uid: str,
|
50
|
+
*args,
|
51
|
+
**kwargs,
|
52
|
+
) -> str:
|
36
53
|
redirect_uri = urljoin(
|
37
|
-
config.public_base_url + "/",
|
38
|
-
f"{config.callback_url_rewrite_prefix}/auth/gumloop/token/callback",
|
54
|
+
config().public_base_url + "/",
|
55
|
+
f"{config().callback_url_rewrite_prefix}/auth/gumloop/token/callback",
|
56
|
+
)
|
57
|
+
auth_url = self._make_auth_url(
|
58
|
+
auth_req=auth_req, redirect_uri=redirect_uri, state=future_uid
|
59
|
+
)
|
60
|
+
FutureStore.create_future(
|
61
|
+
future_uid,
|
62
|
+
data={
|
63
|
+
"redirect_uri": redirect_uri,
|
64
|
+
"thread_id": thread_id,
|
65
|
+
"profile": profile,
|
66
|
+
},
|
39
67
|
)
|
40
|
-
auth_url = self._make_auth_url(auth_req=auth_req, redirect_uri=redirect_uri, state=future_uid)
|
41
|
-
FutureStore.create_future(future_uid, data={
|
42
|
-
"redirect_uri": redirect_uri,
|
43
|
-
"thread_id": thread_id,
|
44
|
-
"profile": profile,
|
45
|
-
})
|
46
68
|
|
47
|
-
return f
|
69
|
+
return f"User needs to authenticate using the following URL: {auth_url}"
|
48
70
|
|
49
|
-
async def authenticate(
|
71
|
+
async def authenticate(
|
72
|
+
self, auth_req: AuthenticateRequest, future_uid: str, *args, **kwargs
|
73
|
+
) -> AuthContext:
|
50
74
|
future_data = FutureStore.get_future(future_uid)
|
51
75
|
access_token = await future_data.future
|
52
76
|
|
@@ -55,10 +79,14 @@ class GumloopTokenAuthHandler(AuthHandlerInterface):
|
|
55
79
|
|
56
80
|
return context
|
57
81
|
|
58
|
-
async def refresh(
|
82
|
+
async def refresh(
|
83
|
+
self, auth_req: AuthenticateRequest, context: AuthContext, *args, **kwargs
|
84
|
+
) -> AuthContext:
|
59
85
|
raise Exception("gumloop token doesn't support refresh")
|
60
86
|
|
61
|
-
def _make_auth_url(
|
87
|
+
def _make_auth_url(
|
88
|
+
self, auth_req: AuthenticateRequest, redirect_uri: str, state: str
|
89
|
+
):
|
62
90
|
params = {
|
63
91
|
"redirect_uri": redirect_uri,
|
64
92
|
"state": state,
|
hyperpocket/auth/handler.py
CHANGED
@@ -11,7 +11,9 @@ from hyperpocket.auth.schema import AuthenticateRequest
|
|
11
11
|
class AuthHandlerInterface(ABC):
|
12
12
|
name: str = Field(description="name of the authentication handler")
|
13
13
|
description: str = Field(description="description of the authentication handler")
|
14
|
-
scoped: bool = Field(
|
14
|
+
scoped: bool = Field(
|
15
|
+
description="Indicates whether the handler requires an auth_scope for access control"
|
16
|
+
)
|
15
17
|
|
16
18
|
@staticmethod
|
17
19
|
def provider() -> AuthProvider:
|
@@ -73,7 +75,9 @@ class AuthHandlerInterface(ABC):
|
|
73
75
|
raise NotImplementedError()
|
74
76
|
|
75
77
|
@abstractmethod
|
76
|
-
def make_request(
|
78
|
+
def make_request(
|
79
|
+
self, auth_scopes: Optional[list[str]] = None, **kwargs
|
80
|
+
) -> AuthenticateRequest:
|
77
81
|
"""
|
78
82
|
Make an AuthenticationRequest.
|
79
83
|
|
@@ -102,8 +106,15 @@ class AuthHandlerInterface(ABC):
|
|
102
106
|
raise NotImplementedError()
|
103
107
|
|
104
108
|
@abstractmethod
|
105
|
-
def prepare(
|
106
|
-
|
109
|
+
def prepare(
|
110
|
+
self,
|
111
|
+
auth_req: AuthenticateRequest,
|
112
|
+
thread_id: str,
|
113
|
+
profile: str,
|
114
|
+
future_uid: str,
|
115
|
+
*args,
|
116
|
+
**kwargs,
|
117
|
+
) -> str:
|
107
118
|
"""
|
108
119
|
Performs preliminary tasks required for authentication.
|
109
120
|
|
@@ -124,7 +135,9 @@ class AuthHandlerInterface(ABC):
|
|
124
135
|
raise NotImplementedError()
|
125
136
|
|
126
137
|
@abstractmethod
|
127
|
-
async def authenticate(
|
138
|
+
async def authenticate(
|
139
|
+
self, auth_req: AuthenticateRequest, future_uid: str, *args, **kwargs
|
140
|
+
) -> AuthContext:
|
128
141
|
"""
|
129
142
|
Performs the actual authentication process.
|
130
143
|
|
@@ -149,7 +162,9 @@ class AuthHandlerInterface(ABC):
|
|
149
162
|
raise NotImplementedError()
|
150
163
|
|
151
164
|
@abstractmethod
|
152
|
-
async def refresh(
|
165
|
+
async def refresh(
|
166
|
+
self, auth_req: AuthenticateRequest, context: AuthContext, *args, **kwargs
|
167
|
+
) -> AuthContext:
|
153
168
|
"""
|
154
169
|
Performs re-authentication for an expired session.
|
155
170
|
|
@@ -3,13 +3,10 @@ from hyperpocket.auth.linear.token_schema import LinearTokenResponse
|
|
3
3
|
|
4
4
|
|
5
5
|
class LinearTokenAuthContext(LinearAuthContext):
|
6
|
-
|
7
6
|
@classmethod
|
8
7
|
def from_linear_token_response(cls, response: LinearTokenResponse):
|
9
|
-
description =
|
8
|
+
description = "Linear Token Context logged in"
|
10
9
|
|
11
10
|
return cls(
|
12
|
-
access_token=response.access_token,
|
13
|
-
description=description,
|
14
|
-
expires_at=None
|
11
|
+
access_token=response.access_token, description=description, expires_at=None
|
15
12
|
)
|