Skip to content

Commit

Permalink
feat: lookup subject section added
Browse files Browse the repository at this point in the history
  • Loading branch information
tolgaOzen committed May 25, 2023
1 parent 891ca33 commit db45567
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 72 deletions.
Binary file modified playground/public/main.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions playground/src/_assets/less/App.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ body {
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--background-base) !important;
}

code {
Expand Down
25 changes: 18 additions & 7 deletions playground/src/layout/sides/enforcement.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, {useState} from 'react'
import {Card, Radio} from 'antd';
import Check from "./particials/check";
import DataFiltering from "./particials/dataFiltering";
import EntityFilter from "./particials/entityFilter";
import SubjectFilter from "./particials/subjectFilter";

function Enforcement(props) {

Expand All @@ -11,18 +12,28 @@ function Enforcement(props) {
setSelected(value);
};

const renderComponent = () => {
switch (selected) {
case "check":
return <Check />;
case "entity-filter":
return <EntityFilter />;
case "subject-filter":
return <SubjectFilter />;
default:
return null;
}
}

return (
<Card title={props.title} className="h-screen" style={{display: props.hidden && 'none'}}>
<div className="p-12">
<Radio.Group defaultValue="check" onChange={onChange} value={selected}>
<Radio value="check">Check</Radio>
<Radio value="data-filtering">Data Filtering</Radio>
<Radio value="entity-filter">Entity Filter</Radio>
<Radio value="subject-filter">Subject Filter</Radio>
</Radio.Group>
{selected === "check" ?
<Check/>
:
<DataFiltering/>
}
{renderComponent()}
</div>
</Card>
)
Expand Down
6 changes: 3 additions & 3 deletions playground/src/layout/sides/particials/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ function Check(props) {
setError("")
setLoading(true)
CheckPermission(entity, permission, subject).then(res => {
// if (res[1] != null) {
// setError(res[1].replaceAll('_', ' '))
// }
if (res[1] != null) {
setError(res[1].replaceAll('_', ' '))
}
setResult(res[0])
setLoading(false)
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, {useState} from 'react'
import {Alert, Button, Input, Result, Spin, Typography} from "antd";
import {InfoCircleOutlined} from "@ant-design/icons";
import {FilterData} from "../../../services/permission";
import {Alert, Button, Input, Spin, Typography} from "antd";
import {FilterEntity} from "../../../services/permission";

const {Paragraph} = Typography;

function DataFiltering(props) {
function EntityFilter(props) {

// loading
const [loading, setLoading] = useState(false);
Expand All @@ -15,24 +14,29 @@ function DataFiltering(props) {
const [queryIsValid, setQueryIsValid] = useState(false);

const isValid = (value) => {
let s = value.split(" ")
if (s.length !== 3) {
return false
// Check if value is a string
if (typeof value !== 'string') {
return false;
}

let sIsValid = false
let sb = s[1].split(":")
if (sb.length !== 2) {
return false
} else {
if (sb[0] === "" || sb[1] === "") {
return false
} else {
sIsValid = true
}
// Split value by space
const parts = value.split(" ");

// Ensure there are exactly three parts
if (parts.length !== 3) {
return false;
}

return sIsValid;
// Split the second part by colon
const subParts = parts[1].split(":");

// Ensure there are exactly two sub-parts and neither are empty strings
if (subParts.length !== 2 || subParts[0] === "" || subParts[1] === "") {
return false;
}

// If all checks pass, the input is valid
return true;
}

const onQueryChange = (e) => {
Expand All @@ -48,24 +52,49 @@ function DataFiltering(props) {
}

const parseQuery = (value) => {
let s = value.split(" ")
setEntityType(s[0])
// Ensure that value is a string to avoid unexpected type errors.
if (typeof value !== 'string') {
throw new Error('Value must be a string');
}

let sb = s[1].split(":")
let userSet = sb[1].split("#")
if (userSet.length === 2) {
// Split the value string into parts.
const parts = value.split(" ");

// Ensure the string has exactly 3 parts.
if (parts.length !== 3) {
throw new Error('Value must be composed of exactly three parts');
}

// Set the entity type using the first part.
setEntityType(parts[0]);

// Split the second part on ":"
const subjectpart = parts[1].split(":");

// Ensure the second part has exactly 2 parts when split on ":".
if (subjectpart.length !== 2) {
throw new Error('Second part must be two terms separated by a ":" symbol');
}

// Split the user set on "#"
const userset = subjectpart[1].split("#");
if (userset.length === 2) {
setSubject({
type: sb[0],
id: userSet[0],
relation: userSet[1],
})
} else {
type: subjectpart[0],
id: userset[0],
relation: userset[1],
});
} else if (userset.length === 1) {
setSubject({
type: sb[0],
id: sb[1],
})
type: subjectpart[0],
id: subjectpart[1],
});
} else {
throw new Error('Invalid format for user set');
}
setPermission(s[2])

// Set the permission using the third part.
setPermission(parts[2]);
}

const [result, setResult] = useState(null);
Expand All @@ -78,7 +107,7 @@ function DataFiltering(props) {
const onQuery = () => {
setError("")
setLoading(true)
FilterData(entityType,permission, subject ).then(res => {
FilterEntity(entityType, permission, subject).then(res => {
if (res[1] != null) {
setError(res[1].replaceAll('_', ' '))
}
Expand Down Expand Up @@ -125,4 +154,4 @@ function DataFiltering(props) {
</Spin>)
}

export default DataFiltering
export default EntityFilter
157 changes: 157 additions & 0 deletions playground/src/layout/sides/particials/subjectFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import React, {useState} from 'react'
import {Alert, Button, Input, Spin, Typography} from "antd";
import {FilterEntity, FilterSubject} from "../../../services/permission";

const {Paragraph} = Typography;

function SubjectFilter(props) {

// loading
const [loading, setLoading] = useState(false);

// error & validations
const [error, setError] = useState("");
const [queryIsValid, setQueryIsValid] = useState(false);

const isValid = (value) => {
// Ensure that value is a string to avoid unexpected type errors.
if (typeof value !== 'string') {
return false;
}

let parts = value.split(" ");

// Value should have exactly 3 parts separated by space.
if (parts.length !== 3) {
return false;
}

let subpart = parts[0].split("#");

// The second part of the string should be split into two by a "#" symbol.
if (subpart.length === 2) {
return subpart[1] !== "";
}

let entitypart = parts[1].split(":");

// The second part of the string should also be split into two by a ":" symbol.
return !(entitypart.length !== 2 || entitypart[0] === "" || entitypart[1] === "");
}

const [result, setResult] = useState(null);

// tuple
const [entity, setEntity] = useState({});
const [permission, setPermission] = useState("");
const [subjectReference, setSubjectReference] = useState({});

const onQueryChange = (e) => {
setResult(null)
setEntity({})
setSubjectReference({})
setPermission("")
setQueryIsValid(false)
if (isValid(e.target.value.trim())) {
parseQuery(e.target.value.trim())
setQueryIsValid(true)
}
}

const onQuery = () => {
setError("")
setLoading(true)
FilterSubject(entity, permission, subjectReference).then(res => {
if (res[1] != null) {
setError(res[1].replaceAll('_', ' '))
}
setResult(res[0])
setLoading(false)
})
}

const parseQuery = (value) => {
// Ensure value is a string to avoid type errors.
if (typeof value !== 'string') {
throw new Error('Value must be a string');
}

// Split the value string into parts.
const parts = value.split(" ");

// Ensure the string has exactly 3 parts.
if (parts.length !== 3) {
throw new Error('Value must be composed of exactly three parts');
}

// Handle the first part (SubjectReference).
const subjectPart = parts[0].split("#");
if (subjectPart.length === 2) {
setSubjectReference({
type: subjectPart[0],
relation: subjectPart[1],
});
} else if (subjectPart.length === 1) {
setSubjectReference({
type: subjectPart[0],
relation: "",
});
} else {
throw new Error('First part must be one or two terms separated by a "#" symbol');
}

// Handle the second part (Entity).
const entityPart = parts[1].split(":");
if (entityPart.length !== 2) {
throw new Error('Second part must be two terms separated by a ":" symbol');
} else {
setEntity({
type: entityPart[0],
id: entityPart[1],
});
}

// Handle the third part (Permission).
setPermission(parts[2]);
}

return (
<Spin spinning={loading}>
<div className="pt-12">
{error !== "" &&
<Alert message={error} type="error" showIcon className="mb-12"/>
}
<Input.Group>
<Input
style={{
width: '85%',
}}
onChange={onQueryChange}
placeholder="user document:1 edit"
className="border-radius-right-none border-right-none"
size="large"
/>
<Button style={{
width: '15%',
}} type="primary" size="large" className="border-radius-left-none" disabled={!queryIsValid}
onClick={onQuery}>Filter</Button>
</Input.Group>
{result != null ?
<>
<div className="pt-12">
<span className="text-grey">Result:</span>
<Paragraph className="pt-6 pl-2 text-primary font-w-600">
[{result.join(', ')}]
</Paragraph>
</div>
{/*user repository:1 edit*/}
</>
:
<Paragraph className="pt-6 pl-2"><blockquote>entity based access check takes form of Which subjects does perform an action X to entity E? This option is best for filtering data or bulk permission checks. A real world example would be: <span className="text-grey font-w-600">user document:1 edit</span></blockquote></Paragraph>
}
</div>
</Spin>
)
}

export default SubjectFilter
1 change: 1 addition & 0 deletions playground/src/loadWasm/wasmTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ declare global {
Go: any;
check: (query: string)=>any[]
lookupEntity: (query: string)=>any[]
lookupSubject: (query: string)=>any[]
writeSchema: (schema: string)=>any[]
readSchema: ()=>any[]
writeTuple: (tuple: string)=>any[]
Expand Down

0 comments on commit db45567

Please sign in to comment.