mirror of
https://github.com/reconurge/flowsint.git
synced 2026-03-11 17:34:31 -05:00
feat: permission
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
"""add passive_delete_v2
|
||||
|
||||
Revision ID: 1d0f26dbbef5
|
||||
Revises: afdaf9aa539c
|
||||
Create Date: 2025-09-17 22:48:31.379106
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '1d0f26dbbef5'
|
||||
down_revision: Union[str, None] = 'afdaf9aa539c'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,35 @@
|
||||
"""add investigation roles permissions
|
||||
|
||||
|
||||
Revision ID: 6be831edfda7
|
||||
Revises: c82bf6af92e5
|
||||
Create Date: 2025-09-17 22:02:46.159090
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '6be831edfda7'
|
||||
down_revision: Union[str, None] = 'c82bf6af92e5'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('investigation_user_roles', sa.Column('roles', postgresql.ARRAY(sa.Enum('OWNER', 'EDITOR', 'VIEWER', name='role_enum', create_constraint=True)), server_default='{}', nullable=False))
|
||||
op.drop_column('investigation_user_roles', 'role')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('investigation_user_roles', sa.Column('role', postgresql.ENUM('OWNER', 'EDITOR', 'VIEWER', name='role_enum'), autoincrement=False, nullable=False))
|
||||
op.drop_column('investigation_user_roles', 'roles')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,63 @@
|
||||
"""add investigation roles permissions
|
||||
|
||||
|
||||
Revision ID: 6e49acfb3816
|
||||
Revises: 1098b7a5eabc
|
||||
Create Date: 2025-09-17 21:46:14.314402
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '6e49acfb3816'
|
||||
down_revision: Union[str, None] = '1098b7a5eabc'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('investigation_user_roles',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('user_id', sa.UUID(), nullable=False),
|
||||
sa.Column('investigation_id', sa.UUID(), nullable=False),
|
||||
sa.Column('role', sa.Enum('OWNER', 'EDITOR', 'VIEWER', name='role_enum', create_constraint=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['investigation_id'], ['investigations.id'], onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['profiles.id'], onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'investigation_id', name='uq_user_investigation')
|
||||
)
|
||||
op.create_index('idx_investigation_roles_investigation_id', 'investigation_user_roles', ['investigation_id'], unique=False)
|
||||
op.create_index('idx_investigation_roles_user_id', 'investigation_user_roles', ['user_id'], unique=False)
|
||||
op.drop_index('idx_investigations_profiles_investigation_id', table_name='investigations_profiles')
|
||||
op.drop_index('idx_investigations_profiles_profile_id', table_name='investigations_profiles')
|
||||
op.drop_index('projects_profiles_unique_profile_project', table_name='investigations_profiles')
|
||||
op.drop_table('investigations_profiles')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('investigations_profiles',
|
||||
sa.Column('id', sa.UUID(), autoincrement=False, nullable=False),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(timezone=True), server_default=sa.text('now()'), autoincrement=False, nullable=True),
|
||||
sa.Column('investigation_id', sa.UUID(), autoincrement=False, nullable=True),
|
||||
sa.Column('profile_id', sa.UUID(), autoincrement=False, nullable=True),
|
||||
sa.Column('role', sa.VARCHAR(), server_default=sa.text("'member'::character varying"), autoincrement=False, nullable=True),
|
||||
sa.ForeignKeyConstraint(['investigation_id'], ['investigations.id'], name='investigations_profiles_investigation_id_fkey', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['profile_id'], ['profiles.id'], name='investigations_profiles_profile_id_fkey', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name='investigations_profiles_pkey')
|
||||
)
|
||||
op.create_index('projects_profiles_unique_profile_project', 'investigations_profiles', ['profile_id', 'investigation_id'], unique=False)
|
||||
op.create_index('idx_investigations_profiles_profile_id', 'investigations_profiles', ['profile_id'], unique=False)
|
||||
op.create_index('idx_investigations_profiles_investigation_id', 'investigations_profiles', ['investigation_id'], unique=False)
|
||||
op.drop_index('idx_investigation_roles_user_id', table_name='investigation_user_roles')
|
||||
op.drop_index('idx_investigation_roles_investigation_id', table_name='investigation_user_roles')
|
||||
op.drop_table('investigation_user_roles')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,32 @@
|
||||
"""fix_backpopulate issue
|
||||
|
||||
Revision ID: 8d0e12b68d1e
|
||||
Revises: 1d0f26dbbef5
|
||||
Create Date: 2025-09-17 22:55:20.721587
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '8d0e12b68d1e'
|
||||
down_revision: Union[str, None] = '1d0f26dbbef5'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,32 @@
|
||||
"""add passive_delete
|
||||
|
||||
Revision ID: afdaf9aa539c
|
||||
Revises: 6be831edfda7
|
||||
Create Date: 2025-09-17 22:46:21.139127
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'afdaf9aa539c'
|
||||
down_revision: Union[str, None] = '6be831edfda7'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,33 @@
|
||||
"""add investigation roles permissions
|
||||
|
||||
|
||||
Revision ID: c82bf6af92e5
|
||||
Revises: d39941278a91
|
||||
Create Date: 2025-09-17 21:55:56.756716
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'c82bf6af92e5'
|
||||
down_revision: Union[str, None] = 'd39941278a91'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
32
flowsint-api/alembic/versions/d39941278a91_init.py
Normal file
32
flowsint-api/alembic/versions/d39941278a91_init.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""init
|
||||
|
||||
Revision ID: d39941278a91
|
||||
Revises: 6e49acfb3816
|
||||
Create Date: 2025-09-17 21:52:57.142634
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'd39941278a91'
|
||||
down_revision: Union[str, None] = '6e49acfb3816'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
@@ -1,10 +1,19 @@
|
||||
from uuid import UUID, uuid4
|
||||
from app.security.permissions import check_investigation_permission
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
from flowsint_core.core.types import Role
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
from flowsint_core.core.postgre_db import get_db
|
||||
from flowsint_core.core.models import Analysis, Investigation, Profile, Sketch
|
||||
from flowsint_core.core.models import (
|
||||
Analysis,
|
||||
Investigation,
|
||||
InvestigationUserRole,
|
||||
Profile,
|
||||
Sketch,
|
||||
)
|
||||
from app.api.deps import get_current_user
|
||||
from app.api.schemas.investigation import (
|
||||
InvestigationRead,
|
||||
@@ -17,17 +26,52 @@ from flowsint_core.core.graph_db import neo4j_connection
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def get_user_accessible_investigations(
|
||||
user_id: str, db: Session, allowed_roles: list[Role] = None
|
||||
) -> list[Investigation]:
|
||||
"""
|
||||
Returns all investigations accessible to user depending on its roles
|
||||
"""
|
||||
query = db.query(Investigation).join(
|
||||
InvestigationUserRole,
|
||||
InvestigationUserRole.investigation_id == Investigation.id,
|
||||
)
|
||||
|
||||
query = query.filter(InvestigationUserRole.user_id == user_id)
|
||||
|
||||
if allowed_roles:
|
||||
# ARRAY(Role) contains any of allowed_roles
|
||||
conditions = [InvestigationUserRole.roles.any(role) for role in allowed_roles]
|
||||
# Inclut également le propriétaire de l’investigation
|
||||
query = query.filter(or_(*conditions, Investigation.owner_id == user_id))
|
||||
|
||||
return (
|
||||
query.options(
|
||||
selectinload(Investigation.sketches),
|
||||
selectinload(Investigation.analyses),
|
||||
selectinload(Investigation.owner),
|
||||
)
|
||||
.distinct()
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
# Get the list of all investigations
|
||||
@router.get("", response_model=List[InvestigationRead])
|
||||
def get_investigations(
|
||||
db: Session = Depends(get_db), current_user: Profile = Depends(get_current_user)
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Profile = Depends(get_current_user),
|
||||
):
|
||||
investigations = (
|
||||
db.query(Investigation)
|
||||
.options(selectinload(Investigation.sketches), selectinload(Investigation.analyses), selectinload(Investigation.owner))
|
||||
.filter(Investigation.owner_id == current_user.id)
|
||||
.all()
|
||||
"""
|
||||
Récupère toutes les investigations accessibles à l'utilisateur
|
||||
selon ses rôles (OWNER, EDITOR, VIEWER).
|
||||
"""
|
||||
allowed_roles_for_read = [Role.OWNER, Role.EDITOR, Role.VIEWER]
|
||||
|
||||
investigations = get_user_accessible_investigations(
|
||||
user_id=current_user.id, db=db, allowed_roles=allowed_roles_for_read
|
||||
)
|
||||
|
||||
return investigations
|
||||
|
||||
|
||||
@@ -46,12 +90,21 @@ def create_investigation(
|
||||
description=payload.description or payload.name,
|
||||
owner_id=current_user.id,
|
||||
status="active",
|
||||
created_at=datetime.utcnow(),
|
||||
last_updated_at=datetime.utcnow(),
|
||||
)
|
||||
db.add(new_investigation)
|
||||
|
||||
new_roles = InvestigationUserRole(
|
||||
id=uuid4(),
|
||||
user_id=current_user.id,
|
||||
investigation_id=new_investigation.id,
|
||||
roles=[Role.OWNER],
|
||||
)
|
||||
db.add(new_roles)
|
||||
|
||||
db.commit()
|
||||
db.refresh(new_investigation)
|
||||
db.refresh(new_roles)
|
||||
|
||||
return new_investigation
|
||||
|
||||
|
||||
@@ -62,9 +115,14 @@ def get_investigation_by_id(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Profile = Depends(get_current_user),
|
||||
):
|
||||
check_investigation_permission(current_user.id, investigation_id, actions=["read"], db=db)
|
||||
investigation = (
|
||||
db.query(Investigation)
|
||||
.options(selectinload(Investigation.sketches), selectinload(Investigation.analyses), selectinload(Investigation.owner))
|
||||
.options(
|
||||
selectinload(Investigation.sketches),
|
||||
selectinload(Investigation.analyses),
|
||||
selectinload(Investigation.owner),
|
||||
)
|
||||
.filter(Investigation.id == investigation_id)
|
||||
.filter(Investigation.owner_id == current_user.id)
|
||||
.first()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from app.security.permissions import check_investigation_permission
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Dict, Any, Literal
|
||||
from typing import Literal, List
|
||||
from fastapi import HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from flowsint_core.utils import flatten
|
||||
from typing import Dict, Any, List
|
||||
from sqlalchemy.orm import Session
|
||||
from app.api.schemas.sketch import SketchCreate, SketchRead, SketchUpdate
|
||||
from flowsint_core.core.models import Sketch, Profile
|
||||
@@ -63,6 +63,9 @@ def create_sketch(
|
||||
current_user: Profile = Depends(get_current_user),
|
||||
):
|
||||
sketch_data = data.dict()
|
||||
check_investigation_permission(
|
||||
current_user.id, sketch_data.get("investigation_id"), actions=["create"], db=db
|
||||
)
|
||||
sketch_data["owner_id"] = current_user.id
|
||||
sketch = Sketch(**sketch_data)
|
||||
db.add(sketch)
|
||||
|
||||
33
flowsint-api/app/security/permissions.py
Normal file
33
flowsint-api/app/security/permissions.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from fastapi import HTTPException
|
||||
from flowsint_core.core.models import InvestigationUserRole
|
||||
from flowsint_core.core.types import Role
|
||||
|
||||
|
||||
def can_user(roles: list[Role], actions: list[str]) -> bool:
|
||||
"""
|
||||
Vérifie si au moins un rôle de la liste autorise au moins une action de la liste.
|
||||
"""
|
||||
for role in roles:
|
||||
for action in actions:
|
||||
if role == Role.OWNER:
|
||||
return True
|
||||
if role == Role.EDITOR and action in ["read", "create", "update"]:
|
||||
return True
|
||||
if role == Role.VIEWER and action == "read":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
from fastapi import HTTPException
|
||||
|
||||
|
||||
def check_investigation_permission(user_id: str, investigation_id: str, actions: list[str], db):
|
||||
role_entry = (
|
||||
db.query(InvestigationUserRole)
|
||||
.filter_by(user_id=user_id, investigation_id=investigation_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not role_entry or not can_user(role_entry.roles, actions):
|
||||
raise HTTPException(status_code=403, detail="Forbidden")
|
||||
return True
|
||||
159
flowsint-api/poetry.lock
generated
159
flowsint-api/poetry.lock
generated
@@ -1019,7 +1019,7 @@ files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
markers = {dev = "platform_system == \"Windows\" or sys_platform == \"win32\""}
|
||||
markers = {dev = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "confection"
|
||||
@@ -1039,49 +1039,49 @@ srsly = ">=2.4.0,<3.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "45.0.6"
|
||||
version = "45.0.7"
|
||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
optional = false
|
||||
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "cryptography-45.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:048e7ad9e08cf4c0ab07ff7f36cc3115924e22e2266e034450a890d9e312dd74"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:44647c5d796f5fc042bbc6d61307d04bf29bccb74d188f18051b635f20a9c75f"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e40b80ecf35ec265c452eea0ba94c9587ca763e739b8e559c128d23bff7ebbbf"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:00e8724bdad672d75e6f069b27970883179bd472cd24a63f6e620ca7e41cc0c5"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a3085d1b319d35296176af31c90338eeb2ddac8104661df79f80e1d9787b8b2"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1b7fa6a1c1188c7ee32e47590d16a5a0646270921f8020efc9a511648e1b2e08"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:275ba5cc0d9e320cd70f8e7b96d9e59903c815ca579ab96c1e37278d231fc402"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f4028f29a9f38a2025abedb2e409973709c660d44319c61762202206ed577c42"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ee411a1b977f40bd075392c80c10b58025ee5c6b47a822a33c1198598a7a5f05"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e2a21a8eda2d86bb604934b6b37691585bd095c1f788530c1fcefc53a82b3453"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-win32.whl", hash = "sha256:d063341378d7ee9c91f9d23b431a3502fc8bfacd54ef0a27baa72a0843b29159"},
|
||||
{file = "cryptography-45.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:833dc32dfc1e39b7376a87b9a6a4288a10aae234631268486558920029b086ec"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:3436128a60a5e5490603ab2adbabc8763613f638513ffa7d311c900a8349a2a0"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0d9ef57b6768d9fa58e92f4947cea96ade1233c0e236db22ba44748ffedca394"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea3c42f2016a5bbf71825537c2ad753f2870191134933196bee408aac397b3d9"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:20ae4906a13716139d6d762ceb3e0e7e110f7955f3bc3876e3a07f5daadec5f3"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dac5ec199038b8e131365e2324c03d20e97fe214af051d20c49db129844e8b3"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:18f878a34b90d688982e43f4b700408b478102dd58b3e39de21b5ebf6509c301"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5bd6020c80c5b2b2242d6c48487d7b85700f5e0038e67b29d706f98440d66eb5"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:eccddbd986e43014263eda489abbddfbc287af5cddfd690477993dbb31e31016"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:550ae02148206beb722cfe4ef0933f9352bab26b087af00e48fdfb9ade35c5b3"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5b64e668fc3528e77efa51ca70fadcd6610e8ab231e3e06ae2bab3b31c2b8ed9"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-win32.whl", hash = "sha256:780c40fb751c7d2b0c6786ceee6b6f871e86e8718a8ff4bc35073ac353c7cd02"},
|
||||
{file = "cryptography-45.0.6-cp37-abi3-win_amd64.whl", hash = "sha256:20d15aed3ee522faac1a39fbfdfee25d17b1284bafd808e1640a74846d7c4d1b"},
|
||||
{file = "cryptography-45.0.6-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:705bb7c7ecc3d79a50f236adda12ca331c8e7ecfbea51edd931ce5a7a7c4f012"},
|
||||
{file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:826b46dae41a1155a0c0e66fafba43d0ede1dc16570b95e40c4d83bfcf0a451d"},
|
||||
{file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:cc4d66f5dc4dc37b89cfef1bd5044387f7a1f6f0abb490815628501909332d5d"},
|
||||
{file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:f68f833a9d445cc49f01097d95c83a850795921b3f7cc6488731e69bde3288da"},
|
||||
{file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3b5bf5267e98661b9b888a9250d05b063220dfa917a8203744454573c7eb79db"},
|
||||
{file = "cryptography-45.0.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2384f2ab18d9be88a6e4f8972923405e2dbb8d3e16c6b43f15ca491d7831bd18"},
|
||||
{file = "cryptography-45.0.6-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fc022c1fa5acff6def2fc6d7819bbbd31ccddfe67d075331a65d9cfb28a20983"},
|
||||
{file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3de77e4df42ac8d4e4d6cdb342d989803ad37707cf8f3fbf7b088c9cbdd46427"},
|
||||
{file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:599c8d7df950aa68baa7e98f7b73f4f414c9f02d0e8104a30c0182a07732638b"},
|
||||
{file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:31a2b9a10530a1cb04ffd6aa1cd4d3be9ed49f7d77a4dafe198f3b382f41545c"},
|
||||
{file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:e5b3dda1b00fb41da3af4c5ef3f922a200e33ee5ba0f0bc9ecf0b0c173958385"},
|
||||
{file = "cryptography-45.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:629127cfdcdc6806dfe234734d7cb8ac54edaf572148274fa377a7d3405b0043"},
|
||||
{file = "cryptography-45.0.6.tar.gz", hash = "sha256:5c966c732cf6e4a276ce83b6e4c729edda2df6929083a952cc7da973c539c719"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:3be4f21c6245930688bd9e162829480de027f8bf962ede33d4f8ba7d67a00cee"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:67285f8a611b0ebc0857ced2081e30302909f571a46bfa7a3cc0ad303fe015c6"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:577470e39e60a6cd7780793202e63536026d9b8641de011ed9d8174da9ca5339"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:4bd3e5c4b9682bc112d634f2c6ccc6736ed3635fc3319ac2bb11d768cc5a00d8"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:465ccac9d70115cd4de7186e60cfe989de73f7bb23e8a7aa45af18f7412e75bf"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:16ede8a4f7929b4b7ff3642eba2bf79aa1d71f24ab6ee443935c0d269b6bc513"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8978132287a9d3ad6b54fcd1e08548033cc09dc6aacacb6c004c73c3eb5d3ac3"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b6a0e535baec27b528cb07a119f321ac024592388c5681a5ced167ae98e9fff3"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a24ee598d10befaec178efdff6054bc4d7e883f615bfbcd08126a0f4931c83a6"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa26fa54c0a9384c27fcdc905a2fb7d60ac6e47d14bc2692145f2b3b1e2cfdbd"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-win32.whl", hash = "sha256:bef32a5e327bd8e5af915d3416ffefdbe65ed975b646b3805be81b23580b57b8"},
|
||||
{file = "cryptography-45.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:3808e6b2e5f0b46d981c24d79648e5c25c35e59902ea4391a0dcb3e667bf7443"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bfb4c801f65dd61cedfc61a83732327fafbac55a47282e6f26f073ca7a41c3b2"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:81823935e2f8d476707e85a78a405953a03ef7b7b4f55f93f7c2d9680e5e0691"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3994c809c17fc570c2af12c9b840d7cea85a9fd3e5c0e0491f4fa3c029216d59"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dad43797959a74103cb59c5dac71409f9c27d34c8a05921341fb64ea8ccb1dd4"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ce7a453385e4c4693985b4a4a3533e041558851eae061a58a5405363b098fcd3"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b04f85ac3a90c227b6e5890acb0edbaf3140938dbecf07bff618bf3638578cf1"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:48c41a44ef8b8c2e80ca4527ee81daa4c527df3ecbc9423c41a420a9559d0e27"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f3df7b3d0f91b88b2106031fd995802a2e9ae13e02c36c1fc075b43f420f3a17"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:dd342f085542f6eb894ca00ef70236ea46070c8a13824c6bde0dfdcd36065b9b"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1993a1bb7e4eccfb922b6cd414f072e08ff5816702a0bdb8941c247a6b1b287c"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-win32.whl", hash = "sha256:18fcf70f243fe07252dcb1b268a687f2358025ce32f9f88028ca5c364b123ef5"},
|
||||
{file = "cryptography-45.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:7285a89df4900ed3bfaad5679b1e668cb4b38a8de1ccbfc84b05f34512da0a90"},
|
||||
{file = "cryptography-45.0.7-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:de58755d723e86175756f463f2f0bddd45cc36fbd62601228a3f8761c9f58252"},
|
||||
{file = "cryptography-45.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a20e442e917889d1a6b3c570c9e3fa2fdc398c20868abcea268ea33c024c4083"},
|
||||
{file = "cryptography-45.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:258e0dff86d1d891169b5af222d362468a9570e2532923088658aa866eb11130"},
|
||||
{file = "cryptography-45.0.7-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d97cf502abe2ab9eff8bd5e4aca274da8d06dd3ef08b759a8d6143f4ad65d4b4"},
|
||||
{file = "cryptography-45.0.7-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:c987dad82e8c65ebc985f5dae5e74a3beda9d0a2a4daf8a1115f3772b59e5141"},
|
||||
{file = "cryptography-45.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c13b1e3afd29a5b3b2656257f14669ca8fa8d7956d509926f0b130b600b50ab7"},
|
||||
{file = "cryptography-45.0.7-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a862753b36620af6fc54209264f92c716367f2f0ff4624952276a6bbd18cbde"},
|
||||
{file = "cryptography-45.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:06ce84dc14df0bf6ea84666f958e6080cdb6fe1231be2a51f3fc1267d9f3fb34"},
|
||||
{file = "cryptography-45.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d0c5c6bac22b177bf8da7435d9d27a6834ee130309749d162b26c3105c0795a9"},
|
||||
{file = "cryptography-45.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:2f641b64acc00811da98df63df7d59fd4706c0df449da71cb7ac39a0732b40ae"},
|
||||
{file = "cryptography-45.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:f5414a788ecc6ee6bc58560e85ca624258a55ca434884445440a810796ea0e0b"},
|
||||
{file = "cryptography-45.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:1f3d56f73595376f4244646dd5c5870c14c196949807be39e79e7bd9bac3da63"},
|
||||
{file = "cryptography-45.0.7.tar.gz", hash = "sha256:4b1654dfc64ea479c242508eb8c724044f1e964a47d1d1cacc5132292d851971"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1094,7 +1094,7 @@ nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_full_version >= \"3.8
|
||||
pep8test = ["check-sdist ; python_full_version >= \"3.8.0\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
|
||||
sdist = ["build (>=1.0.0)"]
|
||||
ssh = ["bcrypt (>=3.1.5)"]
|
||||
test = ["certifi (>=2024)", "cryptography-vectors (==45.0.6)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
|
||||
test = ["certifi (>=2024)", "cryptography-vectors (==45.0.7)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
|
||||
test-randomorder = ["pytest-randomly"]
|
||||
|
||||
[[package]]
|
||||
@@ -1198,25 +1198,26 @@ wmi = ["wmi (>=1.5.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "docker"
|
||||
version = "6.1.3"
|
||||
version = "7.1.0"
|
||||
description = "A Python library for the Docker Engine API."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"},
|
||||
{file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"},
|
||||
{file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"},
|
||||
{file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
packaging = ">=14.0"
|
||||
pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""}
|
||||
requests = ">=2.26.0"
|
||||
urllib3 = ">=1.26.0"
|
||||
websocket-client = ">=0.32.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coverage (==7.2.7)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.1.0)", "ruff (==0.1.8)"]
|
||||
docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"]
|
||||
ssh = ["paramiko (>=2.4.3)"]
|
||||
websockets = ["websocket-client (>=1.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
@@ -1372,7 +1373,8 @@ develop = true
|
||||
alembic = "1.13.0"
|
||||
asyncpg = "^0.29"
|
||||
celery = "^5.3"
|
||||
docker = "^6.1"
|
||||
cryptography = "^45.0.7"
|
||||
docker = "^7.1.0"
|
||||
flowsint-transforms = {path = "../flowsint-transforms", develop = true}
|
||||
neo4j = "^5.0"
|
||||
networkx = "^2.6.3"
|
||||
@@ -1380,6 +1382,7 @@ passlib = {version = "^1.7", extras = ["bcrypt"]}
|
||||
phonenumbers = "^9.0.8"
|
||||
psycopg2-binary = "^2.9"
|
||||
pydantic = {version = "^2.11.7", extras = ["email"]}
|
||||
pytest = "^8.4.2"
|
||||
python-dotenv = "^1.0"
|
||||
python-jose = {version = "^3.3", extras = ["cryptography"]}
|
||||
python-multipart = "^0.0.20"
|
||||
@@ -1404,7 +1407,6 @@ develop = true
|
||||
|
||||
[package.dependencies]
|
||||
dnspython = "^2.4"
|
||||
docker = "^6.1"
|
||||
flowsint-core = {path = "../flowsint-core", develop = true}
|
||||
flowsint-types = {path = "../flowsint-types", develop = true}
|
||||
hibpwned = "^1.3.9"
|
||||
@@ -1830,7 +1832,7 @@ version = "2.1.0"
|
||||
description = "brain-dead simple config-ini parsing"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main", "dev"]
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"},
|
||||
{file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"},
|
||||
@@ -3266,7 +3268,7 @@ version = "1.6.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main", "dev"]
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"},
|
||||
{file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"},
|
||||
@@ -3997,43 +3999,25 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.4"
|
||||
version = "8.4.2"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main", "dev"]
|
||||
files = [
|
||||
{file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
|
||||
{file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=0.12,<2.0"
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "0.21.2"
|
||||
description = "Pytest support for asyncio"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b"},
|
||||
{file = "pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45"},
|
||||
{file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"},
|
||||
{file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytest = ">=7.0.0"
|
||||
colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = ">=1"
|
||||
packaging = ">=20"
|
||||
pluggy = ">=1.5,<2"
|
||||
pygments = ">=2.7.2"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
|
||||
testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
|
||||
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "python-bidi"
|
||||
@@ -5488,23 +5472,6 @@ files = [
|
||||
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websocket-client"
|
||||
version = "1.8.0"
|
||||
description = "WebSocket client for Python with low level API options"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"},
|
||||
{file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"]
|
||||
optional = ["python-socks", "wsaccel"]
|
||||
test = ["websockets"]
|
||||
|
||||
[[package]]
|
||||
name = "werkzeug"
|
||||
version = "3.1.3"
|
||||
@@ -5778,4 +5745,4 @@ propcache = ">=0.2.1"
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.11,<3.13"
|
||||
content-hash = "713413e0c4f9fe453cc2fbb96fe82650caa2776f40af2fae82601326e4981774"
|
||||
content-hash = "4a980251fbdec9cd0fde83177e6a8b96e21ce2af0b852b628095da088ce3af41"
|
||||
|
||||
@@ -26,13 +26,11 @@ alembic = "1.13.0"
|
||||
passlib = {extras = ["bcrypt"], version = "^1.7"}
|
||||
sse-starlette = "^1.8"
|
||||
networkx = "^2.6.3"
|
||||
pytest-asyncio = "^0.21"
|
||||
email-validator = "^2.2.0"
|
||||
mistralai = "^1.9.3"
|
||||
python-multipart = "^0.0.20"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest = "^7.4"
|
||||
black = "^23.0"
|
||||
isort = "^5.12"
|
||||
flake8 = "^6.0"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[tool:pytest]
|
||||
asyncio_mode = auto
|
||||
testpaths = tests
|
||||
python_files = test_*.py
|
||||
python_functions = test_*
|
||||
addopts = -v -s
|
||||
Reference in New Issue
Block a user