This commit is contained in:
Jörn-Michael Miehe 2022-03-25 15:50:45 +00:00
parent 972359cb49
commit 1ed3b587c7
4 changed files with 111 additions and 63 deletions

View file

@ -14,34 +14,6 @@ from sqlalchemy.orm import Session, relationship
ORMBaseModel = declarative_base() ORMBaseModel = declarative_base()
class User(ORMBaseModel):
__tablename__ = "users"
name = Column(String, primary_key=True, index=True)
password = Column(String, nullable=False)
capabilities: list[UserCapability] = relationship(
"UserCapability", lazy="joined", cascade="all, delete-orphan"
)
certificates: list[Certificate] = relationship(
"Certificate", lazy="select", back_populates="owner"
)
distinguished_names: list[DistinguishedName] = relationship(
"DistinguishedName", lazy="select", back_populates="owner"
)
@classmethod
def load(cls, db: Session, name: str) -> User | None:
"""
Load user from database by name.
"""
return (db
.query(User)
.filter(User.name == name)
.first())
class UserCapability(ORMBaseModel): class UserCapability(ORMBaseModel):
__tablename__ = "user_capabilities" __tablename__ = "user_capabilities"
@ -54,53 +26,43 @@ class UserCapability(ORMBaseModel):
capability = Column(String, primary_key=True) capability = Column(String, primary_key=True)
class DistinguishedName(ORMBaseModel): class User(ORMBaseModel):
__tablename__ = "distinguished_names" __tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String, primary_key=True, index=True)
password = Column(String, nullable=False)
owner_name = Column(String, ForeignKey("users.name"))
cn_only = Column(Boolean, default=True, nullable=False)
country = Column(String(2)) country = Column(String(2))
state = Column(String) state = Column(String)
city = Column(String) city = Column(String)
organization = Column(String) organization = Column(String)
organizational_unit = Column(String) organizational_unit = Column(String)
email = Column(String) email = Column(String)
common_name = Column(String, nullable=False)
capabilities: list[UserCapability] = relationship(
"UserCapability", lazy="joined", cascade="all, delete-orphan"
)
devices: list[Device] = relationship(
"Device", lazy="select", back_populates="owner"
)
class Device(ORMBaseModel):
__tablename__ = "devices"
id = Column(Integer, primary_key=True, autoincrement=True)
owner_name = Column(String, ForeignKey("users.name"))
name = Column(String)
type = Column(String)
expiry = Column(DateTime, default=datetime.datetime.now)
owner: User = relationship( owner: User = relationship(
"User", lazy="joined", back_populates="distinguished_names" "User", lazy="joined", back_populates="distinguished_names"
) )
UniqueConstraint( UniqueConstraint(
country, owner_name,
state, name,
city,
organization,
organizational_unit,
email,
common_name,
)
class Certificate(ORMBaseModel):
__tablename__ = "certificates"
id = Column(Integer, primary_key=True, autoincrement=True)
owner_name = Column(String, ForeignKey("users.name"))
dn_id = Column(
Integer,
ForeignKey("distinguished_names.id"),
nullable=False,
)
expiry = Column(DateTime, default=datetime.datetime.now)
distinguished_name: DistinguishedName = relationship(
"DistinguishedName", lazy="joined"
)
owner: User = relationship(
"User", lazy="joined", back_populates="certificates"
) )

View file

@ -79,6 +79,36 @@ class DistinguishedName(DistinguishedNameBase):
# distinguished name already existed # distinguished name already existed
pass pass
def delete(
self,
db: Session,
) -> bool:
"""
Delete this distinguished name from the database.
"""
db_dn = models.DistinguishedName(**dict(self))
db.refresh(db_dn)
# .load(
# db=db,
# country=self.country,
# state=self.state,
# city=self.city,
# organization=self.organization,
# organizational_unit=self.organizational_unit,
# email=self.email,
# common_name=self.common_name,
# )
if db_dn is None:
# nonexistent user
return False
db.delete(db_dn)
db.commit()
return True
########## ##########
# table: certificates # table: certificates
########## ##########

View file

@ -56,3 +56,33 @@ async def add_distinguished_name(
# return the created user on success # return the created user on success
return new_dn return new_dn
# @router.delete(
# "",
# responses={
# status.HTTP_200_OK: Responses.OK,
# status.HTTP_400_BAD_REQUEST: Responses.NOT_INSTALLED,
# status.HTTP_401_UNAUTHORIZED: Responses.NEEDS_USER,
# status.HTTP_403_FORBIDDEN: Responses.NEEDS_ADMIN,
# status.HTTP_404_NOT_FOUND: Responses.ENTRY_DOESNT_EXIST,
# },
# )
# async def remove_distinguished_name(
# user_name: str,
# _: User = Depends(get_current_user_if_admin),
# db: Session | None = Depends(Connection.get),
# ):
# """
# DELETE ./{user_name}: Remove a user from the database.
# """
# # get the user
# user = User.from_db(
# db=db,
# name=user_name,
# )
# # fail if deletion was unsuccessful
# if user is None or not user.delete(db):
# raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

26
api/plan.md Normal file
View file

@ -0,0 +1,26 @@
## Server props
- default DN parts: country, state, city, org, OU
- "customizable" flags for DN parts
- flag: use client-to-client
- force cipher, tls-cipher, auth params
- server name
- default certification length
- default certificate algo
## User props
- username
- password
- custom DN parts: country, state, city, org, OU
- email
## User caps
- admin: administrator
- login: can log into the web interface
- certify: can certify own devices without approval
- renew: can renew certificates for own devices
## Device props
- name
- type (icon)
- is active
- certified until