mirror of
https://github.com/cssgunc/compass.git
synced 2025-04-20 18:40:17 -04:00
Connect delete frontend route to delete backend
This commit is contained in:
parent
9c970ca40e
commit
ccf2f1f83f
|
@ -60,12 +60,12 @@ def update(
|
||||||
return resource_svc.update(subject, resource)
|
return resource_svc.update(subject, resource)
|
||||||
|
|
||||||
|
|
||||||
@api.delete("", response_model=None, tags=["Resource"])
|
@api.delete("", response_model=dict, tags=["Resource"])
|
||||||
def delete(
|
def delete(
|
||||||
uuid: str,
|
uuid: str,
|
||||||
resource: Resource,
|
id: int,
|
||||||
user_svc: UserService = Depends(),
|
user_svc: UserService = Depends(),
|
||||||
resource_svc: ResourceService = Depends(),
|
resource_svc: ResourceService = Depends(),
|
||||||
):
|
):
|
||||||
subject = user_svc.get_user_by_uuid(uuid)
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
resource_svc.delete(subject, resource)
|
return resource_svc.delete(subject, id)
|
||||||
|
|
|
@ -19,7 +19,10 @@ openapi_tags = {
|
||||||
# TODO: Create custom exceptions
|
# TODO: Create custom exceptions
|
||||||
@api.post("", response_model=Service, tags=["Service"])
|
@api.post("", response_model=Service, tags=["Service"])
|
||||||
def create(
|
def create(
|
||||||
uuid: str, service: Service, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
|
uuid: str,
|
||||||
|
service: Service,
|
||||||
|
user_svc: UserService = Depends(),
|
||||||
|
service_svc: ServiceService = Depends(),
|
||||||
):
|
):
|
||||||
subject = user_svc.get_user_by_uuid(uuid)
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
return service_svc.create(subject, service)
|
return service_svc.create(subject, service)
|
||||||
|
@ -27,28 +30,42 @@ def create(
|
||||||
|
|
||||||
@api.get("", response_model=List[Service], tags=["Service"])
|
@api.get("", response_model=List[Service], tags=["Service"])
|
||||||
def get_all(
|
def get_all(
|
||||||
uuid: str, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
|
uuid: str,
|
||||||
|
user_svc: UserService = Depends(),
|
||||||
|
service_svc: ServiceService = Depends(),
|
||||||
):
|
):
|
||||||
subject = user_svc.get_user_by_uuid(uuid)
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
return service_svc.get_service_by_user(subject)
|
return service_svc.get_service_by_user(subject)
|
||||||
|
|
||||||
|
|
||||||
@api.get("/{name}", response_model=Service, tags=["Service"])
|
@api.get("/{name}", response_model=Service, tags=["Service"])
|
||||||
def get_by_name(
|
def get_by_name(
|
||||||
name: str, uuid: str, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
|
name: str,
|
||||||
|
uuid: str,
|
||||||
|
user_svc: UserService = Depends(),
|
||||||
|
service_svc: ServiceService = Depends(),
|
||||||
):
|
):
|
||||||
subject = user_svc.get_user_by_uuid(uuid)
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
return service_svc.get_service_by_name(name, subject)
|
return service_svc.get_service_by_name(name, subject)
|
||||||
|
|
||||||
|
|
||||||
@api.put("", response_model=Service, tags=["Service"])
|
@api.put("", response_model=Service, tags=["Service"])
|
||||||
def update(
|
def update(
|
||||||
uuid: str, service: Service, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
|
uuid: str,
|
||||||
|
service: Service,
|
||||||
|
user_svc: UserService = Depends(),
|
||||||
|
service_svc: ServiceService = Depends(),
|
||||||
):
|
):
|
||||||
subject = user_svc.get_user_by_uuid(uuid)
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
return service_svc.update(subject, service)
|
return service_svc.update(subject, service)
|
||||||
|
|
||||||
@api.delete("", response_model=None, tags=["Service"])
|
|
||||||
|
@api.delete("", response_model=dict, tags=["Service"])
|
||||||
def delete(
|
def delete(
|
||||||
uuid: str, service: Service, user_svc: UserService = Depends(), service_svc: ServiceService = Depends()
|
uuid: str,
|
||||||
|
id: int,
|
||||||
|
user_svc: UserService = Depends(),
|
||||||
|
service_svc: ServiceService = Depends(),
|
||||||
):
|
):
|
||||||
subject = user_svc.get_user_by_uuid(uuid)
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
service_svc.delete(subject, service)
|
return service_svc.delete(subject, id)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from ..services import UserService
|
from ..services import UserService
|
||||||
from ..models.user_model import User, UserTypeEnum
|
from ..models.user_model import User, UserTypeEnum
|
||||||
|
|
||||||
|
@ -46,3 +46,14 @@ def update_user(uuid: str, user: User, user_svc: UserService = Depends()):
|
||||||
raise Exception(f"Insufficient permissions for user {subject.uuid}")
|
raise Exception(f"Insufficient permissions for user {subject.uuid}")
|
||||||
|
|
||||||
return user_svc.update(user)
|
return user_svc.update(user)
|
||||||
|
|
||||||
|
|
||||||
|
@api.delete("/", response_model=dict, tags=["Users"])
|
||||||
|
def delete_user(uuid: str, id: int, user_svc: UserService = Depends()):
|
||||||
|
subject = user_svc.get_user_by_uuid(uuid)
|
||||||
|
|
||||||
|
try:
|
||||||
|
user_svc.delete_by_id(id, subject)
|
||||||
|
return {"message": "User deleted successfully"}
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
|
|
|
@ -93,7 +93,7 @@ class ResourceService:
|
||||||
self._session.commit()
|
self._session.commit()
|
||||||
return entity.to_model()
|
return entity.to_model()
|
||||||
|
|
||||||
def delete(self, subject: User, resource: Resource) -> None:
|
def delete(self, subject: User, id: int) -> None:
|
||||||
"""
|
"""
|
||||||
Delete resource based on id that the user has access to
|
Delete resource based on id that the user has access to
|
||||||
Parameters:
|
Parameters:
|
||||||
|
@ -106,15 +106,16 @@ class ResourceService:
|
||||||
raise ProgramNotAssignedException(
|
raise ProgramNotAssignedException(
|
||||||
f"User is not {UserTypeEnum.ADMIN}, cannot update service"
|
f"User is not {UserTypeEnum.ADMIN}, cannot update service"
|
||||||
)
|
)
|
||||||
query = select(ResourceEntity).where(ResourceEntity.id == resource.id)
|
|
||||||
|
query = select(ResourceEntity).where(ResourceEntity.id == id)
|
||||||
entity = self._session.scalars(query).one_or_none()
|
entity = self._session.scalars(query).one_or_none()
|
||||||
if entity is None:
|
if entity is None:
|
||||||
raise ResourceNotFoundException(
|
raise ResourceNotFoundException(f"No resource found with matching id: {id}")
|
||||||
f"No resource found with matching id: {resource.id}"
|
|
||||||
)
|
|
||||||
self._session.delete(entity)
|
self._session.delete(entity)
|
||||||
self._session.commit()
|
self._session.commit()
|
||||||
|
|
||||||
|
return {"message": "Resource deleted successfully"}
|
||||||
|
|
||||||
def get_by_slug(self, user: User, search_string: str) -> list[Resource]:
|
def get_by_slug(self, user: User, search_string: str) -> list[Resource]:
|
||||||
"""
|
"""
|
||||||
Get a list of resources given a search string that the user has access to
|
Get a list of resources given a search string that the user has access to
|
||||||
|
|
|
@ -90,12 +90,12 @@ class ServiceService:
|
||||||
|
|
||||||
return entity.to_model()
|
return entity.to_model()
|
||||||
|
|
||||||
def delete(self, subject: User, service: Service) -> None:
|
def delete(self, subject: User, id: int) -> None:
|
||||||
"""Deletes a service from the table."""
|
"""Deletes a service from the table."""
|
||||||
if subject.role != UserTypeEnum.ADMIN:
|
if subject.role != UserTypeEnum.ADMIN:
|
||||||
raise ProgramNotAssignedException(f"User is not {UserTypeEnum.ADMIN}")
|
raise ProgramNotAssignedException(f"User is not {UserTypeEnum.ADMIN}")
|
||||||
|
|
||||||
query = select(ServiceEntity).where(ServiceEntity.id == service.id)
|
query = select(ServiceEntity).where(ServiceEntity.id == id)
|
||||||
entity = self._session.scalars(query).one_or_none()
|
entity = self._session.scalars(query).one_or_none()
|
||||||
|
|
||||||
if entity is None:
|
if entity is None:
|
||||||
|
@ -105,3 +105,5 @@ class ServiceService:
|
||||||
|
|
||||||
self._session.delete(entity)
|
self._session.delete(entity)
|
||||||
self._session.commit()
|
self._session.commit()
|
||||||
|
|
||||||
|
return {"message": "Service deleted successfully"}
|
||||||
|
|
|
@ -4,6 +4,7 @@ from sqlalchemy.orm import Session
|
||||||
from ..entities.user_entity import UserEntity
|
from ..entities.user_entity import UserEntity
|
||||||
from ..models.user_model import User
|
from ..models.user_model import User
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
from ..models.enum_for_models import UserTypeEnum
|
||||||
|
|
||||||
|
|
||||||
class UserService:
|
class UserService:
|
||||||
|
@ -89,6 +90,22 @@ class UserService:
|
||||||
self._session.delete(obj)
|
self._session.delete(obj)
|
||||||
self._session.commit()
|
self._session.commit()
|
||||||
|
|
||||||
|
def delete_by_id(self, id: int, user: User) -> None:
|
||||||
|
"""
|
||||||
|
Delete a user by id
|
||||||
|
|
||||||
|
Args: the id of the user to delete
|
||||||
|
|
||||||
|
Returns: none
|
||||||
|
"""
|
||||||
|
|
||||||
|
if user.role != UserTypeEnum.ADMIN:
|
||||||
|
raise Exception(f"Insufficient permissions for user {user.uuid}")
|
||||||
|
|
||||||
|
obj = self._session.get(UserEntity, id)
|
||||||
|
self._session.delete(obj)
|
||||||
|
self._session.commit()
|
||||||
|
|
||||||
def update(self, user: User) -> User:
|
def update(self, user: User) -> User:
|
||||||
"""
|
"""
|
||||||
Updates a user
|
Updates a user
|
||||||
|
|
39
compass/app/api/resource/delete/route.ts
Normal file
39
compass/app/api/resource/delete/route.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function DELETE(request: Request) {
|
||||||
|
const apiEndpoint = `${process.env.NEXT_PUBLIC_API_HOST}/api/resource`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const uuid = searchParams.get("uuid");
|
||||||
|
const resource_id = searchParams.get("id");
|
||||||
|
|
||||||
|
console.log("Resource to be deleted", resource_id);
|
||||||
|
|
||||||
|
// Send the POST request to the backend
|
||||||
|
const response = await fetch(
|
||||||
|
`${apiEndpoint}?uuid=${uuid}&id=${resource_id}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: "Resource deleted successfully" },
|
||||||
|
{ status: response.status }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting resource:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to delete resource" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
39
compass/app/api/service/delete/route.ts
Normal file
39
compass/app/api/service/delete/route.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function DELETE(request: Request) {
|
||||||
|
const apiEndpoint = `${process.env.NEXT_PUBLIC_API_HOST}/api/service`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const uuid = searchParams.get("uuid");
|
||||||
|
const service_id = searchParams.get("id");
|
||||||
|
|
||||||
|
console.log("Service to be deleted", service_id);
|
||||||
|
|
||||||
|
// Send the POST request to the backend
|
||||||
|
const response = await fetch(
|
||||||
|
`${apiEndpoint}?uuid=${uuid}&id=${service_id}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: "Service deleted successfully" },
|
||||||
|
{ status: response.status }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting service:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to delete service" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
39
compass/app/api/user/delete/route.ts
Normal file
39
compass/app/api/user/delete/route.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function DELETE(request: Request) {
|
||||||
|
const apiEndpoint = `${process.env.NEXT_PUBLIC_API_HOST}/api/user`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const uuid = searchParams.get("uuid");
|
||||||
|
const user_id = searchParams.get("id");
|
||||||
|
|
||||||
|
console.log("User to be deleted", user_id);
|
||||||
|
|
||||||
|
// Send the POST request to the backend
|
||||||
|
const response = await fetch(
|
||||||
|
`${apiEndpoint}?uuid=${uuid}&id=${user_id}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: "User deleted successfully" },
|
||||||
|
{ status: response.status }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting user:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to delete user" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -143,6 +143,7 @@ export default function ResourceTable({
|
||||||
columns={columns}
|
columns={columns}
|
||||||
details={resourceDetails}
|
details={resourceDetails}
|
||||||
createEndpoint={`/api/resource/create?uuid=${user?.uuid}`}
|
createEndpoint={`/api/resource/create?uuid=${user?.uuid}`}
|
||||||
|
deleteEndpoint={`/api/resource/delete?uuid=${user?.uuid}`}
|
||||||
isAdmin={user?.role === "ADMIN"}
|
isAdmin={user?.role === "ADMIN"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { useState, useEffect, useRef } from "react";
|
||||||
import { RowOption } from "./RowOption";
|
import { RowOption } from "./RowOption";
|
||||||
|
|
||||||
interface RowOptionMenuProps {
|
interface RowOptionMenuProps {
|
||||||
onDelete?: () => void;
|
onDelete: () => void;
|
||||||
onHide: () => void;
|
onHide: () => void;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,13 @@ export const RowOptionMenu = ({
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
if (window.confirm("Are you sure you want to delete this item?")) {
|
||||||
|
onDelete();
|
||||||
|
setMenuOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
if (
|
if (
|
||||||
|
@ -60,18 +67,11 @@ export const RowOptionMenu = ({
|
||||||
(!menuOpen ? " invisible" : "")
|
(!menuOpen ? " invisible" : "")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{onDelete && (
|
|
||||||
<RowOption
|
<RowOption
|
||||||
icon={TrashIcon}
|
icon={TrashIcon}
|
||||||
label="Delete"
|
label="Delete"
|
||||||
onClick={onDelete}
|
onClick={handleDelete}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
{/* <RowOption
|
|
||||||
icon={ArrowUpRightIcon}
|
|
||||||
label="Open"
|
|
||||||
onClick={() => {}}
|
|
||||||
/> */}
|
|
||||||
<RowOption
|
<RowOption
|
||||||
icon={visible ? EyeSlashIcon : EyeIcon}
|
icon={visible ? EyeSlashIcon : EyeIcon}
|
||||||
label={visible ? "Hide" : "Show"}
|
label={visible ? "Hide" : "Show"}
|
||||||
|
|
|
@ -195,6 +195,7 @@ export default function ServiceTable({
|
||||||
columns={columns}
|
columns={columns}
|
||||||
details={serviceDetails}
|
details={serviceDetails}
|
||||||
createEndpoint={`/api/service/create?uuid=${user?.uuid}`}
|
createEndpoint={`/api/service/create?uuid=${user?.uuid}`}
|
||||||
|
deleteEndpoint={`/api/service/delete?uuid=${user?.uuid}`}
|
||||||
isAdmin={user?.role === "ADMIN"}
|
isAdmin={user?.role === "ADMIN"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -28,6 +28,7 @@ type TableProps<T extends DataPoint> = {
|
||||||
columns: ColumnDef<T, any>[];
|
columns: ColumnDef<T, any>[];
|
||||||
details: Details[];
|
details: Details[];
|
||||||
createEndpoint: string;
|
createEndpoint: string;
|
||||||
|
deleteEndpoint: string;
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,12 +80,24 @@ export default function Table<T extends DataPoint>({
|
||||||
columns,
|
columns,
|
||||||
details,
|
details,
|
||||||
createEndpoint,
|
createEndpoint,
|
||||||
|
deleteEndpoint,
|
||||||
isAdmin = false,
|
isAdmin = false,
|
||||||
}: TableProps<T>) {
|
}: TableProps<T>) {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<T>();
|
const columnHelper = createColumnHelper<T>();
|
||||||
|
|
||||||
|
const deleteRow = async (id: number) => {
|
||||||
|
const response = await fetch(`${deleteEndpoint}&id=${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.ok;
|
||||||
|
};
|
||||||
|
|
||||||
const createRow = async (newItem: any) => {
|
const createRow = async (newItem: any) => {
|
||||||
const response = await fetch(createEndpoint, {
|
const response = await fetch(createEndpoint, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -144,7 +157,23 @@ export default function Table<T extends DataPoint>({
|
||||||
id: "options",
|
id: "options",
|
||||||
cell: (props) => (
|
cell: (props) => (
|
||||||
<RowOptionMenu
|
<RowOptionMenu
|
||||||
onDelete={() => console.log("delete")}
|
onDelete={() => {
|
||||||
|
deleteRow(props.row.original.id).then(
|
||||||
|
(response) => {
|
||||||
|
if (response) {
|
||||||
|
setData((prev) =>
|
||||||
|
prev.filter(
|
||||||
|
(data) =>
|
||||||
|
data.id !==
|
||||||
|
props.row.original.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
alert("Failed to delete row!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}}
|
||||||
onHide={() => hideData(props.row.original.id)}
|
onHide={() => hideData(props.row.original.id)}
|
||||||
visible={props.row.original.visible}
|
visible={props.row.original.visible}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -143,6 +143,7 @@ export default function UserTable({ data, setData, user }: UserTableProps) {
|
||||||
columns={columns}
|
columns={columns}
|
||||||
details={userDetails}
|
details={userDetails}
|
||||||
createEndpoint={`/api/user/create?uuid=${user?.uuid}`}
|
createEndpoint={`/api/user/create?uuid=${user?.uuid}`}
|
||||||
|
deleteEndpoint={`/api/user/delete?uuid=${user?.uuid}`}
|
||||||
isAdmin={user?.role === "ADMIN"}
|
isAdmin={user?.role === "ADMIN"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user