Skip to content

Commit b0b2cea

Browse files
committed
populate search personas from ACL index
1 parent c72b7e1 commit b0b2cea

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

example-apps/internal-knowledge-search/app-ui/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ You need to set `REACT_APP_SEARCH_APP_NAME`, `REACT_APP_SEARCH_APP_API_KEY` and
117117
6. define mappings, as above in this README
118118
7. create search application
119119
8. enable cors: https://www.elastic.co/guide/en/elasticsearch/reference/master/search-application-security.html#search-application-security-cors-elasticsearch
120+
9. create an API key that has read access to `.search-acl-filter-search-sharepoint` and the search application (`sharepoint`)
120121

121122

122123
### Make it go

example-apps/internal-knowledge-search/app-ui/src/components/SearchApplicationSettings.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
1-
import React, {useState} from 'react';
1+
import React, {useEffect, useState} from 'react';
22
import {useDispatch, useSelector} from "react-redux";
33
import {updateSettings} from "../store/slices/searchApplicationSettingsSlice";
44
import {useToast} from "../contexts/ToastContext";
55
import {MessageType} from "./Toast";
66
import {RootState} from "../store/store";
77
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
88
import {faAngleDown, faAngleUp} from "@fortawesome/free-solid-svg-icons";
9+
import {json} from "react-router-dom";
910

1011

1112
const SearchApplicationSettings: React.FC = () => {
1213
const dispatch = useDispatch();
1314
const {appName, apiKey, searchEndpoint, searchPersona} = useSelector((state: RootState) => state.searchApplicationSettings);
1415
const {showToast} = useToast();
15-
const searchPersonaOptions = [
16-
"admin",
17-
"user"
18-
]
16+
17+
const fetchPersonaOptions = async () => {
18+
const identitiesIndex = ".search-acl-filter-search-sharepoint" //TODO fix hardcoded
19+
const identitiesPath = searchEndpoint+"/"+identitiesIndex+"/_search"
20+
const response = await fetch(identitiesPath, {headers: {"Authorization": "ApiKey "+apiKey}});
21+
const jsonData = await response.json();
22+
const ids = jsonData.hits.hits.map((hit) => hit._id)
23+
return ids
24+
}
25+
26+
const [searchPersonaOptions, setSearchPersonaOptions] = useState(["admin", "user"]);
27+
28+
useEffect(()=>{
29+
(async()=>{
30+
const fetched = await fetchPersonaOptions()
31+
setSearchPersonaOptions(fetched)
32+
})()
33+
},[])
34+
1935
const [isOpen, setIsOpen] = useState(false);
2036

2137
const toggleDropdown = () => {

example-apps/internal-knowledge-search/app-ui/src/pages/SearchPage.tsx

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import dataSourceToLogoPathLookup from '../config/dataSourceToLogoPathLookup.jso
1313
import documentsToSearchResultsMappings from '../config/documentsToSearchResultMappings.json';
1414
import {RootState} from "../store/store";
1515

16-
1716
const mapHitToSearchResult = (hit) => {
1817
const doc = hit._source;
1918
const dataSource = hit._index;
@@ -38,20 +37,82 @@ export default function SearchPage() {
3837
//TODO: simplify query state and move it to one place
3938
const [query, setQuery] = useState<string>("");
4039

41-
const {appName, apiKey, searchEndpoint} = useSelector((state: RootState) => state.searchApplicationSettings);
40+
const {appName, apiKey: adminApiKey, searchEndpoint, searchPersona} = useSelector((state: RootState) => state.searchApplicationSettings);
4241
const {sorts} = useSelector((state: RootState) => state.sort);
4342
const indexFilter = useSelector((state: RootState) => state.filter)["filters"]["Data sources"].values;
4443

4544

4645
useEffect(() => {
4746
const fetchData = async () => await handleSearchSubmit();
4847
fetchData();
49-
}, [indexFilter, sorts, appName, apiKey, searchEndpoint]);
48+
}, [indexFilter, sorts, appName, adminApiKey, searchEndpoint]);
49+
50+
const getOrCreateApiKey = async () => {
51+
if (searchPersona == "admin"){
52+
return adminApiKey
53+
}
54+
else {
55+
const permissions = ['foo'] // todo
56+
const apiKeyRoleDescriptor = {
57+
name: searchPersona,
58+
role_descriptors: {
59+
"dls-role": {
60+
"cluster": ["all"],
61+
"indices": [
62+
{
63+
"names": ["search-sharepoint"],
64+
"privileges": ["read"],
65+
"query": {
66+
"template": {
67+
"params": {
68+
"permissions": permissions
69+
},
70+
'source': `
71+
{
72+
"bool": {
73+
"filter": {
74+
"bool": {
75+
"should": [
76+
{
77+
"bool": {
78+
"must_not": {
79+
"exists": {
80+
"field": "_allow_access_control"
81+
}
82+
}
83+
}
84+
},
85+
{
86+
"terms": {
87+
"_allow_access_control": {{#toJson}}permissions{{/toJson}}
88+
}
89+
}
90+
]
91+
}
92+
}
93+
}
94+
}
95+
`
96+
}
97+
}
98+
}
99+
]
100+
}
101+
}
102+
}
103+
104+
// TODO Use fetch: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
105+
return "missing"
106+
}
107+
}
50108

51109
const handleSearchSubmit = async () => {
52110
try {
53111
setLoading(true);
54112

113+
const apiKey = await getOrCreateApiKey()
114+
showToast("API key is: "+apiKey)
115+
55116
const client = SearchApplicationClient(appName, searchEndpoint, apiKey, {
56117
"facets": {
57118
description: {

0 commit comments

Comments
 (0)