paskia 0.7.2__py3-none-any.whl → 0.8.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.
- paskia/_version.py +2 -2
- paskia/authsession.py +12 -49
- paskia/bootstrap.py +30 -25
- paskia/db/__init__.py +163 -401
- paskia/db/background.py +128 -0
- paskia/db/jsonl.py +132 -0
- paskia/db/operations.py +1241 -0
- paskia/db/structs.py +148 -0
- paskia/fastapi/admin.py +456 -215
- paskia/fastapi/api.py +16 -15
- paskia/fastapi/authz.py +7 -2
- paskia/fastapi/mainapp.py +2 -1
- paskia/fastapi/remote.py +20 -20
- paskia/fastapi/reset.py +9 -10
- paskia/fastapi/user.py +10 -18
- paskia/fastapi/ws.py +22 -19
- paskia/frontend-build/auth/admin/index.html +3 -3
- paskia/frontend-build/auth/assets/AccessDenied-aTdCvz9k.js +8 -0
- paskia/frontend-build/auth/assets/admin-BeNu48FR.css +1 -0
- paskia/frontend-build/auth/assets/admin-tVs8oyLv.js +1 -0
- paskia/frontend-build/auth/assets/{auth-BU_O38k2.css → auth-BKX7shEe.css} +1 -1
- paskia/frontend-build/auth/assets/auth-Dk3q4pNS.js +1 -0
- paskia/frontend-build/auth/index.html +3 -3
- paskia/globals.py +7 -10
- paskia/migrate/__init__.py +274 -0
- paskia/migrate/sql.py +381 -0
- paskia/util/permutil.py +16 -5
- paskia/util/sessionutil.py +3 -2
- paskia/util/userinfo.py +12 -26
- {paskia-0.7.2.dist-info → paskia-0.8.0.dist-info}/METADATA +21 -25
- {paskia-0.7.2.dist-info → paskia-0.8.0.dist-info}/RECORD +33 -29
- {paskia-0.7.2.dist-info → paskia-0.8.0.dist-info}/entry_points.txt +1 -0
- paskia/db/sql.py +0 -1424
- paskia/frontend-build/auth/assets/AccessDenied-C-lL9vbN.js +0 -8
- paskia/frontend-build/auth/assets/admin-Cs6Mg773.css +0 -1
- paskia/frontend-build/auth/assets/admin-Df5_Damp.js +0 -1
- paskia/frontend-build/auth/assets/auth-Df3pjeSS.js +0 -1
- paskia/util/tokens.py +0 -44
- {paskia-0.7.2.dist-info → paskia-0.8.0.dist-info}/WHEEL +0 -0
paskia/db/structs.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
|
|
4
|
+
import msgspec
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Permission(msgspec.Struct, omit_defaults=True):
|
|
8
|
+
uuid: UUID # UUID primary key
|
|
9
|
+
scope: str # Permission scope identifier (e.g. "auth:admin", "myapp:write")
|
|
10
|
+
display_name: str
|
|
11
|
+
domain: str | None = None # If set, scopes permission to this domain
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Role(msgspec.Struct):
|
|
15
|
+
uuid: UUID
|
|
16
|
+
org_uuid: UUID
|
|
17
|
+
display_name: str
|
|
18
|
+
permissions: list[str] = [] # permission UUIDs this role grants
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Org(msgspec.Struct):
|
|
22
|
+
uuid: UUID
|
|
23
|
+
display_name: str
|
|
24
|
+
permissions: list[str] = [] # permission UUIDs this org can grant
|
|
25
|
+
roles: list[Role] = [] # roles belonging to this org
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class User(msgspec.Struct):
|
|
29
|
+
uuid: UUID
|
|
30
|
+
display_name: str
|
|
31
|
+
role_uuid: UUID
|
|
32
|
+
created_at: datetime | None = None
|
|
33
|
+
last_seen: datetime | None = None
|
|
34
|
+
visits: int = 0
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Credential(msgspec.Struct):
|
|
38
|
+
uuid: UUID
|
|
39
|
+
credential_id: bytes # Long binary ID from the authenticator
|
|
40
|
+
user_uuid: UUID
|
|
41
|
+
aaguid: UUID
|
|
42
|
+
public_key: bytes
|
|
43
|
+
sign_count: int
|
|
44
|
+
created_at: datetime
|
|
45
|
+
last_used: datetime | None = None
|
|
46
|
+
last_verified: datetime | None = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Session(msgspec.Struct):
|
|
50
|
+
key: str
|
|
51
|
+
user_uuid: UUID
|
|
52
|
+
credential_uuid: UUID
|
|
53
|
+
host: str | None
|
|
54
|
+
ip: str | None
|
|
55
|
+
user_agent: str | None
|
|
56
|
+
expiry: datetime
|
|
57
|
+
|
|
58
|
+
def metadata(self) -> dict:
|
|
59
|
+
"""Return session metadata for backwards compatibility."""
|
|
60
|
+
return {
|
|
61
|
+
"ip": self.ip,
|
|
62
|
+
"user_agent": self.user_agent,
|
|
63
|
+
"expiry": self.expiry.isoformat(),
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ResetToken(msgspec.Struct):
|
|
68
|
+
key: bytes
|
|
69
|
+
user_uuid: UUID
|
|
70
|
+
expiry: datetime
|
|
71
|
+
token_type: str
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class SessionContext(msgspec.Struct):
|
|
75
|
+
session: Session
|
|
76
|
+
user: User
|
|
77
|
+
org: Org
|
|
78
|
+
role: Role
|
|
79
|
+
credential: Credential | None = None
|
|
80
|
+
permissions: list[Permission] | None = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# -------------------------------------------------------------------------
|
|
84
|
+
# Internal storage types (different structure for efficient storage)
|
|
85
|
+
# -------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class _PermissionData(msgspec.Struct, omit_defaults=True):
|
|
89
|
+
scope: str # Permission scope identifier
|
|
90
|
+
display_name: str
|
|
91
|
+
domain: str | None = None
|
|
92
|
+
orgs: dict[UUID, bool] = {} # org_uuid -> True (which orgs can grant this)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class _OrgData(msgspec.Struct):
|
|
96
|
+
display_name: str
|
|
97
|
+
created_at: datetime | None = None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class _RoleData(msgspec.Struct):
|
|
101
|
+
org: UUID
|
|
102
|
+
display_name: str
|
|
103
|
+
permissions: dict[UUID, bool] = {} # permission_uuid -> True
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class _UserData(msgspec.Struct):
|
|
107
|
+
display_name: str
|
|
108
|
+
role: UUID
|
|
109
|
+
created_at: datetime
|
|
110
|
+
last_seen: datetime | None
|
|
111
|
+
visits: int
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class _CredentialData(msgspec.Struct):
|
|
115
|
+
credential_id: bytes
|
|
116
|
+
user: UUID
|
|
117
|
+
aaguid: UUID
|
|
118
|
+
public_key: bytes
|
|
119
|
+
sign_count: int
|
|
120
|
+
created_at: datetime
|
|
121
|
+
last_used: datetime | None
|
|
122
|
+
last_verified: datetime | None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class _SessionData(msgspec.Struct):
|
|
126
|
+
user: UUID
|
|
127
|
+
credential: UUID
|
|
128
|
+
host: str | None
|
|
129
|
+
ip: str | None
|
|
130
|
+
user_agent: str | None
|
|
131
|
+
expiry: datetime
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class _ResetTokenData(msgspec.Struct):
|
|
135
|
+
user: UUID
|
|
136
|
+
expiry: datetime
|
|
137
|
+
token_type: str
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class _DatabaseData(msgspec.Struct, omit_defaults=True):
|
|
141
|
+
permissions: dict[UUID, _PermissionData]
|
|
142
|
+
orgs: dict[UUID, _OrgData]
|
|
143
|
+
roles: dict[UUID, _RoleData]
|
|
144
|
+
users: dict[UUID, _UserData]
|
|
145
|
+
credentials: dict[UUID, _CredentialData]
|
|
146
|
+
sessions: dict[str, _SessionData]
|
|
147
|
+
reset_tokens: dict[bytes, _ResetTokenData]
|
|
148
|
+
v: int = 0
|