feat(users): track who created each account (created_by_id)
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

- 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) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-04-06 12:48:48 +02:00
parent 4cef43fedc
commit 3862706197
6 changed files with 25 additions and 2 deletions

View File

@ -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)

View File

@ -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

View File

@ -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])

View File

@ -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)

View File

@ -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;

View File

@ -1245,6 +1245,11 @@
<td style="font-size: var(--font-size-sm); color: var(--text-secondary);"
data-sort-value="{{ user.created_at.strftime('%Y%m%d%H%M') }}">
{{ user.created_at.strftime('%d.%m.%Y %H:%M') }}
{% if user.created_by_id %}
<br><span style="font-size: 0.75rem; color: var(--text-muted, #9CA3AF);" title="Dodany przez {{ user.created_by.name or user.created_by.email }}">dodał: {{ user.created_by.name or user.created_by.email }}</span>
{% else %}
<br><span style="font-size: 0.75rem; color: var(--text-muted, #9CA3AF);">samorejestracja</span>
{% endif %}
</td>
<td style="font-size: var(--font-size-sm); color: var(--text-secondary);"
data-sort-value="{{ user.last_login.strftime('%Y%m%d%H%M') if user.last_login else '0' }}">