check issue permission
This commit is contained in:
parent
2d39c4aaa3
commit
d8bdb46a5c
4 changed files with 51 additions and 15 deletions
|
@ -23,7 +23,6 @@ class DeviceBase(SQLModel):
|
|||
|
||||
name: str
|
||||
type: str
|
||||
expiry: datetime | None
|
||||
|
||||
|
||||
class DeviceCreate(DeviceBase):
|
||||
|
@ -37,11 +36,13 @@ class DeviceRead(DeviceBase):
|
|||
Representation of a device read via the API
|
||||
"""
|
||||
|
||||
approved: bool
|
||||
owner_name: str | None
|
||||
id: int | None = Field(primary_key=True)
|
||||
approved: bool | None = Field(default=None)
|
||||
expiry: datetime | None = Field(default=None)
|
||||
owner_name: str = Field(foreign_key="user.name")
|
||||
|
||||
|
||||
class Device(DeviceBase, table=True):
|
||||
class Device(DeviceRead, table=True):
|
||||
"""
|
||||
Representation of `device` table
|
||||
"""
|
||||
|
@ -51,10 +52,6 @@ class Device(DeviceBase, table=True):
|
|||
"name",
|
||||
),)
|
||||
|
||||
id: int | None = Field(primary_key=True)
|
||||
approved: bool = Field(default=False)
|
||||
owner_name: str | None = Field(foreign_key="user.name")
|
||||
|
||||
# no idea, but "User" (in quotes) doesn't work here
|
||||
# might be a future problem?
|
||||
owner: User = Relationship(
|
||||
|
@ -74,8 +71,7 @@ class Device(DeviceBase, table=True):
|
|||
|
||||
try:
|
||||
with Connection.session as db:
|
||||
new_device = cls.from_orm(device)
|
||||
new_device.owner = owner
|
||||
new_device = cls.from_orm(device, {"owner_name": owner.name})
|
||||
|
||||
db.add(new_device)
|
||||
db.commit()
|
||||
|
|
|
@ -281,3 +281,23 @@ class User(UserBase, table=True):
|
|||
|
||||
# deny be default
|
||||
return False
|
||||
|
||||
def can_issue(self, device: Device) -> bool:
|
||||
"""
|
||||
Check if this user can issue a certificate without approval.
|
||||
"""
|
||||
|
||||
return (
|
||||
device.approved in (None, False)
|
||||
and (self.is_admin or self.has_tag(TagValue.issue))
|
||||
)
|
||||
|
||||
def can_renew(self, device: Device) -> bool:
|
||||
"""
|
||||
Check if this user can renew a certificate without approval.
|
||||
"""
|
||||
|
||||
return (
|
||||
device.approved is True
|
||||
and (self.is_admin or self.has_tag(TagValue.renew))
|
||||
)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
/device endpoints.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
from ..db import Connection, Device, DeviceCreate, DeviceRead, User
|
||||
|
@ -106,7 +108,20 @@ async def request_certificate(
|
|||
db.add(device)
|
||||
dn = DistinguishedName.build(device)
|
||||
|
||||
easy_rsa.issue(
|
||||
if current_user.can_issue(device):
|
||||
device.approved = True
|
||||
|
||||
if (cert := easy_rsa.issue(
|
||||
dn=dn,
|
||||
cert_type=CertificateType.server,
|
||||
)) is not None:
|
||||
assert (expiry := cert.get_notAfter()) is not None
|
||||
|
||||
date_format, encoding = "%Y%m%d%H%M%SZ", "ascii"
|
||||
expiry = datetime.strptime(
|
||||
expiry.decode(encoding),
|
||||
date_format,
|
||||
)
|
||||
device.expiry = expiry
|
||||
|
||||
db.commit()
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
- approved: bool
|
||||
- expiry
|
||||
|
||||
## Device status
|
||||
- created (approved = NULL): device has been newly created
|
||||
- requested (approved = false): certificate has been requested (issue or renew)
|
||||
- issued (approved = true): certificate has been granted (may be expired)
|
||||
|
||||
## Permissions
|
||||
- admin cannot "admin" itself (to prevent self decapitation)
|
||||
- admin can "edit", "admin" and "create" everything else
|
||||
|
@ -37,5 +42,5 @@
|
|||
- admin: add or remove tag, delete, generate password
|
||||
|
||||
### Device
|
||||
- edit: change type, delete
|
||||
- edit: change type, delete, request
|
||||
- admin: approve
|
||||
|
|
Loading…
Reference in a new issue