groups functional & bugfixes
This commit is contained in:
@ -76,6 +76,7 @@ class Queue(Base):
|
||||
|
||||
users = relationship("QueueUser", backref="queue", lazy="dynamic")
|
||||
logs = relationship("QueueLog", backref="queue", lazy="dynamic")
|
||||
groups = relationship("QueueGroup", backref="queue", lazy="dynamic")
|
||||
|
||||
|
||||
class QueueUser(Base):
|
||||
@ -86,6 +87,7 @@ class QueueUser(Base):
|
||||
queue_id = Column(UUID(as_uuid=True), ForeignKey("queues.id"))
|
||||
position = Column(Integer)
|
||||
passed = Column(Boolean, default=False)
|
||||
group_id = Column(UUID(as_uuid=True), ForeignKey("queuegroup.id"), nullable=True)
|
||||
|
||||
|
||||
class QueueLog(Base):
|
||||
@ -97,6 +99,17 @@ class QueueLog(Base):
|
||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||
|
||||
|
||||
class QueueGroup(Base):
|
||||
__tablename__ = "queuegroup"
|
||||
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
name = Column(String)
|
||||
priority = Column(Integer)
|
||||
queue_id = Column(UUID(as_uuid=True), ForeignKey("queues.id"))
|
||||
|
||||
users = relationship("QueueUser", backref="group", lazy="dynamic")
|
||||
|
||||
|
||||
class Captcha(Base):
|
||||
__tablename__ = "captcha"
|
||||
|
||||
|
||||
@ -96,17 +96,21 @@ def get_current_user(
|
||||
|
||||
|
||||
def get_current_user_or_none(
|
||||
token: Annotated[str, Depends(oauth2_scheme)],
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
authorization: Annotated[Union[str, None], Header()] = None,
|
||||
) -> Union[schemas.UserInDB, None]:
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token, jwt_config.SECRET_KEY, algorithms=[jwt_config.ALGORITHM]
|
||||
)
|
||||
username: str = payload.get("sub")
|
||||
if username is None:
|
||||
raise credentials_exception
|
||||
token_data = schemas.TokenData(username=username)
|
||||
if authorization:
|
||||
token = authorization.split()[1]
|
||||
payload = jwt.decode(
|
||||
token, jwt_config.SECRET_KEY, algorithms=[jwt_config.ALGORITHM]
|
||||
)
|
||||
username: str = payload.get("sub")
|
||||
if username is None:
|
||||
raise credentials_exception
|
||||
token_data = schemas.TokenData(username=username)
|
||||
else:
|
||||
return None
|
||||
except JWTError:
|
||||
return None
|
||||
user = get_user_by_username(db, username=token_data.username)
|
||||
|
||||
@ -4,10 +4,23 @@ from uuid import UUID
|
||||
from ..auth import schemas as auth_schemas
|
||||
|
||||
|
||||
class QueueGroup(BaseModel):
|
||||
name: str
|
||||
priority: int
|
||||
|
||||
|
||||
class QueueGroupDetail(QueueGroup):
|
||||
id: UUID
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class QueueUser(BaseModel):
|
||||
id: UUID
|
||||
position: int
|
||||
passed: bool
|
||||
group_id: UUID | None = None
|
||||
user: auth_schemas.AnonUser
|
||||
|
||||
class Config:
|
||||
@ -23,6 +36,7 @@ class ParticipantInfo(BaseModel):
|
||||
class Queue(BaseModel):
|
||||
name: str
|
||||
description: Union[str, None] = None
|
||||
groups: List[QueueGroup] | None = None
|
||||
|
||||
|
||||
class QueueInList(Queue):
|
||||
@ -32,8 +46,10 @@ class QueueInList(Queue):
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class QueueInDb(Queue):
|
||||
class QueueInDb(BaseModel):
|
||||
id: UUID
|
||||
name: str
|
||||
description: Union[str, None] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
@ -44,6 +60,7 @@ class QueueDetail(Queue):
|
||||
status: str
|
||||
owner_id: UUID
|
||||
participants: ParticipantInfo
|
||||
groups: List[QueueGroupDetail] | None
|
||||
|
||||
|
||||
class ActionResult(BaseModel):
|
||||
@ -52,3 +69,7 @@ class ActionResult(BaseModel):
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class JoinRequest(BaseModel):
|
||||
group_id: UUID | None = None
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from typing import Annotated
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from sqlalchemy import func
|
||||
from uuid import UUID
|
||||
import redis
|
||||
import asyncio
|
||||
@ -49,6 +50,14 @@ def create_queue(
|
||||
)
|
||||
db.add(q)
|
||||
db.commit()
|
||||
if new_queue.groups:
|
||||
db.add_all(
|
||||
instances=[
|
||||
models.QueueGroup(name=qg.name, priority=qg.priority, queue_id=q.id)
|
||||
for qg in new_queue.groups
|
||||
]
|
||||
)
|
||||
db.commit()
|
||||
return schemas.QueueInDb.model_validate(q)
|
||||
|
||||
|
||||
@ -64,6 +73,7 @@ def get_detailed_queue(
|
||||
description=q.description,
|
||||
status=q.status,
|
||||
owner_id=q.owner_id,
|
||||
groups=q.groups.order_by(models.QueueGroup.priority.asc()),
|
||||
participants=schemas.ParticipantInfo(
|
||||
total=q.users.count(),
|
||||
remaining=q.users.filter(models.QueueUser.passed == False).count(),
|
||||
@ -80,6 +90,7 @@ def get_detailed_queue(
|
||||
|
||||
async def join_queue(
|
||||
queue_id: UUID,
|
||||
join_request: schemas.JoinRequest | None,
|
||||
client: Annotated[auth_schemas.AnonUser, Depends(auth_services.get_anon_user)],
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
r: Annotated[redis.client.Redis, Depends(get_redis)],
|
||||
@ -90,10 +101,18 @@ async def join_queue(
|
||||
last_qu = q.users.order_by(models.QueueUser.position.desc()).first()
|
||||
position = last_qu.position + 1 if last_qu else 0
|
||||
new_qu = models.QueueUser(
|
||||
user_id=client.id, queue_id=q.id, position=position
|
||||
user_id=client.id,
|
||||
queue_id=q.id,
|
||||
position=position,
|
||||
group_id=(
|
||||
join_request.group_id
|
||||
if join_request and join_request.group_id
|
||||
else None
|
||||
),
|
||||
)
|
||||
db.add(new_qu)
|
||||
db.commit()
|
||||
await rebuild_queue(queue=q, db=db)
|
||||
await r.publish(str(queue_id), "updated")
|
||||
return new_qu
|
||||
raise HTTPException(
|
||||
@ -129,7 +148,7 @@ async def get_queue_owner(
|
||||
async def verify_queue_owner(
|
||||
queue_owner: Annotated[auth_schemas.UserInDB, Depends(get_queue_owner)],
|
||||
current_user: Annotated[
|
||||
auth_schemas.UserInDB, Depends(auth_services.get_current_user)
|
||||
auth_schemas.UserInDB, Depends(auth_services.get_current_user_or_none)
|
||||
],
|
||||
) -> bool:
|
||||
return queue_owner.id == current_user.id if queue_owner and current_user else False
|
||||
@ -139,11 +158,32 @@ async def rebuild_queue(
|
||||
queue: Annotated[models.Queue, Depends(get_queue_by_id)],
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
):
|
||||
for i, qu in enumerate(
|
||||
queue.users.filter(models.QueueUser.passed == False).order_by(
|
||||
models.QueueUser.position.asc()
|
||||
query = (
|
||||
db.query(models.QueueUser)
|
||||
.join(
|
||||
models.QueueGroup,
|
||||
models.QueueUser.group_id == models.QueueGroup.id,
|
||||
isouter=True,
|
||||
)
|
||||
):
|
||||
.filter(models.QueueUser.passed == False, models.QueueUser.queue_id == queue.id)
|
||||
.order_by(
|
||||
func.coalesce(models.QueueGroup.priority, 0).asc(),
|
||||
models.QueueUser.position.asc(),
|
||||
)
|
||||
.options(joinedload(models.QueueUser.group))
|
||||
)
|
||||
queueusers = query.all()
|
||||
first_qu_found_and_queue_in_process = False
|
||||
if queue.status == "active":
|
||||
for i, qu in enumerate(queueusers):
|
||||
if qu.position == 0:
|
||||
first_qu_found_and_queue_in_process = True
|
||||
del queueusers[i]
|
||||
break
|
||||
for i, qu in enumerate(queueusers):
|
||||
if first_qu_found_and_queue_in_process:
|
||||
setattr(qu, "position", i + 1)
|
||||
continue
|
||||
setattr(qu, "position", i)
|
||||
db.commit()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user