fix
This commit is contained in:
@@ -84,3 +84,17 @@ async def assign_app_to_user(user_id: int, app_id: int, db: Session = Depends(da
|
|||||||
db.add(new_assignment)
|
db.add(new_assignment)
|
||||||
db.commit()
|
db.commit()
|
||||||
return {"message": "Assigned successfully"}
|
return {"message": "Assigned successfully"}
|
||||||
|
|
||||||
|
@router.delete("/{user_id}/assign/{app_id}")
|
||||||
|
async def remove_app_assignment(user_id: int, app_id: int, db: Session = Depends(database.get_db)):
|
||||||
|
assignment = db.query(models.UserApplication).filter(
|
||||||
|
models.UserApplication.user_id == user_id,
|
||||||
|
models.UserApplication.application_id == app_id
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if not assignment:
|
||||||
|
raise HTTPException(status_code=404, detail="Assignment not found")
|
||||||
|
|
||||||
|
db.delete(assignment)
|
||||||
|
db.commit()
|
||||||
|
return {"message": "Assignment removed"}
|
||||||
|
|||||||
@@ -48,19 +48,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<table id="users-table">
|
<table id="users-table">
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Username</th>
|
|
||||||
<th>Email</th>
|
|
||||||
<th>Admin</th>
|
|
||||||
<th>Active</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<!-- Users will be populated here -->
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ async function authFetch(url, options = {}) {
|
|||||||
...options.headers,
|
...options.headers,
|
||||||
"Authorization": `Bearer ${token}`
|
"Authorization": `Bearer ${token}`
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await fetch(url, { ...options, headers });
|
const res = await fetch(url, { ...options, headers });
|
||||||
if (res.status === 401) {
|
if (res.status === 401) {
|
||||||
logoutBtn.click();
|
logoutBtn.click();
|
||||||
@@ -102,21 +102,46 @@ async function authFetch(url, options = {}) {
|
|||||||
async function loadUsers() {
|
async function loadUsers() {
|
||||||
const res = await authFetch(`${API_URL}/users/`);
|
const res = await authFetch(`${API_URL}/users/`);
|
||||||
const users = await res.json();
|
const users = await res.json();
|
||||||
usersTableBody.innerHTML = users.map(user => `
|
usersTableBody.innerHTML = users.map(user => {
|
||||||
|
const appsList = user.applications.map(ua =>
|
||||||
|
`<span class="badge badge-info" style="margin-right: 5px; display: inline-flex; align-items: center;">
|
||||||
|
${ua.application.name}
|
||||||
|
<button onclick="removeAppAssignment(${user.id}, ${ua.application.id})" style="margin-left: 5px; color: red; font-weight: bold; border: none; background: none; cursor: pointer;">×</button>
|
||||||
|
</span>`
|
||||||
|
).join("");
|
||||||
|
|
||||||
|
return `
|
||||||
<tr>
|
<tr>
|
||||||
<td>${user.id}</td>
|
<td>${user.id}</td>
|
||||||
<td>${user.username}</td>
|
<td>${user.username}</td>
|
||||||
<td>${user.email}</td>
|
<td>${user.email}</td>
|
||||||
<td>${user.is_admin ? "Yes" : "No"}</td>
|
<td>${user.is_admin ? "Yes" : "No"}</td>
|
||||||
<td>${user.is_active ? "Yes" : "No"}</td>
|
<td>${user.is_active ? "Yes" : "No"}</td>
|
||||||
|
<td>${appsList}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-secondary" onclick='editUser(${JSON.stringify(user)})'>Edit</button>
|
<button class="btn btn-secondary" onclick='editUser(${JSON.stringify(user)})'>Edit</button>
|
||||||
<button class="btn btn-primary" onclick='assignAppModal(${user.id})'>Assign App</button>
|
<button class="btn btn-primary" onclick='assignAppModal(${user.id})'>Assign App</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`).join("");
|
`}).join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.removeAppAssignment = async (userId, appId) => {
|
||||||
|
if (!confirm("Are you sure you want to remove this app assignment?")) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await authFetch(`${API_URL}/users/${userId}/assign/${appId}`, {
|
||||||
|
method: "DELETE"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error("Failed to remove assignment");
|
||||||
|
|
||||||
|
loadUsers();
|
||||||
|
} catch (err) {
|
||||||
|
alert(err.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Apps
|
// Apps
|
||||||
async function loadApps() {
|
async function loadApps() {
|
||||||
const res = await authFetch(`${API_URL}/apps/`);
|
const res = await authFetch(`${API_URL}/apps/`);
|
||||||
@@ -170,12 +195,12 @@ userForm.addEventListener("submit", async (e) => {
|
|||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const err = await res.json();
|
const err = await res.json();
|
||||||
throw new Error(err.detail);
|
throw new Error(err.detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeModal("user-modal");
|
closeModal("user-modal");
|
||||||
loadUsers();
|
loadUsers();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -222,12 +247,12 @@ appForm.addEventListener("submit", async (e) => {
|
|||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ name, url })
|
body: JSON.stringify({ name, url })
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const err = await res.json();
|
const err = await res.json();
|
||||||
throw new Error(err.detail);
|
throw new Error(err.detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeModal("app-modal");
|
closeModal("app-modal");
|
||||||
loadApps();
|
loadApps();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -238,14 +263,14 @@ appForm.addEventListener("submit", async (e) => {
|
|||||||
// Assign App
|
// Assign App
|
||||||
window.assignAppModal = async (userId) => {
|
window.assignAppModal = async (userId) => {
|
||||||
document.getElementById("assign-user-id").value = userId;
|
document.getElementById("assign-user-id").value = userId;
|
||||||
|
|
||||||
// Load apps for select
|
// Load apps for select
|
||||||
const res = await authFetch(`${API_URL}/apps/`);
|
const res = await authFetch(`${API_URL}/apps/`);
|
||||||
const apps = await res.json();
|
const apps = await res.json();
|
||||||
const select = document.getElementById("assign-app-select");
|
const select = document.getElementById("assign-app-select");
|
||||||
select.innerHTML = '<option value="">Select Application</option>' +
|
select.innerHTML = '<option value="">Select Application</option>' +
|
||||||
apps.map(app => `<option value="${app.id}">${app.name}</option>`).join("");
|
apps.map(app => `<option value="${app.id}">${app.name}</option>`).join("");
|
||||||
|
|
||||||
openModal("assign-modal");
|
openModal("assign-modal");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -259,9 +284,9 @@ assignForm.addEventListener("submit", async (e) => {
|
|||||||
const res = await authFetch(`${API_URL}/users/${userId}/assign/${appId}`, {
|
const res = await authFetch(`${API_URL}/users/${userId}/assign/${appId}`, {
|
||||||
method: "POST"
|
method: "POST"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) throw new Error("Failed to assign");
|
if (!res.ok) throw new Error("Failed to assign");
|
||||||
|
|
||||||
closeModal("assign-modal");
|
closeModal("assign-modal");
|
||||||
alert("Assigned successfully");
|
alert("Assigned successfully");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user