|
13 | 13 | # under the License.
|
14 | 14 | from __future__ import annotations
|
15 | 15 |
|
16 |
| -import re |
17 | 16 | from os import environ
|
18 | 17 | from typing import TYPE_CHECKING, Awaitable, Callable, List, Optional, Union, Dict, Any
|
19 | 18 |
|
20 | 19 | from supertokens_python.normalised_url_path import NormalisedURLPath
|
21 |
| -from supertokens_python.recipe_module import APIHandled, RecipeModule, ApiIdWithTenantId |
| 20 | +from supertokens_python.recipe_module import APIHandled, RecipeModule |
22 | 21 |
|
23 | 22 | from .api import (
|
24 | 23 | api_key_protector,
|
|
47 | 46 | from .exceptions import SuperTokensDashboardError
|
48 | 47 | from .interfaces import APIInterface, APIOptions
|
49 | 48 | from .recipe_implementation import RecipeImplementation
|
50 |
| -from ..multitenancy.constants import DEFAULT_TENANT_ID |
51 | 49 |
|
52 | 50 | if TYPE_CHECKING:
|
53 | 51 | from supertokens_python.framework.request import BaseRequest
|
|
56 | 54 | from supertokens_python.types import APIResponse
|
57 | 55 |
|
58 | 56 | from supertokens_python.exceptions import SuperTokensError, raise_general_exception
|
59 |
| -from supertokens_python.recipe.multitenancy.recipe import MultitenancyRecipe |
| 57 | +from supertokens_python.recipe.dashboard.utils import get_api_path_with_dashboard_base |
60 | 58 |
|
61 | 59 | from .constants import (
|
62 | 60 | DASHBOARD_ANALYTICS_API,
|
|
77 | 75 | )
|
78 | 76 | from .utils import (
|
79 | 77 | InputOverrideConfig,
|
80 |
| - get_api_if_matched, |
81 |
| - is_api_path, |
82 | 78 | validate_and_normalise_user_input,
|
83 | 79 | )
|
84 | 80 |
|
@@ -119,14 +115,140 @@ def is_error_from_this_recipe_based_on_instance(self, err: Exception) -> bool:
|
119 | 115 | )
|
120 | 116 |
|
121 | 117 | def get_apis_handled(self) -> List[APIHandled]:
|
122 |
| - # Normally this array is used by the SDK to decide whether the recipe |
123 |
| - # handles a specific API path and method and then returns the ID. |
124 |
| - |
125 |
| - # However, for the dashboard recipe this logic is fully custom and handled inside the |
126 |
| - # `return_api_id_if_can_handle_request` method of this class. Since this array is never |
127 |
| - # used for this recipe, we simply return an empty array. |
128 |
| - |
129 |
| - return [] |
| 118 | + return [ |
| 119 | + APIHandled( |
| 120 | + NormalisedURLPath(get_api_path_with_dashboard_base("/")), |
| 121 | + "get", |
| 122 | + DASHBOARD_API, |
| 123 | + False, |
| 124 | + ), |
| 125 | + APIHandled( |
| 126 | + NormalisedURLPath( |
| 127 | + get_api_path_with_dashboard_base(EMAIL_PASSWORD_SIGN_IN) |
| 128 | + ), |
| 129 | + "post", |
| 130 | + EMAIL_PASSWORD_SIGN_IN, |
| 131 | + False, |
| 132 | + ), |
| 133 | + APIHandled( |
| 134 | + NormalisedURLPath(get_api_path_with_dashboard_base(VALIDATE_KEY_API)), |
| 135 | + "post", |
| 136 | + VALIDATE_KEY_API, |
| 137 | + False, |
| 138 | + ), |
| 139 | + APIHandled( |
| 140 | + NormalisedURLPath( |
| 141 | + get_api_path_with_dashboard_base(EMAIL_PASSSWORD_SIGNOUT) |
| 142 | + ), |
| 143 | + "post", |
| 144 | + EMAIL_PASSSWORD_SIGNOUT, |
| 145 | + False, |
| 146 | + ), |
| 147 | + APIHandled( |
| 148 | + NormalisedURLPath(get_api_path_with_dashboard_base(USERS_LIST_GET_API)), |
| 149 | + "get", |
| 150 | + USERS_LIST_GET_API, |
| 151 | + False, |
| 152 | + ), |
| 153 | + APIHandled( |
| 154 | + NormalisedURLPath(get_api_path_with_dashboard_base(USERS_COUNT_API)), |
| 155 | + "get", |
| 156 | + USERS_COUNT_API, |
| 157 | + False, |
| 158 | + ), |
| 159 | + APIHandled( |
| 160 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_API)), |
| 161 | + "get", |
| 162 | + USER_API, |
| 163 | + False, |
| 164 | + ), |
| 165 | + APIHandled( |
| 166 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_API)), |
| 167 | + "post", |
| 168 | + USER_API, |
| 169 | + False, |
| 170 | + ), |
| 171 | + APIHandled( |
| 172 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_API)), |
| 173 | + "put", |
| 174 | + USER_API, |
| 175 | + False, |
| 176 | + ), |
| 177 | + APIHandled( |
| 178 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_API)), |
| 179 | + "delete", |
| 180 | + USER_API, |
| 181 | + False, |
| 182 | + ), |
| 183 | + APIHandled( |
| 184 | + NormalisedURLPath( |
| 185 | + get_api_path_with_dashboard_base(USER_EMAIL_VERIFY_API) |
| 186 | + ), |
| 187 | + "get", |
| 188 | + USER_EMAIL_VERIFY_API, |
| 189 | + False, |
| 190 | + ), |
| 191 | + APIHandled( |
| 192 | + NormalisedURLPath( |
| 193 | + get_api_path_with_dashboard_base(USER_EMAIL_VERIFY_API) |
| 194 | + ), |
| 195 | + "put", |
| 196 | + USER_EMAIL_VERIFY_API, |
| 197 | + False, |
| 198 | + ), |
| 199 | + APIHandled( |
| 200 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_METADATA_API)), |
| 201 | + "get", |
| 202 | + USER_METADATA_API, |
| 203 | + False, |
| 204 | + ), |
| 205 | + APIHandled( |
| 206 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_METADATA_API)), |
| 207 | + "put", |
| 208 | + USER_METADATA_API, |
| 209 | + False, |
| 210 | + ), |
| 211 | + APIHandled( |
| 212 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_SESSION_API)), |
| 213 | + "get", |
| 214 | + USER_SESSION_API, |
| 215 | + False, |
| 216 | + ), |
| 217 | + APIHandled( |
| 218 | + NormalisedURLPath(get_api_path_with_dashboard_base(USER_PASSWORD_API)), |
| 219 | + "put", |
| 220 | + USER_PASSWORD_API, |
| 221 | + False, |
| 222 | + ), |
| 223 | + APIHandled( |
| 224 | + NormalisedURLPath( |
| 225 | + get_api_path_with_dashboard_base(USER_EMAIL_VERIFY_API) |
| 226 | + ), |
| 227 | + "post", |
| 228 | + USER_EMAIL_VERIFY_API, |
| 229 | + False, |
| 230 | + ), |
| 231 | + APIHandled( |
| 232 | + NormalisedURLPath(get_api_path_with_dashboard_base(SEARCH_TAGS_API)), |
| 233 | + "get", |
| 234 | + SEARCH_TAGS_API, |
| 235 | + False, |
| 236 | + ), |
| 237 | + APIHandled( |
| 238 | + NormalisedURLPath( |
| 239 | + get_api_path_with_dashboard_base(DASHBOARD_ANALYTICS_API) |
| 240 | + ), |
| 241 | + "post", |
| 242 | + DASHBOARD_ANALYTICS_API, |
| 243 | + False, |
| 244 | + ), |
| 245 | + APIHandled( |
| 246 | + NormalisedURLPath(get_api_path_with_dashboard_base(TENANTS_LIST_API)), |
| 247 | + "get", |
| 248 | + TENANTS_LIST_API, |
| 249 | + False, |
| 250 | + ), |
| 251 | + ] |
130 | 252 |
|
131 | 253 | async def handle_api_request(
|
132 | 254 | self,
|
@@ -261,70 +383,3 @@ def reset():
|
261 | 383 | ):
|
262 | 384 | raise_general_exception("calling testing function in non testing env")
|
263 | 385 | DashboardRecipe.__instance = None
|
264 |
| - |
265 |
| - async def return_api_id_if_can_handle_request( |
266 |
| - self, path: NormalisedURLPath, method: str, user_context: Dict[str, Any] |
267 |
| - ) -> Union[ApiIdWithTenantId, None]: |
268 |
| - dashboard_bundle_path = self.app_info.api_base_path.append( |
269 |
| - NormalisedURLPath(DASHBOARD_API) |
270 |
| - ) |
271 |
| - |
272 |
| - base_path_str = self.app_info.api_base_path.get_as_string_dangerous() |
273 |
| - path_str = path.get_as_string_dangerous() |
274 |
| - regex = rf"^{base_path_str}(?:/([a-zA-Z0-9-]+))?(/.*)$" |
275 |
| - # some examples against for above regex: |
276 |
| - # books => match = None |
277 |
| - # public/books => match = None |
278 |
| - # /books => match.group(1) = None, match.group(2) = /dashboard |
279 |
| - # /public/books => match.group(1) = 'public', match.group(2) = '/books' |
280 |
| - # /public/book/1 => match.group(1) = 'public', match.group(2) = '/book/1' |
281 |
| - |
282 |
| - match = re.match(regex, path_str) |
283 |
| - match_group_1 = match.group(1) if match is not None else None |
284 |
| - match_group_2 = match.group(2) if match is not None else None |
285 |
| - |
286 |
| - tenant_id: str = DEFAULT_TENANT_ID |
287 |
| - remaining_path: Optional[NormalisedURLPath] = None |
288 |
| - |
289 |
| - if ( |
290 |
| - match is not None |
291 |
| - and isinstance(match_group_1, str) |
292 |
| - and isinstance(match_group_2, str) |
293 |
| - ): |
294 |
| - tenant_id = match_group_1 |
295 |
| - remaining_path = NormalisedURLPath(match_group_2) |
296 |
| - |
297 |
| - mt_recipe = MultitenancyRecipe.get_instance() |
298 |
| - |
299 |
| - if is_api_path(path, self.app_info.api_base_path) or ( |
300 |
| - remaining_path is not None |
301 |
| - and is_api_path( |
302 |
| - path, |
303 |
| - self.app_info.api_base_path.append(NormalisedURLPath(f"/{tenant_id}")), |
304 |
| - ) |
305 |
| - ): |
306 |
| - # check remainingPath first as path that contains tenantId might match as well |
307 |
| - # since getApiIdIfMatched uses endsWith to match |
308 |
| - if remaining_path is not None: |
309 |
| - id_ = get_api_if_matched(remaining_path, method) |
310 |
| - if id_ is not None: |
311 |
| - final_tenant_id = ( |
312 |
| - await mt_recipe.recipe_implementation.get_tenant_id( |
313 |
| - DEFAULT_TENANT_ID if tenant_id is None else tenant_id, |
314 |
| - user_context, |
315 |
| - ) |
316 |
| - ) |
317 |
| - return ApiIdWithTenantId(id_, final_tenant_id) |
318 |
| - |
319 |
| - id_ = get_api_if_matched(path, method) |
320 |
| - if id_ is not None: |
321 |
| - final_tenant_id = await mt_recipe.recipe_implementation.get_tenant_id( |
322 |
| - DEFAULT_TENANT_ID, user_context |
323 |
| - ) |
324 |
| - return ApiIdWithTenantId(id_, final_tenant_id) |
325 |
| - |
326 |
| - if path.startswith(dashboard_bundle_path): |
327 |
| - return ApiIdWithTenantId(DASHBOARD_API, DEFAULT_TENANT_ID) |
328 |
| - |
329 |
| - # tenantId is not supported for bundlePath, so not matching for it |
330 |
| - return None |
|
0 commit comments