async def post_token(request: web.Request) -> web.Response: """Post to IDP to create a jwt token""" # Proceed as a refresh token handler if query string refresh is available if "refresh" in request.rel_url.query: if not request.headers.get("Authorization"): raise web.HTTPBadRequest( reason="Missing Authorization header for refreshing access token" ) claims = utils.enforce_authorization(request.headers, request.app["settings"]) if not claims.get("refresh_token", False): raise Unauthorized("Token is not a refresh token") else: claims = await authenticate_with_identity_provider(request) response_content: Dict[str, Any] = { "identify_to_kisee": coreapi.Link( action="post", title="Login via login/password pair", description=""" POSTing to this endpoint will identify you by login/password. """, fields=[ coreapi.Field(name="login", required=True), coreapi.Field(name="password", required=True), ], url="/tokens/?idp=kisee", ) } if "sub" in claims: storage_backend = request.app["storage_backend"] if not await storage_backend.user_exists(claims["sub"]): await storage_backend.create_user(claims["sub"]) claims["groups"] = await storage_backend.get_authorizations_for_user( claims["sub"] ) access_token, refresh_token = generate_access_token_and_refresh_token_pairs( claims, request.app["settings"]["private_key"], algorithm=request.app["settings"]["algorithm"], ) response_content["access_token"] = access_token response_content["refresh_token"] = refresh_token else: response_content["authorize_url"] = claims["authorize_url"] return serialize( request, coreapi.Document( url="/tokens/", title="Create a token with Identify Provider", content=response_content, ), headers={"Cache-Control": "no-store", "Pragma": "no-cache"}, status=201, )
async def get_user(request: web.Request) -> web.Response: """Handlers for GET /users/{username} List groups of {username} """ hostname = request.app["settings"]["hostname"] username = request.match_info["username"] claims = utils.enforce_authorization(request.headers, request.app["settings"]) if not is_root( claims["groups"]) and not claims["sub"] == username: # is user raise web.HTTPForbidden(reason="Do not have rights to view user info") last_element = request.rel_url.query.get("last_element", "") user = await request.app["storage_backend"].get_user(username) if not user: raise web.HTTPNotFound(reason="User does not exist") groups = await request.app["storage_backend"].get_groups_of_user( username, last_element) content = user content["patch"] = coreapi.Link( action="patch", title="Patch fields of user", description="A method to patch fields of user", fields=[coreapi.Field(name="is_banned")], ) if groups: content["next"] = coreapi.Link( url=f"{hostname}/users/{username}?last_element={groups[-1]}") content["groups"] = [ coreapi.Document(url=f"{hostname}/groups/{group}/", content={"group": group}) for group in groups ] return serialize( request, coreapi.Document(url=f"{hostname}/users/{username}", title="User interface", content=content), headers={"Vary": "Origin"}, )
async def get_groups(request: web.Request) -> web.Response: """Handlers for GET /groups/""" hostname = request.app["settings"]["hostname"] errors, groups = await _get_groups(request) content = { "groups": [ coreapi.Document(url=f"{hostname}/groups/{group}/", content={"group": group}) for group in groups ], "create_group": coreapi.Link( action="post", title="Create a group", description="A method to create a group by a staff member", fields=[coreapi.Field(name="group", required=True)], ), "get_groups_of_user": coreapi.Link( action="get", title="Get groups of user", description="Get list of groups of a user", url=f"{hostname}/groups/{{?user}}", ), "errors": errors, } if groups: content["next"] = coreapi.Link( url=f"{hostname}/groups/?last_element={groups[-1]}") return serialize( request, coreapi.Document( url=f"{hostname}/groups/", title="Groups of Identity Manager", content=content, ), headers={"Vary": "Origin"}, )
async def get_tokens(request: web.Request) -> web.Response: """Handlers for GET /token/, just describes that a POST is possible.""" hostname = request.app["settings"]["hostname"] access_token, refresh_token = None, None identity_provider_input = request.rel_url.query.get("idp", None) if identity_provider_input: access_token, refresh_token = await handle_oauth_callback( identity_provider_input, request ) idps = {} for idp_name, idp_conf in request.app["settings"]["idps"].items(): fields: List[coreapi.Field] = [] if idp_conf.get("input_fields"): fields = [ coreapi.Field(name=field.get("name"), required=field.get("required")) for field in idp_conf["input_fields"] ] idps[f"identify_via_{idp_name}"] = coreapi.Link( action="post", title=idp_conf.get("title"), description=idp_conf.get("description"), fields=fields, url=f"/tokens/?idp={idp_name}", ) return serialize( request, coreapi.Document( url=f"{hostname}/token", title="Request Token From Identity Provider", content={ "access_token": access_token, "refresh_token": refresh_token, **idps, }, ), )
async def get_group(request: web.Request) -> web.Response: """Handler for GET /groups/{group_uid}""" hostname = request.app["settings"]["hostname"] claims = utils.enforce_authorization(request.headers, request.app["settings"]) storage_backend = request.app["storage_backend"] group = request.match_info["group_uid"] if not is_authorized_for_group(claims["groups"], group): raise web.HTTPForbidden(reason="Not authorized to view group") if not await storage_backend.group_exists(group): raise web.HTTPNotFound(reason="Group does not exist") members = await storage_backend.get_members_of_group(group) return serialize( request, coreapi.Document( url=f"{hostname}/groups/{{group}}/", title=f"{group} group management interface", content={ "members": [ coreapi.Document(url=f"{hostname}/users/{member}", content={"username": member}) for member in members ], "add_member": coreapi.Link( action="post", title="Add a member to group", description="A method to add a member to group", fields=[coreapi.Field(name="username", required=True)], ), }, ), headers={"Vary": "Origin"}, )