update id
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ requirements.txt
|
||||
.dynamodb_volume/
|
||||
.elastic_volume/
|
||||
.env
|
||||
node_modules/
|
||||
|
||||
@@ -14,7 +14,7 @@ from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
|
||||
from api_gateway import JSONResponse
|
||||
from json_encoder import JSONEncoder
|
||||
from routes import courses, enrollments, orders, users
|
||||
from routes import courses, enrollments, orders, orgs, users
|
||||
|
||||
logger = Logger(__name__)
|
||||
tracer = Tracer()
|
||||
@@ -42,6 +42,7 @@ app.include_router(users.router, prefix='/users')
|
||||
app.include_router(users.emails, prefix='/users')
|
||||
app.include_router(users.orgs, prefix='/users')
|
||||
app.include_router(orders.router, prefix='/orders')
|
||||
app.include_router(orgs.custom_pricing, prefix='/orgs')
|
||||
|
||||
|
||||
@app.exception_handler(ServiceError)
|
||||
|
||||
@@ -51,17 +51,18 @@ class Course(BaseModel):
|
||||
|
||||
|
||||
@router.put('/<course_id>')
|
||||
def edit_course(course_id: str):
|
||||
def put_course(course_id: str):
|
||||
event = router.current_event
|
||||
|
||||
if not event.decoded_body:
|
||||
raise BadRequestError('Invalid request body')
|
||||
|
||||
body = BytesIO(event.decoded_body.encode())
|
||||
course = Course.model_validate(
|
||||
{'id': course_id, 'cert': {}} | parse(event.headers, body),
|
||||
)
|
||||
now_ = now()
|
||||
body = parse(
|
||||
event.headers,
|
||||
BytesIO(event.decoded_body.encode()),
|
||||
)
|
||||
course = Course.model_validate({'id': course_id, 'cert': {}} | body)
|
||||
|
||||
if course.rawfile:
|
||||
object_key = f'certs/templates/{course_id}.html'
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||
from aws_lambda_powertools.event_handler.exceptions import NotFoundError
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, SortKey, TransactKey
|
||||
|
||||
from boto3clients import dynamodb_client
|
||||
from config import ENROLLMENT_TABLE
|
||||
@@ -20,7 +19,6 @@ dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||
|
||||
@router.get('/<enrollment_id>')
|
||||
def get_enrollment(enrollment_id: str):
|
||||
return dyn.collection.get_item(
|
||||
KeyPair(enrollment_id, '0'),
|
||||
exc_cls=NotFoundError,
|
||||
return dyn.collection.get_items(
|
||||
TransactKey(enrollment_id) + SortKey('0') + SortKey('ORG') + SortKey('LOCK'),
|
||||
)
|
||||
|
||||
4
api.saladeaula.digital/app/routes/orgs/__init__.py
Normal file
4
api.saladeaula.digital/app/routes/orgs/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
from .custom_pricing import router as custom_pricing
|
||||
|
||||
__all__ = ['custom_pricing']
|
||||
17
api.saladeaula.digital/app/routes/orgs/custom_pricing.py
Normal file
17
api.saladeaula.digital/app/routes/orgs/custom_pricing.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, PartitionKey
|
||||
|
||||
from boto3clients import dynamodb_client
|
||||
from config import COURSE_TABLE, USER_TABLE
|
||||
|
||||
router = Router()
|
||||
dyn = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)
|
||||
|
||||
|
||||
@router.get('/<org_id>/custompricing')
|
||||
def get_custom_pricing(org_id: str):
|
||||
return dyn.collection.query(
|
||||
PartitionKey(f'CUSTOM_PRICING#ORG#{org_id}'),
|
||||
table_name=COURSE_TABLE,
|
||||
limit=100,
|
||||
)
|
||||
@@ -26,7 +26,7 @@ Globals:
|
||||
Architectures:
|
||||
- x86_64
|
||||
Layers:
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:99
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:100
|
||||
Environment:
|
||||
Variables:
|
||||
TZ: America/Sao_Paulo
|
||||
|
||||
@@ -18,6 +18,7 @@ def pytest_configure():
|
||||
os.environ['TZ'] = 'America/Sao_Paulo'
|
||||
os.environ['COURSE_TABLE'] = PYTEST_TABLE_NAME
|
||||
os.environ['USER_TABLE'] = PYTEST_TABLE_NAME
|
||||
os.environ['ENROLLMENT_TABLE'] = PYTEST_TABLE_NAME
|
||||
os.environ['BUCKET_NAME'] = 'saladeaula.digital'
|
||||
os.environ['DYNAMODB_PARTITION_KEY'] = PK
|
||||
os.environ['DYNAMODB_SORT_KEY'] = SK
|
||||
|
||||
24
api.saladeaula.digital/tests/routes/test_enrollments.py
Normal file
24
api.saladeaula.digital/tests/routes/test_enrollments.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import json
|
||||
from http import HTTPMethod, HTTPStatus
|
||||
|
||||
from ..conftest import HttpApiProxy, LambdaContext
|
||||
|
||||
|
||||
def test_get_enrollment(
|
||||
app,
|
||||
seeds,
|
||||
http_api_proxy: HttpApiProxy,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
r = app.lambda_handler(
|
||||
http_api_proxy(
|
||||
raw_path='/enrollments/578ec87f-94c7-4840-8780-bb4839cc7e64',
|
||||
method=HTTPMethod.GET,
|
||||
),
|
||||
lambda_context,
|
||||
)
|
||||
assert r['statusCode'] == HTTPStatus.OK
|
||||
|
||||
body = json.loads(r['body'])
|
||||
assert 'user' in body
|
||||
assert 'course' in body
|
||||
@@ -4,4 +4,7 @@
|
||||
{"id": "15bacf02-1535-4bee-9022-19d106fd7518", "sk": "emails#sergio@somosbeta.com.br"}
|
||||
|
||||
// User orgs
|
||||
{"id": "213a6682-2c59-4404-9189-12eec0a846d4", "sk": "orgs#286f7729-7765-482a-880a-0b153ea799be", "name": "ACME", "cnpj": "00000000000191"}
|
||||
{"id": "213a6682-2c59-4404-9189-12eec0a846d4", "sk": "orgs#286f7729-7765-482a-880a-0b153ea799be", "name": "ACME", "cnpj": "00000000000191"}
|
||||
|
||||
// Enrollment
|
||||
{"id": "578ec87f-94c7-4840-8780-bb4839cc7e64", "sk": "0", "course": {"id": "af3258f0-bccf-4781-aec6-d4c618d234a7", "name": "pytest", "access_period": 180}, "user": {"id": "068b4600-cc36-4b55-b832-bb620021705a", "name": "Benjamin Burnley", "email": "burnley@breakingbenjamin.com"}}
|
||||
2
api.saladeaula.digital/uv.lock
generated
2
api.saladeaula.digital/uv.lock
generated
@@ -592,7 +592,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "layercake"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = { directory = "../layercake" }
|
||||
dependencies = [
|
||||
{ name = "arnparse" },
|
||||
|
||||
@@ -25,7 +25,7 @@ Globals:
|
||||
Architectures:
|
||||
- x86_64
|
||||
Layers:
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:99
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:100
|
||||
Environment:
|
||||
Variables:
|
||||
TZ: America/Sao_Paulo
|
||||
|
||||
2
http-api/uv.lock
generated
2
http-api/uv.lock
generated
@@ -523,7 +523,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "layercake"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = { directory = "../layercake" }
|
||||
dependencies = [
|
||||
{ name = "arnparse" },
|
||||
|
||||
@@ -76,6 +76,7 @@ class OpenIDCode(OpenIDCode_):
|
||||
).filter(scope)
|
||||
|
||||
if user.scope:
|
||||
# Used to define permission granularity
|
||||
user_info['scope'] = user.scope
|
||||
|
||||
return user_info
|
||||
@@ -247,10 +248,13 @@ class RefreshTokenGrant(grants.RefreshTokenGrant):
|
||||
"""The authorization server MAY revoke the old refresh token after
|
||||
issuing a new refresh token to the client."""
|
||||
|
||||
logger.debug('Revoking old refresh token', refresh_token=refresh_token)
|
||||
token = getattr(refresh_token, 'refresh_token', None)
|
||||
logger.debug('Revoking old refresh token', refresh_token=token)
|
||||
user = refresh_token.get_user()
|
||||
|
||||
if not token:
|
||||
return None
|
||||
|
||||
with dyn.transact_writer() as transact:
|
||||
transact.delete(
|
||||
key=KeyPair(
|
||||
|
||||
@@ -48,11 +48,13 @@ def authorize():
|
||||
if not client_scopes.issubset(user_scopes):
|
||||
raise ForbiddenError('Access denied')
|
||||
|
||||
return server.create_authorization_response(
|
||||
response = server.create_authorization_response(
|
||||
request=router.current_event,
|
||||
grant_user=sub,
|
||||
grant=grant,
|
||||
)
|
||||
|
||||
logger.debug(response)
|
||||
except JoseError as err:
|
||||
logger.exception(err)
|
||||
raise BadRequestError(str(err))
|
||||
@@ -62,6 +64,8 @@ def authorize():
|
||||
status_code=err.status_code,
|
||||
msg=dict(err.get_body()), # type: ignore
|
||||
)
|
||||
else:
|
||||
return response
|
||||
|
||||
|
||||
def _user_scopes(sub: str) -> set:
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||
|
||||
from oauth2 import RevocationEndpoint, server
|
||||
|
||||
logger = Logger(__name__)
|
||||
router = Router()
|
||||
|
||||
|
||||
@router.post('/revoke')
|
||||
def revoke():
|
||||
return server.create_endpoint_response(
|
||||
response = server.create_endpoint_response(
|
||||
RevocationEndpoint.ENDPOINT_NAME,
|
||||
router.current_event,
|
||||
)
|
||||
logger.debug(response)
|
||||
return response
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||
|
||||
from oauth2 import server
|
||||
|
||||
logger = Logger(__name__)
|
||||
router = Router()
|
||||
|
||||
|
||||
@router.post('/token')
|
||||
def issue_token():
|
||||
return server.create_token_response(router.current_event)
|
||||
response = server.create_token_response(router.current_event)
|
||||
logger.debug(response)
|
||||
return response
|
||||
|
||||
@@ -59,7 +59,8 @@ export async function loader({ request, context }: Route.LoaderArgs) {
|
||||
Location: loginUrl.toString()
|
||||
}
|
||||
})
|
||||
} catch {
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return new Response(null, { status: httpStatus.INTERNAL_SERVER })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,8 @@ export async function action({ request, context }: Route.ActionArgs) {
|
||||
status: httpStatus.FOUND,
|
||||
headers
|
||||
})
|
||||
} catch {
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return Response.json({}, { status: httpStatus.INTERNAL_SERVER })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
import type { Route } from './+types'
|
||||
|
||||
export async function action({ request, context }: Route.ActionArgs) {
|
||||
const url = new URL(request.url)
|
||||
const issuerUrl = new URL(url.pathname, context.cloudflare.env.ISSUER_URL)
|
||||
const r = await fetch(issuerUrl.toString(), {
|
||||
method: request.method,
|
||||
headers: request.headers,
|
||||
body: await request.text()
|
||||
})
|
||||
export const loader = proxy
|
||||
export const action = proxy
|
||||
|
||||
return new Response(await r.text(), {
|
||||
status: r.status,
|
||||
headers: r.headers
|
||||
})
|
||||
}
|
||||
|
||||
export async function loader({ request, context }: Route.ActionArgs) {
|
||||
async function proxy({
|
||||
request,
|
||||
context
|
||||
}: Route.ActionArgs): Promise<Response> {
|
||||
const url = new URL(request.url)
|
||||
const issuerUrl = new URL(url.pathname, context.cloudflare.env.ISSUER_URL)
|
||||
const r = await fetch(issuerUrl.toString(), {
|
||||
@@ -23,6 +14,8 @@ export async function loader({ request, context }: Route.ActionArgs) {
|
||||
headers: request.headers
|
||||
})
|
||||
|
||||
console.log('[response]', r)
|
||||
|
||||
return new Response(await r.text(), {
|
||||
status: r.status,
|
||||
headers: r.headers
|
||||
|
||||
@@ -14,7 +14,7 @@ Globals:
|
||||
Architectures:
|
||||
- x86_64
|
||||
Layers:
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:99
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:100
|
||||
Environment:
|
||||
Variables:
|
||||
TZ: America/Sao_Paulo
|
||||
|
||||
@@ -20,7 +20,7 @@ Globals:
|
||||
Architectures:
|
||||
- x86_64
|
||||
Layers:
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:99
|
||||
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:100
|
||||
Environment:
|
||||
Variables:
|
||||
TZ: America/Sao_Paulo
|
||||
|
||||
@@ -1124,6 +1124,7 @@ class DynamoDBCollection:
|
||||
filter_expr: str | None = None,
|
||||
index_forward: bool = False,
|
||||
limit: int = LIMIT,
|
||||
table_name: str | None = None,
|
||||
) -> PaginatedResult:
|
||||
"""Query returns all items with that partition key or key pair.
|
||||
|
||||
@@ -1185,6 +1186,7 @@ class DynamoDBCollection:
|
||||
index_forward=index_forward,
|
||||
limit=limit,
|
||||
start_key=_startkey_b64decode(start_key) if start_key else {},
|
||||
table_name=table_name,
|
||||
)
|
||||
|
||||
items = r['items']
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "layercake"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
description = "Packages shared dependencies to optimize deployment and ensure consistency across functions."
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
|
||||
Reference in New Issue
Block a user