Skip to content

Commit

Permalink
Merge pull request #104 from amosproj/create-policy-button
Browse files Browse the repository at this point in the history
Added a button to create a policy
  • Loading branch information
daku-de authored Jul 14, 2024
2 parents 6a95ec7 + 8ed7461 commit 574fee1
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 10 deletions.
29 changes: 29 additions & 0 deletions src/frontend/actions/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,35 @@ export async function createAsset(file: FileInfo): Promise<boolean> {
}
}

export async function createPolicy(name: string, description: string): Promise<boolean> {
try {
const response = await fetch('/api/createPolicy', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: name,
description: description
})
});

if (!response.ok) {
throw new Error(`API call failed with status ${response.status}`);
}

const data = await response.json();

if (data.error) {
throw new Error(data.error);
}

return true;
} catch (err) {
throw new Error("Error creating policy: ", err);
}
}

export async function createContractDefinition(contractId: string, policyId: string, assetId: string): Promise<boolean> {
try {
const response = await fetch('/api/createContractDefinition', {
Expand Down
12 changes: 7 additions & 5 deletions src/frontend/app/api/connector-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,16 @@ export async function registerDataplaneProvider(dataplaneId: string) {
}
};

function generateCreatePolicy(policyId: string) {
// TODO: acutal policy with permission/prohibition/obligation
function generateCreatePolicy(name: string, description: string) {
const createPolicy = {
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/",
"odrl": "http://www.w3.org/ns/odrl/2/"
},
"@id": policyId,
"privateProperties": {
"name": name,
"description": description
},
"policy": {
"@context": "http://www.w3.org/ns/odrl.jsonld",
"@type": "Set",
Expand All @@ -251,7 +253,7 @@ function generateCreatePolicy(policyId: string) {
return createPolicy;
};

export async function createPolicy(policyId: string) {
export async function createPolicy(name: string, description: string) {
try {
const result = await fetch(connectorManagementUrl + "v2/policydefinitions", {
method: 'POST',
Expand All @@ -260,7 +262,7 @@ export async function createPolicy(policyId: string) {
'Content-Type': 'application/json',
'X-API-Key': authenticationPassword
},
body: JSON.stringify(generateCreatePolicy(policyId)),
body: JSON.stringify(generateCreatePolicy(name, description)),
});
if (!result.ok) {
throw new Error(`HTTP Error! Status: ${result.status}`);
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/app/api/createPolicy/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export const POST = auth(async function POST(req) {
return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
}
const body = await req.json();
const { policyId } = body;
const result = await createPolicy(policyId);
const { name, description } = body;
const result = await createPolicy(name, description);
return NextResponse.json(result);
} catch (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/app/api/getPolicies/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const GET = auth(async function GET(req) {
}
const data = await getPolicies();
const policies = data.map((item: any) => ({
name: item.privateProperties?.name || 'Unnamed Policy',
name: item.privateProperties?.name || 'Default Policy',
description: item.privateProperties?.description || 'No description provided',
id: item["@id"]
}));
Expand Down
14 changes: 12 additions & 2 deletions src/frontend/app/dashboard/upload/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use client';
import React, { useState, useEffect } from 'react';

import { ArrowPathIcon, TrashIcon, CloudArrowDownIcon, XCircleIcon, CheckCircleIcon } from '@heroicons/react/24/outline';
import { createAsset, createContractDefinition, getAssets, uploadFile, getPolicies, fetchCatalogItems, deleteAsset, deleteContractDefinition, deleteFile, getContractDefinitions } from '@/actions/api';
import { FileInfo, Policy, Asset, CatalogItem } from "@/data/interface/file";
import PolicyDropdown from './PolicyDropdown';
import PolicyModal from './policyModal';

const MAX_FILE_SIZE_MB = 10;

Expand All @@ -12,6 +14,7 @@ const UploadPage: React.FC = () => {
const [title, setTitle] = useState('');
const [policy, setPolicy] = useState<Policy | null>(null);
const [showModal, setShowModal] = useState(false);
const [showPolicyModal, setShowPolicyModal] = useState<boolean>(false);
const [errorMessage, setErrorMessage] = useState('');
const [files, setFiles] = useState<Asset[]>([]);
const [contractDefinitions, setContractDefinitions] = useState<[]>([]);
Expand Down Expand Up @@ -175,16 +178,19 @@ const UploadPage: React.FC = () => {

return (
<div className="p-6">
<div className="flex justify-end mb-4">
<div className="flex justify-end mb-4 gap-2">
<button
onClick={fetchAssets}
className="px-4 py-2 mr-2 bg-neonBlue rounded flex items-center"
className="px-4 py-2 bg-neonBlue rounded flex items-center"
>
<ArrowPathIcon className="w-5 h-5" />
</button>
<button onClick={() => setShowModal(true)} className="px-4 py-2 bg-neonGreen rounded">
Upload File
</button>
<button onClick={() => setShowPolicyModal(true)} className="px-4 py-2 bg-neonGreen rounded">
Create Policy
</button>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
Expand Down Expand Up @@ -238,6 +244,8 @@ const UploadPage: React.FC = () => {
</table>
</div>

<PolicyModal isOpen={showPolicyModal} onClose={() => setShowPolicyModal(false)} />

{showModal && (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 text-black">
<div className="bg-white p-6 rounded">
Expand Down Expand Up @@ -289,6 +297,8 @@ const UploadPage: React.FC = () => {
</form>
</div>
</div>


)}
</div>
);
Expand Down
75 changes: 75 additions & 0 deletions src/frontend/app/dashboard/upload/policyModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use client';
import { createPolicy } from '@/actions/api';
import React, { useState, useEffect, FormEvent } from 'react';

interface PolicyModalProps {
isOpen: boolean;
onClose: () => void;
}

const PolicyModal: React.FC<PolicyModalProps> = ({ isOpen, onClose }) => {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [errorMessage, setErrorMessage] = useState("");

const handleCreate = async (e: FormEvent) => {
e.preventDefault();
try {
setErrorMessage("");
await createPolicy(name, description);
onClose();
} catch(err) {
setErrorMessage("There was a problem creating the policy.");
}
}

if(!isOpen) {
return null;
}

return (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 text-black">
<div className="bg-white p-6 rounded">
<form onSubmit={handleCreate} className="flex gap-4 flex-col">
<div>
<label htmlFor="name" className="block mb-2 text-sm font-medium">Policy Name</label>
<input
type="text"
name="name"
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
className="border border-gray-300 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500"
required
/>
</div>
<div>
<label htmlFor="description" className="block mb-2 text-sm font-medium">Description</label>
<textarea
name="description"
id="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
className="border border-gray-300 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500"
/>
</div>

{errorMessage && <p className="text-red-500">{errorMessage}</p>}

<div className="flex justify-end">
<button onClick={() => onClose()} className="px-4 py-2 bg-gray-500 text-white rounded mr-2">
Cancel
</button>
<button type="submit" className="px-4 py-2 bg-green-500 text-white rounded">
Create
</button>
</div>
</form>
</div>
</div>

)
}


export default PolicyModal;

0 comments on commit 574fee1

Please sign in to comment.