From 3862706197e313dab74d3ff7a4af8cb3240525cf Mon Sep 17 00:00:00 2001 From: Maciej Pienczyn Date: Mon, 6 Apr 2026 12:48:48 +0200 Subject: [PATCH] feat(users): track who created each account (created_by_id) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add created_by_id FK to users table (NULL = self-registration) - Set created_by_id in admin create, bulk create, and team add routes - Show "samorejestracja" or "dodał: [name]" in admin users panel Co-Authored-By: Claude Opus 4.6 (1M context) --- blueprints/admin/routes.py | 3 ++- blueprints/admin/routes_users_api.py | 3 ++- blueprints/public/routes_team.py | 1 + database.py | 4 ++++ database/migrations/097_add_created_by_id.sql | 11 +++++++++++ templates/admin/users.html | 5 +++++ 6 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 database/migrations/097_add_created_by_id.sql diff --git a/blueprints/admin/routes.py b/blueprints/admin/routes.py index 27a0b95..eb40e2c 100644 --- a/blueprints/admin/routes.py +++ b/blueprints/admin/routes.py @@ -229,7 +229,8 @@ def admin_user_add(): name=data.get('name', '').strip() or None, company_id=data.get('company_id') or None, is_verified=data.get('is_verified', True), - is_active=True + is_active=True, + created_by_id=current_user.id ) db.add(new_user) diff --git a/blueprints/admin/routes_users_api.py b/blueprints/admin/routes_users_api.py index 653c156..3e3faae 100644 --- a/blueprints/admin/routes_users_api.py +++ b/blueprints/admin/routes_users_api.py @@ -270,7 +270,8 @@ def admin_users_bulk_create(): name=user_data.get('name', '').strip() or None, company_id=company_id, is_verified=True, - is_active=True + is_active=True, + created_by_id=current_user.id ) db.add(new_user) # Set role based on AI parse result diff --git a/blueprints/public/routes_team.py b/blueprints/public/routes_team.py index ad4e42a..09c1fff 100644 --- a/blueprints/public/routes_team.py +++ b/blueprints/public/routes_team.py @@ -170,6 +170,7 @@ def team_add_member(company_id): is_verified=True, is_active=True, is_norda_member=company.status == 'active', + created_by_id=current_user.id, ) user.set_role(SystemRole.EMPLOYEE) user.set_company_role(CompanyRole[role_str]) diff --git a/database.py b/database.py index f0b9589..beb64a2 100644 --- a/database.py +++ b/database.py @@ -296,6 +296,10 @@ class User(Base, UserMixin): chamber_role = Column(String(50)) # prezes, wiceprezes, czlonek_rady, komisja_rewizyjna, sad_kolezenski avatar_path = Column(String(500)) # Path to profile photo (relative to static/uploads/) + # Account origin tracking + created_by_id = Column(Integer, ForeignKey('users.id'), nullable=True) # NULL = self-registration + created_by = relationship('User', remote_side='User.id', foreign_keys='User.created_by_id') + # Timestamps created_at = Column(DateTime, default=datetime.now) last_login = Column(DateTime) diff --git a/database/migrations/097_add_created_by_id.sql b/database/migrations/097_add_created_by_id.sql new file mode 100644 index 0000000..df93c7b --- /dev/null +++ b/database/migrations/097_add_created_by_id.sql @@ -0,0 +1,11 @@ +-- Migration 097: Add created_by_id to users table +-- Tracks who created the user account: +-- NULL = self-registration +-- user_id = created by that admin/manager + +ALTER TABLE users ADD COLUMN IF NOT EXISTS created_by_id INTEGER REFERENCES users(id) ON DELETE SET NULL; + +-- Backfill: mark existing admin-created users where we can infer from audit logs +-- (Skip for now — new column will be populated going forward) + +GRANT ALL ON TABLE users TO nordabiz_app; diff --git a/templates/admin/users.html b/templates/admin/users.html index 838f5f5..2e920cb 100644 --- a/templates/admin/users.html +++ b/templates/admin/users.html @@ -1245,6 +1245,11 @@ {{ user.created_at.strftime('%d.%m.%Y %H:%M') }} + {% if user.created_by_id %} +
dodał: {{ user.created_by.name or user.created_by.email }} + {% else %} +
samorejestracja + {% endif %}