progress in permissions

This commit is contained in:
Hesabix 2025-09-19 14:34:43 +03:30
parent 33a2441cd9
commit c1da9cd0bd
8 changed files with 117 additions and 3 deletions

View file

@ -51,7 +51,7 @@ def register(request: Request, payload: RegisterRequest, db: Session = Depends(g
api_repo.create_session_key(user_id=user_id, key_hash=key_hash, device_id=payload.device_id, user_agent=user_agent, ip=ip, expires_at=None)
from adapters.db.models.user import User
user_obj = db.get(User, user_id)
user = {"id": user_id, "first_name": payload.first_name, "last_name": payload.last_name, "email": payload.email, "mobile": payload.mobile, "referral_code": getattr(user_obj, "referral_code", None)}
user = {"id": user_id, "first_name": payload.first_name, "last_name": payload.last_name, "email": payload.email, "mobile": payload.mobile, "referral_code": getattr(user_obj, "referral_code", None), "app_permissions": getattr(user_obj, "app_permissions", None)}
response_data = {"api_key": api_key, "expires_at": None, "user": user}
formatted_data = format_datetime_fields(response_data, request)
return success_response(formatted_data, request)

View file

@ -6,5 +6,6 @@ from .api_key import ApiKey # noqa: F401
from .captcha import Captcha # noqa: F401
from .password_reset import PasswordReset # noqa: F401
from .business import Business # noqa: F401
from .business_permission import BusinessPermission # noqa: F401

View file

@ -0,0 +1,19 @@
from __future__ import annotations
from datetime import datetime
from sqlalchemy import Integer, ForeignKey, JSON, DateTime
from sqlalchemy.orm import Mapped, mapped_column
from adapters.db.session import Base
class BusinessPermission(Base):
__tablename__ = "business_permissions"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
business_id: Mapped[int] = mapped_column(Integer, ForeignKey("businesses.id", ondelete="CASCADE"), nullable=False, index=True)
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
business_permissions: Mapped[dict | None] = mapped_column(JSON, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from datetime import datetime
from sqlalchemy import String, DateTime, Boolean, Integer, ForeignKey
from sqlalchemy import String, DateTime, Boolean, Integer, ForeignKey, JSON
from sqlalchemy.orm import Mapped, mapped_column
from adapters.db.session import Base
@ -21,6 +21,8 @@ class User(Base):
# Marketing/Referral fields
referral_code: Mapped[str] = mapped_column(String(32), unique=True, index=True, nullable=False)
referred_by_user_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
# App permissions
app_permissions: Mapped[dict | None] = mapped_column(JSON, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

View file

@ -26,8 +26,26 @@ class UserRepository(BaseRepository[User]):
stmt = select(User).where(User.referral_code == referral_code)
return self.db.execute(stmt).scalars().first()
def is_first_user(self) -> bool:
"""بررسی اینکه آیا این اولین کاربر سیستم است یا نه"""
stmt = select(func.count()).select_from(User)
count = self.db.execute(stmt).scalar() or 0
return count == 0
def create(self, *, email: str | None, mobile: str | None, password_hash: str, first_name: str | None, last_name: str | None, referral_code: str, referred_by_user_id: int | None = None) -> User:
user = User(email=email, mobile=mobile, password_hash=password_hash, first_name=first_name, last_name=last_name, referral_code=referral_code, referred_by_user_id=referred_by_user_id)
# تعیین دسترسی‌های برنامه بر اساس اینکه آیا کاربر اول است یا نه
app_permissions = {"superadmin": True} if self.is_first_user() else {}
user = User(
email=email,
mobile=mobile,
password_hash=password_hash,
first_name=first_name,
last_name=last_name,
referral_code=referral_code,
referred_by_user_id=referred_by_user_id,
app_permissions=app_permissions
)
self.db.add(user)
self.db.commit()
self.db.refresh(user)
@ -85,6 +103,7 @@ class UserRepository(BaseRepository[User]):
"is_active": user.is_active,
"referral_code": user.referral_code,
"referred_by_user_id": user.referred_by_user_id,
"app_permissions": user.app_permissions,
"created_at": user.created_at,
"updated_at": user.updated_at,
}

View file

@ -12,6 +12,7 @@ adapters/db/session.py
adapters/db/models/__init__.py
adapters/db/models/api_key.py
adapters/db/models/business.py
adapters/db/models/business_permission.py
adapters/db/models/captcha.py
adapters/db/models/password_reset.py
adapters/db/models/user.py
@ -52,6 +53,8 @@ migrations/env.py
migrations/versions/20250117_000003_add_business_table.py
migrations/versions/20250117_000004_add_business_contact_fields.py
migrations/versions/20250117_000005_add_business_geographic_fields.py
migrations/versions/20250117_000006_add_app_permissions_to_users.py
migrations/versions/20250117_000007_create_business_permissions_table.py
migrations/versions/20250915_000001_init_auth_tables.py
migrations/versions/20250916_000002_add_referral_fields.py
tests/__init__.py

View file

@ -0,0 +1,28 @@
"""add app permissions to users
Revision ID: 20250117_000006
Revises: 20250117_000005
Create Date: 2025-01-17 00:00:06.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '20250117_000006'
down_revision = '20250117_000005'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('app_permissions', sa.JSON(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('users', 'app_permissions')
# ### end Alembic commands ###

View file

@ -0,0 +1,42 @@
"""create business permissions table
Revision ID: 20250117_000007
Revises: 20250117_000006
Create Date: 2025-01-17 00:00:07.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '20250117_000007'
down_revision = '20250117_000006'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('business_permissions',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('business_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('business_permissions', sa.JSON(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['business_id'], ['businesses.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_business_permissions_business_id'), 'business_permissions', ['business_id'], unique=False)
op.create_index(op.f('ix_business_permissions_user_id'), 'business_permissions', ['user_id'], unique=False)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_business_permissions_user_id'), table_name='business_permissions')
op.drop_index(op.f('ix_business_permissions_business_id'), table_name='business_permissions')
op.drop_table('business_permissions')
# ### end Alembic commands ###