mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-19 12:50:11 -05:00
ae9ee9dec1
- Add user_clients table and UserClient model for many-to-many user-client assignment - Add 'subcontractor' system role; users with this role see only assigned clients and their projects - User helpers: is_scope_restricted, get_allowed_client_ids(), get_allowed_project_ids() - Admin user form: assign clients when role is Subcontractor (multi-select, JS toggle) - Scope filtering: clients, projects, time entries, reports, invoices, timer, API v1 - Direct access to out-of-scope client/project returns 403 (web and API) - Migration 127_add_user_clients_table; scope_filter utility and ProjectService scope_client_ids - Docs: SUBCONTRACTOR_ROLE.md, ADVANCED_PERMISSIONS.md, RBAC, CLIENT_PORTAL, README, CHANGELOG Addresses GitHub Discussion #476 (user with limited clients/projects).
21 lines
843 B
Python
21 lines
843 B
Python
"""User-Client association for subcontractor scope (restrict user to assigned clients)."""
|
|
|
|
from datetime import datetime
|
|
from app import db
|
|
|
|
|
|
class UserClient(db.Model):
|
|
"""Association: user is allowed to see this client (subcontractor scope)."""
|
|
|
|
__tablename__ = "user_clients"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
user_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
client_id = db.Column(db.Integer, db.ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
|
|
|
__table_args__ = (db.UniqueConstraint("user_id", "client_id", name="uq_user_client"),)
|
|
|
|
def __repr__(self):
|
|
return f"<UserClient user_id={self.user_id} client_id={self.client_id}>"
|