feat: Add company role dropdown to admin users panel
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
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
Adds independent company_role management (NONE/VIEWER/EMPLOYEE/MANAGER) visible next to company column. Decouples company_role from system role so admins can control portal permissions for company profiles separately. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
30d9cdb698
commit
c2a6d5e286
@ -341,23 +341,7 @@ def admin_users_change_role():
|
||||
old_role = user.role
|
||||
user.set_role(SystemRole[new_role])
|
||||
|
||||
# Update company_role based on new role
|
||||
if new_role in ['MANAGER']:
|
||||
user.company_role = 'MANAGER'
|
||||
elif new_role in ['EMPLOYEE']:
|
||||
user.company_role = 'EMPLOYEE'
|
||||
elif new_role in ['UNAFFILIATED', 'MEMBER']:
|
||||
user.company_role = 'NONE'
|
||||
# OFFICE_MANAGER and ADMIN keep their company_role unchanged
|
||||
|
||||
# Sync role to user_companies table (primary company)
|
||||
if user.company_id and new_role in ['MANAGER', 'EMPLOYEE']:
|
||||
uc = db.query(UserCompany).filter_by(
|
||||
user_id=user.id, company_id=user.company_id
|
||||
).first()
|
||||
if uc:
|
||||
uc.role = new_role
|
||||
uc.updated_at = datetime.now()
|
||||
# Note: company_role is now managed independently via change-company-role endpoint
|
||||
|
||||
# Create default permissions for EMPLOYEE if they have a company
|
||||
if new_role == 'EMPLOYEE' and user.company_id:
|
||||
@ -411,6 +395,59 @@ def admin_users_get_roles():
|
||||
return jsonify({'success': True, 'roles': roles})
|
||||
|
||||
|
||||
@bp.route('/users-api/change-company-role', methods=['POST'])
|
||||
@login_required
|
||||
@role_required(SystemRole.OFFICE_MANAGER)
|
||||
def admin_users_change_company_role():
|
||||
"""Change user's company role (portal permissions for company profile)."""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
user_id = data.get('user_id')
|
||||
new_role = data.get('company_role')
|
||||
|
||||
if not user_id or not new_role:
|
||||
return jsonify({'success': False, 'error': 'Brak wymaganych danych'}), 400
|
||||
|
||||
valid_roles = ['NONE', 'VIEWER', 'EMPLOYEE', 'MANAGER']
|
||||
if new_role not in valid_roles:
|
||||
return jsonify({'success': False, 'error': f'Nieprawidłowa rola: {new_role}'}), 400
|
||||
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
return jsonify({'success': False, 'error': 'Użytkownik nie znaleziony'}), 404
|
||||
|
||||
old_role = user.company_role
|
||||
user.company_role = new_role
|
||||
|
||||
# Sync to user_companies table
|
||||
if user.company_id:
|
||||
uc = db.query(UserCompany).filter_by(
|
||||
user_id=user.id, company_id=user.company_id
|
||||
).first()
|
||||
if uc:
|
||||
uc.role = new_role
|
||||
uc.updated_at = datetime.now()
|
||||
|
||||
db.commit()
|
||||
logger.info(f"Admin {current_user.email} changed company_role for user {user.email}: {old_role} -> {new_role}")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': f'Uprawnienia firmowe zmienione na {new_role}',
|
||||
'user_id': user.id,
|
||||
'old_role': old_role,
|
||||
'new_role': new_role
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f"Error changing company role: {e}")
|
||||
return jsonify({'success': False, 'error': f'Błąd: {str(e)}'}), 500
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# USER-COMPANY ASSOCIATIONS (Multi-company support)
|
||||
# ============================================================
|
||||
|
||||
@ -1140,6 +1140,7 @@
|
||||
<th>ID</th>
|
||||
<th>Użytkownik</th>
|
||||
<th>Firma</th>
|
||||
<th>Upr. firmowe</th>
|
||||
<th>Rola</th>
|
||||
<th>Utworzono</th>
|
||||
<th>Ostatnie logowanie</th>
|
||||
@ -1169,6 +1170,20 @@
|
||||
<span style="color: var(--text-secondary);">-</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if user.company %}
|
||||
<select class="role-select" style="font-size: var(--font-size-sm);"
|
||||
data-user-id="{{ user.id }}"
|
||||
onchange="changeCompanyRole({{ user.id }}, this.value)">
|
||||
<option value="NONE" {% if user.company_role == 'NONE' %}selected{% endif %}>Brak</option>
|
||||
<option value="VIEWER" {% if user.company_role == 'VIEWER' %}selected{% endif %}>Podgląd</option>
|
||||
<option value="EMPLOYEE" {% if user.company_role == 'EMPLOYEE' %}selected{% endif %}>Pracownik</option>
|
||||
<option value="MANAGER" {% if user.company_role == 'MANAGER' %}selected{% endif %}>Zarządzający</option>
|
||||
</select>
|
||||
{% else %}
|
||||
<span style="color: var(--text-secondary);">-</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<select class="role-select"
|
||||
data-user-id="{{ user.id }}"
|
||||
@ -1884,6 +1899,40 @@ Lub format CSV, Excel, lista emaili..."></textarea>
|
||||
}
|
||||
}
|
||||
|
||||
async function changeCompanyRole(userId, newRole) {
|
||||
const selects = document.querySelectorAll(`select[data-user-id="${userId}"]`);
|
||||
const select = Array.from(selects).find(s => s.onchange?.toString().includes('changeCompanyRole'));
|
||||
if (!select) return;
|
||||
const originalValue = select.dataset.originalValue || select.value;
|
||||
|
||||
try {
|
||||
const response = await fetch('/admin/users-api/change-company-role', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
user_id: userId,
|
||||
company_role: newRole
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
select.dataset.originalValue = newRole;
|
||||
const labels = {'NONE': 'Brak', 'VIEWER': 'Podgląd', 'EMPLOYEE': 'Pracownik', 'MANAGER': 'Zarządzający'};
|
||||
showMessage(`Uprawnienia firmowe zmienione na: ${labels[newRole] || newRole}`, 'success');
|
||||
} else {
|
||||
select.value = originalValue;
|
||||
showMessage(data.error || 'Wystąpił błąd', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
select.value = originalValue;
|
||||
showMessage('Błąd połączenia', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function getRoleLabel(role) {
|
||||
const labels = {
|
||||
'UNAFFILIATED': 'Niezrzeszony',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user