Skip to content

Commit

Permalink
473 deeplink fix (#474)
Browse files Browse the repository at this point in the history
* fix deeplink

* deep link in web main

* lint
---------

Signed-off-by: Spyros <[email protected]>
  • Loading branch information
northdpole authored Jan 8, 2024
1 parent 645c0a8 commit 4369366
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 33 deletions.
68 changes: 43 additions & 25 deletions application/frontend/src/pages/Deeplink/Deeplink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { useLocation, useParams } from 'react-router-dom';
import { LoadingAndErrorIndicator } from '../../components/LoadingAndErrorIndicator';
import { useEnvironment } from '../../hooks';
import { Document } from '../../types';
import { Standard } from '../Standard/Standard';

export const Deeplink = () => {
let { type, nodeName, section, subsection, tooltype, sectionID } = useParams();
let { type, nodeName, section, subsection, tooltype, sectionID, sectionid } = useParams();
const { apiUrl } = useEnvironment();
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | Object | null>(null);
Expand All @@ -17,26 +18,36 @@ export const Deeplink = () => {
subsection = subsection ? subsection : new URLSearchParams(search).get('subsection');
tooltype = tooltype ? tooltype : new URLSearchParams(search).get('tooltype');
sectionID = sectionID ? sectionID : new URLSearchParams(search).get('sectionID');
sectionid = sectionID ? sectionID : new URLSearchParams(search).get('sectionid');
if (!type) {
// Backwards compatible fix, the url used to be /deeplink/:nodename, new url is /deeplink/:type/:nodename
type = 'Standard';
}

var url =
`${apiUrl}/${type}/${nodeName}` +
(section != null ? `?section=${section}&` : '') +
(subsection != null ? `subsection=${subsection}&` : '') +
(tooltype != null ? `tooltype=${tooltype}&` : '') +
(sectionID != null ? `sectionID=${sectionID}&` : '');
var apiCall = new URL(`${apiUrl}/${type}/${nodeName}?`);

if (section != null) {
apiCall.searchParams.append('section', section);
}
if (subsection != null) {
apiCall.searchParams.append('subsection', subsection);
}
if (tooltype != null) {
apiCall.searchParams.append('tooltype', tooltype);
}
if (sectionID != null) {
apiCall.searchParams.append('sectionID', sectionID);
} else if (sectionid != null) {
apiCall.searchParams.append('sectionID', sectionid);
}
useEffect(() => {
window.scrollTo(0, 0);
setLoading(true);
axios
.get(url)
.get(apiCall.toString())
.then(function (response) {
setError(null);
setData(response.data?.standard);
setData(response.data?.standards);
})
.catch(function (axiosError) {
if (axiosError.response.status === 404) {
Expand All @@ -49,25 +60,32 @@ export const Deeplink = () => {
setLoading(false);
});
}, [type, nodeName]);

const documents = data || [];
return (
<>

var redirectTo = window.location.href;
if (documents) {
for (const standard of documents) {
if (standard.hyperlink && standard.hyperlink?.length > 0) {
redirectTo = standard.hyperlink;
}
}
}
if (!error && !loading && redirectTo != window.location.href) {
return (
<div className="standard-page">
<h4 className="standard-page__heading">{nodeName}</h4>
<LoadingAndErrorIndicator loading={loading} error={error} />
<h4>Redirecting to:</h4>
{window.location.href}
{(window.location.href = redirectTo)}
</div>
);
} else {
return (
<div className="standard-page">
<h4 className="standard-page__heading">{nodeName}</h4>
<LoadingAndErrorIndicator loading={loading} error={error} />
{!error &&
!loading &&
documents.map(
(standard, i) =>
// console.log( (standard && standard.hyperlink && standard.hyperlink.length > 0) ? standard.hyperlink : window.location.href)
(window.location.href =
standard && standard.hyperlink && standard.hyperlink.length > 0
? standard.hyperlink
: window.location.href)
)}
</div>
;
</>
);
);
}
};
111 changes: 103 additions & 8 deletions application/tests/web_main_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random
import string
import re
import json
import unittest
Expand Down Expand Up @@ -80,15 +82,18 @@ def test_extend_cre_with_tag_links(self) -> None:
)
),
"cc": cres["cc"],
"cd": cres["cd"]
.add_link(
defs.Link(
ltype=defs.LinkTypes.PartOf, document=cres["ca"].shallow_copy()
"cd": (
cres["cd"]
.add_link(
defs.Link(
ltype=defs.LinkTypes.PartOf, document=cres["ca"].shallow_copy()
)
)
)
.add_link(
defs.Link(
ltype=defs.LinkTypes.Contains, document=cres["cb"].shallow_copy()
.add_link(
defs.Link(
ltype=defs.LinkTypes.Contains,
document=cres["cb"].shallow_copy(),
)
)
),
}
Expand Down Expand Up @@ -711,3 +716,93 @@ def test_gap_analysis_weak_links_response(self, db_mock) -> None:
)
self.assertEqual(200, response.status_code)
self.assertEqual(expected, json.loads(response.data))

def test_deeplink(self) -> None:
self.maxDiff = None
collection = db.Node_collection()
with self.app.test_client() as client:
response = client.get(
f"/rest/v1/deeplink/{''.join(random.choice(string.ascii_letters) for i in range(10))}",
)
self.assertEqual(404, response.status_code)

cres = {
"ca": defs.CRE(id="1", description="CA", name="CA", tags=["ta"]),
"cd": defs.CRE(id="2", description="CD", name="CD", tags=["td"]),
"cb": defs.CRE(id="3", description="CB", name="CB", tags=["tb"]),
}
standards = {
"cwe0": defs.Standard(name="CWE", sectionID="456"),
"ASVS": defs.Standard(
name="ASVS",
section="sectionASVS",
sectionID="v0.1.2",
hyperlink="https://github.com/owasp/asvs/blah",
),
}
cres["ca"].add_link(
defs.Link(
ltype=defs.LinkTypes.Contains, document=cres["cd"].shallow_copy()
)
)
cres["cb"].add_link(
defs.Link(
ltype=defs.LinkTypes.Contains, document=cres["cd"].shallow_copy()
)
)
cres["cd"].add_link(defs.Link(document=standards["cwe0"]))
cres["cb"].add_link(defs.Link(document=standards["ASVS"]))

dca = collection.add_cre(cres["ca"])
dcb = collection.add_cre(cres["cb"])
dcd = collection.add_cre(cres["cd"])
dasvs = collection.add_node(standards["ASVS"])
dcwe = collection.add_node(standards["cwe0"])
collection.add_internal_link(
group=dca, cre=dcd, type=defs.LinkTypes.Contains
)
collection.add_internal_link(
group=dcb, cre=dcd, type=defs.LinkTypes.Contains
)

collection.add_link(dcb, dasvs)
collection.add_link(dcd, dcwe)

response = client.get("/rest/v1/deeplink/CWE?sectionid=456")
self.assertEqual(404, response.status_code)

response = client.get("/rest/v1/deeplink/ASVS?sectionid=v0.1.2")
location = ""
for head in response.headers:
if head[0] == "Location":
location = head[1]
self.assertEqual(location, standards["ASVS"].hyperlink)
self.assertEqual(302, response.status_code)

response = client.get("/rest/v1/deeplink/ASVS?sectionID=v0.1.2")
location = ""
for head in response.headers:
if head[0] == "Location":
location = head[1]
self.assertEqual(location, standards["ASVS"].hyperlink)
self.assertEqual(302, response.status_code)

response = client.get(
f'/rest/v1/deeplink/ASVS?section={standards["ASVS"].section}'
)
location = ""
for head in response.headers:
if head[0] == "Location":
location = head[1]
self.assertEqual(location, standards["ASVS"].hyperlink)
self.assertEqual(302, response.status_code)

response = client.get(
f'/rest/v1/deeplink/ASVS?section={standards["ASVS"].section}&sectionID={standards["ASVS"].sectionID}'
)
location = ""
for head in response.headers:
if head[0] == "Location":
location = head[1]
self.assertEqual(location, standards["ASVS"].hyperlink)
self.assertEqual(302, response.status_code)
32 changes: 32 additions & 0 deletions application/web/web_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,38 @@ def smartlink(
return abort(404, "Document does not exist")


@app.route("/rest/v1/deeplink/<ntype>/<name>", methods=["GET"])
@app.route("/rest/v1/deeplink/<name>", methods=["GET"])
def deeplink(name: str, ntype: str = "") -> Any:
database = db.Node_collection()
opt_section = request.args.get("section")
opt_sectionID = request.args.get("sectionID")
opt_sectionid = request.args.get("sectionid")
opt_version = request.args.get("version")
opt_subsection = request.args.get("subsection")

if opt_section:
opt_section = urllib.parse.unquote(opt_section)
if opt_sectionID:
opt_sectionID = urllib.parse.unquote(opt_sectionID)
elif opt_sectionid:
opt_sectionID = urllib.parse.unquote(opt_sectionid)

nodes = None
nodes = database.get_nodes(
name=name,
section=opt_section,
subsection=opt_subsection,
version=opt_version,
sectionID=opt_sectionID,
)
for node in nodes:
if len(node.hyperlink) > 0:
return redirect(node.hyperlink)

return abort(404)


@app.before_request
def before_request():
if os.environ.get("INSECURE_REQUESTS"):
Expand Down

0 comments on commit 4369366

Please sign in to comment.