Bases: Base
, GUIDPk
, Timestamped
, UserColumn
, TenantColumn
username
class-attribute
instance-attribute
username = acol(storage=S(String(120), nullable=False))
auth_time
class-attribute
instance-attribute
auth_time = acol(
storage=S(
TZDateTime, nullable=False, default=lambda: now(utc)
)
)
created_at
class-attribute
instance-attribute
created_at = acol(
spec=ColumnSpec(
storage=S(
type_=TZDateTime,
default=tzutcnow,
nullable=False,
),
field=F(py_type=datetime),
io=RO_IO,
)
)
updated_at
class-attribute
instance-attribute
updated_at = acol(
spec=ColumnSpec(
storage=S(
type_=TZDateTime,
default=tzutcnow,
onupdate=tzutcnow,
nullable=False,
),
field=F(py_type=datetime),
io=RO_IO,
)
)
id
class-attribute
instance-attribute
id = acol(
spec=ColumnSpec(
storage=S(
type_=PgUUID(as_uuid=True),
primary_key=True,
default=uuid4,
),
field=F(
py_type=UUID,
constraints={"examples": [uuid_example]},
),
io=RO_IO,
)
)
metadata = MetaData(
naming_convention={
"pk": "pk_%(table_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"ix": "ix_%(table_name)s_%(column_0_name)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s_%(constraint_type)s",
}
)
login
async
Source code in tigrbl_auth/orm/auth_session.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 | @op_ctx(
alias="login",
target="create",
arity="collection",
request_schema=CredsIn,
response_schema=TokenPair,
)
async def login(cls, ctx):
import secrets
from ..rfc.rfc8414_metadata import ISSUER
from ..oidc_id_token import mint_id_token
from ..routers.shared import _jwt, _require_tls
request = ctx.get("request")
_require_tls(request)
payload = ctx.get("payload") or {}
session = await cls.handlers.create.core(
{"payload": payload, "db": ctx.get("db")}
)
access, refresh = await _jwt.async_sign_pair(
sub=str(session.user_id),
tid=str(session.tenant_id),
scope="openid profile email",
)
id_token = await mint_id_token(
sub=str(session.user_id),
aud=ISSUER,
nonce=secrets.token_urlsafe(8),
issuer=ISSUER,
sid=str(session.id),
)
pair = {
"access_token": access,
"refresh_token": refresh,
"id_token": id_token,
}
response = JSONResponse(pair)
response.set_cookie("sid", str(session.id), httponly=True, samesite="lax")
return response
|
logout
async
Source code in tigrbl_auth/orm/auth_session.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 | @op_ctx(
alias="logout",
target="delete",
arity="collection",
request_schema=LogoutIn,
status_code=status.HTTP_204_NO_CONTENT,
)
async def logout(cls, ctx):
from ..rfc.rfc8414_metadata import ISSUER
from ..oidc_id_token import verify_id_token
from ..routers.shared import (
_require_tls,
_front_channel_logout,
_back_channel_logout,
)
request = ctx.get("request")
_require_tls(request)
payload = ctx.get("payload") or {}
id_hint = payload.get("id_token_hint")
try:
claims = await verify_id_token(id_hint, issuer=ISSUER, audience=ISSUER)
except Exception as exc: # pragma: no cover - passthrough
raise HTTPException(
status.HTTP_400_BAD_REQUEST, "invalid id_token_hint"
) from exc
sid = claims.get("sid")
if sid:
session = await cls.handlers.read.core({"payload": {"id": UUID(sid)}})
if session:
await cls.handlers.delete.core({"obj": session})
await _front_channel_logout(sid)
await _back_channel_logout(sid)
response = Response(status_code=status.HTTP_204_NO_CONTENT)
response.delete_cookie("sid")
return response
|
tenant_id
Source code in tigrbl/orm/mixins/principals.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44 | @declared_attr
def tenant_id(cls) -> Mapped[UUID]:
schema = getattr(cls, "__tenant_table_schema__", None) or _infer_schema(cls)
spec = ColumnSpec(
storage=S(
type_=PgUUID(as_uuid=True),
fk=ForeignKeySpec(target=f"{schema}.tenants.id"),
nullable=False,
index=True,
),
field=F(py_type=UUID, constraints={"examples": [uuid_example]}),
io=CRUD_IO,
)
return acol(spec=spec)
|
user_id
Source code in tigrbl/orm/mixins/principals.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64 | @declared_attr
def user_id(cls) -> Mapped[UUID]:
schema = getattr(cls, "__user_table_schema__", None) or _infer_schema(cls)
spec = ColumnSpec(
storage=S(
type_=PgUUID(as_uuid=True),
fk=ForeignKeySpec(target=f"{schema}.users.id"),
nullable=False,
index=True,
),
field=F(py_type=UUID, constraints={"examples": [uuid_example]}),
io=CRUD_IO,
)
return acol(spec=spec)
|