Skip to content

Commit bc0de58

Browse files
Valecantchicco785
andauthored
Fix 0.5 (#91)
* passing token to delete * tenantSelection if only super Admin * tenant page link not displayed if user has no access to it * config when a tenant is added * fix form console errors * initial state of the component changed * update docs Co-authored-by: Federico M. Facca <chicco785@users.noreply.github.com>
1 parent 041615f commit bc0de58

File tree

10 files changed

+131
-47
lines changed

10 files changed

+131
-47
lines changed

.env.docker

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
REACT_APP_URI=http://localhost:3000/
22
REACT_APP_ANUBIS_API_URL=http://localhost:8085/
33
REACT_APP_CONFIGURATION_API_URL=http://localhost:4000/configuration
4-
REACT_APP_OIDC_ISSUER=http://localhost:8080/realms/default
4+
REACT_APP_OIDC_ISSUER=http://keycloak:8080/realms/default
55
REACT_APP_OIDC_CLIENT=configuration
66
REACT_APP_OIDC_SCOPE="openid profile email"
77
REACT_APP_IMAGE_SIZE=20
88
REACT_APP_LOG_LEVEL=debug
9-
REACT_APP_KEYCLOACK_ADMIN=http://localhost:8080/admin/realms/default
9+
REACT_APP_KEYCLOACK_ADMIN=http://keycloak:8080/admin/realms/default
1010

1111
MONGO_DB=mongodb://mongo:27017/graphql
1212
CONFIGURATION_API_PORT=4000

README.md

+15
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ To run this demo you'll need to have the following installed:
6161
To run the demo in your local environment, you need to create a `.env`
6262
(an example file is provided [.env.docker](.env.docker)).
6363

64+
To be able to create tenants, the hostname of the token issuer (Keycloak) in
65+
docker and in your local system, needs to be the same, to ensure that,
66+
add the following entry in your `/etc/hosts`:
67+
68+
```console
69+
127.0.0.1 keycloak
70+
```
71+
6472
To deploy the demo that includes the Auth UI, Anubis, the Configuration API
6573
and Keycloak, run the following script:
6674

@@ -148,6 +156,13 @@ the `src/env.js` file:
148156
$ npx generate-env-getter js
149157
```
150158

159+
> **NOTE:** Tenant creation won't work due to the issuer different between
160+
docker (`keycloak`) and your local environment (`localhost`), you can solve this
161+
by adding and entry in your `/etc/hosts` file that points `127.0.0.1` to
162+
`keycloak` and using using `keycloak` as hostname in
163+
`REACT_APP_KEYCLOACK_ADMIN` and `REACT_APP_OIDC_ISSUER`. This is already
164+
the default value in case of `.env.docker`.
165+
151166
### Management UI
152167

153168
To start the locally the Management UI:

RELEASE_NOTES.md

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
- Fixed filters margin top
1616
- Filters naming
1717
- Filters behavior when another tenant is selected
18+
- Token on TenantDelete
19+
- Display Tenant selector if only superAdmin
20+
_ fix tenantPreferencies creation when a new tenant is created
1821

1922
### Documentation
2023

src/App.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,10 @@ export default class App extends Component {
356356
name: 'Tenant',
357357
route: '/Tenant',
358358
icon: <InboxIcon></InboxIcon>,
359-
isAdmin: <AuthorizedElement tokenDecoded={this.state.tokenData} iSuperAdmin={true} />
359+
withPermissions: true
360360
},
361-
{ name: 'Service', route: '/Service', icon: <InboxIcon></InboxIcon>, isAdmin: 'not-necessary' },
362-
{ name: 'Policy', route: '/Policy', icon: <InboxIcon></InboxIcon>, isAdmin: 'not-necessary' }
361+
{ name: 'Service', route: '/Service', icon: <InboxIcon></InboxIcon>, withPermissions: false },
362+
{ name: 'Policy', route: '/Policy', icon: <InboxIcon></InboxIcon>, withPermissions: false }
363363
];
364364

365365
componentDidMount() {
@@ -448,15 +448,22 @@ export default class App extends Component {
448448
<Divider />
449449
<List>
450450
{this.links.map((thisItem, index) =>
451-
thisItem.isAdmin !== false ? (
451+
thisItem.withPermissions === false ? (
452452
<NavLink to={thisItem.route} key={index}>
453453
<ListItem button key={thisItem.name}>
454454
<ListItemIcon>{thisItem.icon}</ListItemIcon>
455455
<ListItemText primary={thisItem.name} />
456456
</ListItem>
457457
</NavLink>
458458
) : (
459-
''
459+
<AuthorizedElement tokenDecoded={this.state.tokenData} iSuperAdmin={true}>
460+
<NavLink to={thisItem.route} key={index}>
461+
<ListItem button key={thisItem.name}>
462+
<ListItemIcon>{thisItem.icon}</ListItemIcon>
463+
<ListItemText primary={thisItem.name} />
464+
</ListItem>
465+
</NavLink>
466+
</AuthorizedElement>
460467
)
461468
)}
462469
</List>

src/components/policy/policiesTable.js

+1
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ export default function PoliciesTable({ data, getData, access_modes, tenantName,
501501
<DeleteDialog
502502
open={openDeleteDialog}
503503
env={env}
504+
token={token}
504505
onClose={handleCloseDeleteDialog}
505506
getData={getData}
506507
data={{

src/components/shared/cards.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const RadiusDiv = styled(Box)(({ theme }) => ({
2020
maxWidth: 550
2121
}));
2222

23-
export default function DashboardCard({ pageType, data, getData, seTenant, colors, tenantName_id, env }) {
23+
export default function DashboardCard({ pageType, data, getData, seTenant, colors, tenantName_id, env, token }) {
2424
const [subpathOpen, setSubpathOpen] = React.useState(false);
2525
const anubisURL = typeof env !== 'undefined' ? env.ANUBIS_API_URL : '';
2626

@@ -71,6 +71,7 @@ export default function DashboardCard({ pageType, data, getData, seTenant, color
7171
}
7272
action={
7373
<MultifunctionButton
74+
token={token}
7475
data={data}
7576
env={env}
7677
getData={getData}

src/components/shared/messages/cardDelete.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const DialogRounded = styled(Dialog)(() => ({
2020
}
2121
}));
2222

23-
export default function DeleteDialog({ open, onClose, getData, data, env }) {
23+
export default function DeleteDialog({ open, onClose, getData, data, env, token }) {
2424
typeof env === 'undefined' ? log.setDefaultLevel('debug') : log.setLevel(env.LOG_LEVEL);
2525
const anubisURL = typeof env !== 'undefined' ? env.ANUBIS_API_URL : '';
2626

@@ -94,8 +94,9 @@ export default function DeleteDialog({ open, onClose, getData, data, env }) {
9494
data.setSelected([]);
9595
onClose(false);
9696
} else {
97+
let header = typeof data.name !== 'undefined' ? { headers: { authorization: `Bearer ${token}` } } : {};
9798
axios
98-
.delete(deleteMapper(data))
99+
.delete(deleteMapper(data), header)
99100
.then(() => {
100101
onClose(false);
101102
getData();

src/components/shared/speedDial.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const Transition = React.forwardRef(function Transition(props, ref) {
3636
return <Grow direction="up" ref={ref} {...props} />;
3737
});
3838

39-
export default function MultifunctionButton({ pageType, setOpen, status, data, getData, env }) {
39+
export default function MultifunctionButton({ pageType, setOpen, status, data, getData, env, token }) {
4040
const theme = useTheme();
4141
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
4242

@@ -95,7 +95,14 @@ export default function MultifunctionButton({ pageType, setOpen, status, data, g
9595
<SpeedDialAction onClick={action.click} key={index} icon={action.icon} tooltipTitle={action.name} />
9696
))}
9797
</SpeedDial>
98-
<DeleteDialog open={openDeleteDialog} onClose={handleCloseDeleteDialog} getData={getData} data={data} env={env} />
98+
<DeleteDialog
99+
open={openDeleteDialog}
100+
onClose={handleCloseDeleteDialog}
101+
getData={getData}
102+
data={data}
103+
env={env}
104+
token={token}
105+
/>
99106
<DialogRounded
100107
open={status}
101108
fullWidth={true}

src/components/tenant/tenantForm.js

+83-35
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ export default function TenantForm({ title, close, action, tenant, getTenants, t
4141
reader.onerror = (error) => reject(error);
4242
});
4343
const [name, setName] = React.useState(action === 'modify' ? tenant.name : ' ');
44-
const [primaryColor, setPrimaryColor] = React.useState(action === 'modify' ? tenant.props.primaryColor : null);
45-
const [secondaryColor, setSecondaryColor] = React.useState(action === 'modify' ? tenant.props.secondaryColor : null);
44+
const [primaryColor, setPrimaryColor] = React.useState(action === 'modify' ? tenant.props.primaryColor : '#8086ba');
45+
const [secondaryColor, setSecondaryColor] = React.useState(
46+
action === 'modify' ? tenant.props.secondaryColor : '#8086ba'
47+
);
4648
const [iconName, setIconName] = React.useState(action === 'modify' ? tenant.props.icon : 'none');
4749

4850
const [openImageUpload, setOpenImageUpload] = React.useState(false);
@@ -76,47 +78,93 @@ export default function TenantForm({ title, close, action, tenant, getTenants, t
7678
});
7779

7880
React.useEffect(async () => {
79-
const result = await toBase64(customImage[0]);
80-
setBase64Image(result);
81+
if (iconName === 'custom') {
82+
const result = await toBase64(customImage[0]);
83+
setBase64Image(result);
84+
}
8185
}, [customImage]);
8286

8387
const handleSave = () => {
8488
switch (action) {
8589
case 'create':
86-
axios
87-
.post(
88-
anubisURL + 'v1/tenants',
89-
{
90-
name: name
91-
},
92-
{
93-
headers: {
94-
authorization: `Bearer ${token}`
90+
if (iconName === 'custom' && customImage.length === 0) {
91+
sendNotification({ msg: 'No image uploaded', variant: 'error' });
92+
break;
93+
} else {
94+
axios
95+
.post(
96+
anubisURL + 'v1/tenants',
97+
{
98+
name: name
99+
},
100+
{
101+
headers: {
102+
authorization: `Bearer ${token}`
103+
}
95104
}
96-
}
97-
)
98-
.then(() => {
99-
close(false);
100-
sendNotification({
101-
msg: (
102-
<Trans
103-
i18nKey="common.messages.sucessCreate"
104-
values={{
105-
data: 'Tenant'
106-
}}
107-
/>
108-
),
109-
variant: 'success'
105+
)
106+
.then(() => {
107+
client
108+
.mutate({
109+
mutation: gql`
110+
mutation getTenantConfig(
111+
$name: String!
112+
$icon: String!
113+
$primaryColor: String!
114+
$secondaryColor: String!
115+
$file: String
116+
) {
117+
getTenantConfig(
118+
name: $name
119+
icon: $icon
120+
primaryColor: $primaryColor
121+
secondaryColor: $secondaryColor
122+
file: $file
123+
) {
124+
name
125+
icon
126+
primaryColor
127+
secondaryColor
128+
}
129+
}
130+
`,
131+
variables: {
132+
name,
133+
icon: iconName,
134+
file: iconName === 'custom' && customImage.length > 0 && base64Image !== '' ? base64Image : '',
135+
primaryColor: primaryColor.toString(),
136+
secondaryColor: secondaryColor.toString()
137+
}
138+
})
139+
.then(() => {
140+
close(false);
141+
getTenants();
142+
sendNotification({
143+
msg: (
144+
<Trans
145+
i18nKey="common.messages.sucessCreate"
146+
values={{
147+
data: name
148+
}}
149+
/>
150+
),
151+
variant: 'success'
152+
});
153+
renewTokens();
154+
})
155+
.catch((e) => {
156+
sendNotification({ msg: e.message + ' the config', variant: 'error' });
157+
});
158+
})
159+
.catch((e) => {
160+
getTenants();
161+
typeof e.response.data.detail === 'string'
162+
? sendNotification({ msg: e.response.data.detail, variant: 'error' })
163+
: e.response.data.detail.map((msgObj) => sendNotification({ msg: msgObj.msg, variant: 'error' }));
110164
});
111-
renewTokens();
112-
getTenants();
113-
})
114-
.catch((e) => {
115-
getTenants();
116-
e.response.data.detail.map((thisError) => sendNotification({ msg: thisError.msg, variant: 'error' }));
117-
});
118165

119-
break;
166+
break;
167+
}
120168
case 'modify':
121169
client
122170
.mutate({

src/pages/tenantPage.js

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export default function TenantPage({
6767
<Grid item xs={12} sm={12} md={6} lg={4} xl={4}>
6868
<DashboardCard
6969
env={env}
70+
token={token}
7071
index={index}
7172
key={index}
7273
pageType={

0 commit comments

Comments
 (0)