Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
anis
anis-next
Commits
dcf243b6
Commit
dcf243b6
authored
Apr 20, 2022
by
François Agneray
Browse files
Instance public private => WIP
parent
7e963a3e
Changes
15
Hide whitespace changes
Inline
Side-by-side
client/src/app/admin/admin.component.ts
View file @
dcf243b6
...
...
@@ -19,7 +19,6 @@ import * as authSelector from 'src/app/auth/auth.selector';
import
*
as
databaseActions
from
'
src/app/metamodel/actions/database.actions
'
;
import
*
as
selectActions
from
'
src/app/metamodel/actions/select.actions
'
;
import
*
as
optionActions
from
'
src/app/metamodel/actions/select-option.actions
'
;
import
*
as
instanceGroupActions
from
'
src/app/metamodel/actions/instance-group.actions
'
;
import
{
AppConfigService
}
from
'
src/app/app-config.service
'
;
@
Component
({
...
...
@@ -60,7 +59,6 @@ export class AdminComponent implements OnInit {
Promise
.
resolve
(
null
).
then
(()
=>
this
.
store
.
dispatch
(
databaseActions
.
loadDatabaseList
()));
Promise
.
resolve
(
null
).
then
(()
=>
this
.
store
.
dispatch
(
selectActions
.
loadSelectList
()));
Promise
.
resolve
(
null
).
then
(()
=>
this
.
store
.
dispatch
(
optionActions
.
loadSelectOptionList
()));
Promise
.
resolve
(
null
).
then
(()
=>
this
.
store
.
dispatch
(
instanceGroupActions
.
loadInstanceGroupList
()));
}
getBaseHref
()
{
...
...
client/src/app/admin/instance/containers/edit-instance-group.component.html
View file @
dcf243b6
...
...
@@ -11,15 +11,15 @@
Instance groups
</a>
</li>
<li
*ngIf=
"instanceGroupListIsLoaded | async"
class=
"breadcrumb-item active"
aria-current=
"page"
>
Edit instance group {{ (instanceGroup | async).role }}
</li>
<li
class=
"breadcrumb-item active"
aria-current=
"page"
>
Edit instance group {{ (instanceGroup | async).role }}
</li>
</ol>
</nav>
</div>
<div
class=
"container"
>
<app-spinner
*ngIf=
"
(instanceGroupListIsLoading | async) ||
(instanceListIsLoading | async)"
></app-spinner>
<app-spinner
*ngIf=
"(instanceListIsLoading | async)"
></app-spinner>
<div
*ngIf=
"
(instanceGroupListIsLoaded | async) &&
(instanceListIsLoaded | async)"
class=
"row"
>
<div
*ngIf=
"(instanceListIsLoaded | async)"
class=
"row"
>
<div
class=
"col-12"
>
<app-instance-group-form
[instanceGroup]=
"instanceGroup | async"
[instanceList]=
"instanceList | async"
(onSubmit)=
"editInstanceGroup($event)"
#formGroup
>
<button
[disabled]=
"!formGroup.form.valid || formGroup.form.pristine"
type=
"submit"
class=
"btn btn-primary"
>
...
...
client/src/app/admin/instance/containers/edit-instance-group.component.ts
View file @
dcf243b6
...
...
@@ -21,16 +21,12 @@ import * as instanceGroupSelector from 'src/app/metamodel/selectors/instance-gro
templateUrl
:
'
edit-instance-group.component.html
'
})
export
class
EditInstanceGroupComponent
{
public
instanceGroupListIsLoading
:
Observable
<
boolean
>
;
public
instanceGroupListIsLoaded
:
Observable
<
boolean
>
;
public
instanceGroup
:
Observable
<
InstanceGroup
>
;
public
instanceListIsLoading
:
Observable
<
boolean
>
;
public
instanceListIsLoaded
:
Observable
<
boolean
>
;
public
instanceList
:
Observable
<
Instance
[]
>
;
constructor
(
private
store
:
Store
<
{
}
>
)
{
this
.
instanceGroupListIsLoading
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupListIsLoading
);
this
.
instanceGroupListIsLoaded
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupListIsLoaded
);
this
.
instanceGroup
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupByRouteId
);
this
.
instanceListIsLoading
=
store
.
select
(
instanceSelector
.
selectInstanceListIsLoading
);
this
.
instanceListIsLoaded
=
store
.
select
(
instanceSelector
.
selectInstanceListIsLoaded
);
...
...
client/src/app/admin/instance/containers/instance-group-list.component.html
View file @
dcf243b6
...
...
@@ -10,28 +10,24 @@
</ol>
</nav>
<app-spinner
*ngIf=
"instanceGroupListIsLoading | async"
></app-spinner>
<ng-container
*ngIf=
"instanceGroupListIsLoaded | async"
>
<div
class=
"row"
>
<div
class=
"col-12"
>
<button
title=
"Add a new instance group"
class=
"btn btn-outline-success float-right"
routerLink=
"new-group"
>
<span
class=
"fas fa-plus"
></span>
New instance group
</button>
</div>
<div
class=
"row"
>
<div
class=
"col-12"
>
<button
title=
"Add a new instance group"
class=
"btn btn-outline-success float-right"
routerLink=
"new-group"
>
<span
class=
"fas fa-plus"
></span>
New instance group
</button>
</div>
</div>
<div
class=
"row mt-1"
>
<div
class=
"col-12 lead text-center font-weight-bold"
*ngIf=
"(instanceGroupList | async).length < 1"
>
Oops! No instance groups available...
</div>
<div
class=
"row mt-1"
>
<div
class=
"col-12 lead text-center font-weight-bold"
*ngIf=
"(instanceGroupList | async).length < 1"
>
Oops! No instance groups available...
</div>
<div
class=
"col-12"
*ngIf=
"(instanceGroupList | async).length > 0"
>
<app-instance-group-table
[instanceGroupList]=
"instanceGroupList | async"
(deleteInstanceGroup)=
"deleteInstanceGroup($event)"
>
</app-instance-group-table>
</div>
<div
class=
"col-12"
*ngIf=
"(instanceGroupList | async).length > 0"
>
<app-instance-group-table
[instanceGroupList]=
"instanceGroupList | async"
(deleteInstanceGroup)=
"deleteInstanceGroup($event)"
>
</app-instance-group-table>
</div>
</
ng-container
>
</
div
>
</div>
client/src/app/admin/instance/containers/instance-group-list.component.ts
View file @
dcf243b6
...
...
@@ -20,13 +20,9 @@ import * as instanceGroupSelector from 'src/app/metamodel/selectors/instance-gro
templateUrl
:
'
instance-group-list.component.html
'
})
export
class
InstanceGroupListComponent
{
public
instanceGroupListIsLoading
:
Observable
<
boolean
>
;
public
instanceGroupListIsLoaded
:
Observable
<
boolean
>
;
public
instanceGroupList
:
Observable
<
InstanceGroup
[]
>
;
constructor
(
private
store
:
Store
<
{
}
>
)
{
this
.
instanceGroupListIsLoading
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupListIsLoading
);
this
.
instanceGroupListIsLoaded
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupListIsLoaded
);
this
.
instanceGroupList
=
store
.
select
(
instanceGroupSelector
.
selectAllInstanceGroups
);
}
...
...
client/src/app/core/containers/app.component.html
View file @
dcf243b6
<div
*ngIf=
"(instanceListIsLoading | async)"
class=
"row justify-content-center mt-5"
>
<div
*ngIf=
"(instanceListIsLoading |
async) || (instanceGroupListIsLoading |
async)"
class=
"row justify-content-center mt-5"
>
<span
class=
"fas fa-circle-notch fa-spin fa-3x"
></span>
<span
class=
"sr-only"
>
Loading...
</span>
</div>
<router-outlet
*ngIf=
"(instanceListIsLoaded | async)"
></router-outlet>
<router-outlet
*ngIf=
"(instanceListIsLoaded |
async) && (instanceGroupListIsLoaded |
async)"
></router-outlet>
<footer
class=
"footer mt-auto bg-light"
>
<div
class=
"container my-3"
>
<div
class=
"row justify-content-center font-weight-bold mb-1"
>
...
...
client/src/app/core/containers/app.component.ts
View file @
dcf243b6
...
...
@@ -18,6 +18,8 @@ import * as authActions from 'src/app/auth/auth.actions';
import
*
as
authSelector
from
'
src/app/auth/auth.selector
'
;
import
*
as
instanceActions
from
'
src/app/metamodel/actions/instance.actions
'
;
import
*
as
instanceSelector
from
'
src/app/metamodel/selectors/instance.selector
'
;
import
*
as
instanceGroupActions
from
'
src/app/metamodel/actions/instance-group.actions
'
;
import
*
as
instanceGroupSelector
from
'
src/app/metamodel/selectors/instance-group.selector
'
;
import
{
UserProfile
}
from
'
src/app/auth/user-profile.model
'
;
import
{
AppConfigService
}
from
'
src/app/app-config.service
'
;
...
...
@@ -34,6 +36,8 @@ export class AppComponent implements OnInit {
public
year
:
number
=
(
new
Date
()).
getFullYear
();
public
instanceListIsLoading
:
Observable
<
boolean
>
;
public
instanceListIsLoaded
:
Observable
<
boolean
>
;
public
instanceGroupListIsLoading
:
Observable
<
boolean
>
;
public
instanceGroupListIsLoaded
:
Observable
<
boolean
>
;
public
isAuthenticated
:
Observable
<
boolean
>
;
public
userProfile
:
Observable
<
UserProfile
>
;
public
userRoles
:
Observable
<
string
[]
>
;
...
...
@@ -41,6 +45,8 @@ export class AppComponent implements OnInit {
constructor
(
private
store
:
Store
<
{
auth
:
fromAuth
.
State
}
>
,
private
config
:
AppConfigService
)
{
this
.
instanceListIsLoading
=
store
.
select
(
instanceSelector
.
selectInstanceListIsLoading
);
this
.
instanceListIsLoaded
=
store
.
select
(
instanceSelector
.
selectInstanceListIsLoaded
);
this
.
instanceGroupListIsLoading
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupListIsLoading
);
this
.
instanceGroupListIsLoaded
=
store
.
select
(
instanceGroupSelector
.
selectInstanceGroupListIsLoaded
);
this
.
isAuthenticated
=
store
.
select
(
authSelector
.
selectIsAuthenticated
);
this
.
userProfile
=
store
.
select
(
authSelector
.
selectUserProfile
);
this
.
userRoles
=
store
.
select
(
authSelector
.
selectUserRoles
);
...
...
@@ -50,6 +56,7 @@ export class AppComponent implements OnInit {
// Create a micro task that is processed after the current synchronous code
// This micro task prevent the expression has changed after view init error
Promise
.
resolve
(
null
).
then
(()
=>
this
.
store
.
dispatch
(
instanceActions
.
loadInstanceList
()));
Promise
.
resolve
(
null
).
then
(()
=>
this
.
store
.
dispatch
(
instanceGroupActions
.
loadInstanceGroupList
()));
}
/**
...
...
client/src/app/metamodel/models/instance.model.ts
View file @
dcf243b6
...
...
@@ -21,6 +21,8 @@ export interface Instance {
wavelength_domain
:
string
;
display
:
number
;
data_path
:
string
;
files_path
:
string
;
public
:
boolean
;
portal_logo
:
string
;
design_color
:
string
;
design_background_color
:
string
;
...
...
client/src/app/metamodel/selectors/instance.selector.ts
View file @
dcf243b6
...
...
@@ -56,4 +56,4 @@ export const selectInstanceByRouteName = createSelector(
export
const
selectInstanceNameByRoute
=
createSelector
(
reducer
.
selectRouterState
,
router
=>
router
.
state
.
params
.
iname
as
string
);
\ No newline at end of file
);
client/src/app/portal/components/instance-card.component.html
View file @
dcf243b6
...
...
@@ -22,8 +22,8 @@
</p>
</div>
<div
class=
"card-footer bg-transparent text-right"
>
<
a
routerLink=
"/instance/{{ instance.name }}"
class=
"btn btn-outline-primary"
title=
"Go to instance"
>
<
button
[disabled]=
"!isInstanceAccessible()"
routerLink=
"/instance/{{ instance.name }}"
class=
"btn btn-outline-primary"
title=
"Go to instance"
>
Go to instance
</
a
>
</
button
>
</div>
</div>
client/src/app/portal/components/instance-card.component.ts
View file @
dcf243b6
...
...
@@ -9,8 +9,7 @@
import
{
Component
,
Input
,
ChangeDetectionStrategy
}
from
'
@angular/core
'
;
import
{
AppConfigService
}
from
'
src/app/app-config.service
'
;
import
{
Instance
}
from
'
src/app/metamodel/models
'
;
import
{
Instance
,
InstanceGroup
}
from
'
src/app/metamodel/models
'
;
/**
* @class
...
...
@@ -24,6 +23,11 @@ import { Instance } from 'src/app/metamodel/models';
})
export
class
InstanceCardComponent
{
@
Input
()
instance
:
Instance
;
@
Input
()
authenticationEnabled
:
boolean
;
@
Input
()
isAuthenticated
:
boolean
;
@
Input
()
userRoles
:
string
[];
@
Input
()
adminRoles
:
string
[];
@
Input
()
instanceGroupList
:
InstanceGroup
[];
@
Input
()
apiUrl
:
string
;
/**
...
...
@@ -34,4 +38,35 @@ export class InstanceCardComponent {
getLogoSrc
():
string
{
return
`
${
this
.
apiUrl
}
/instance/
${
this
.
instance
.
name
}
/file-explorer
${
this
.
instance
.
portal_logo
}
`
;
}
isInstanceAccessible
()
{
let
accessible
=
true
;
if
(
this
.
authenticationEnabled
&&
!
this
.
instance
.
public
&&
!
this
.
isAdmin
())
{
accessible
=
false
;
if
(
this
.
isAuthenticated
)
{
accessible
=
this
.
instanceGroupList
.
filter
(
instanceGroup
=>
instanceGroup
.
instances
.
includes
(
this
.
instance
.
name
))
.
filter
(
instanceGroup
=>
this
.
userRoles
.
includes
(
instanceGroup
.
role
))
.
length
>
0
;
}
}
return
accessible
;
}
/**
* Returns true if user is admin
*
* @returns boolean
*/
isAdmin
()
{
let
admin
=
false
;
for
(
let
i
=
0
;
i
<
this
.
adminRoles
.
length
;
i
++
)
{
admin
=
this
.
userRoles
.
includes
(
this
.
adminRoles
[
i
]);
if
(
admin
)
break
;
}
return
admin
;
}
}
client/src/app/portal/containers/portal-home.component.html
View file @
dcf243b6
...
...
@@ -28,6 +28,11 @@
<div
class=
"col-auto mb-3"
*ngFor=
"let instance of (instanceList | async)"
>
<app-instance-card
[instance]=
"instance"
[authenticationEnabled]=
"getAuthenticationEnabled()"
[isAuthenticated]=
"isAuthenticated | async"
[userRoles]=
"userRoles | async"
[adminRoles]=
"getAdminRoles()"
[instanceGroupList]=
"instanceGroupList | async"
[apiUrl]=
"getApiUrl()"
>
</app-instance-card>
</div>
...
...
client/src/app/portal/containers/portal-home.component.ts
View file @
dcf243b6
...
...
@@ -14,10 +14,11 @@ import { Store } from '@ngrx/store';
import
*
as
fromRouter
from
'
@ngrx/router-store
'
;
import
{
UserProfile
}
from
'
src/app/auth/user-profile.model
'
;
import
{
Instance
}
from
'
src/app/metamodel/models
'
;
import
{
Instance
,
InstanceGroup
}
from
'
src/app/metamodel/models
'
;
import
*
as
authActions
from
'
src/app/auth/auth.actions
'
;
import
*
as
authSelector
from
'
src/app/auth/auth.selector
'
;
import
*
as
instanceSelector
from
'
src/app/metamodel/selectors/instance.selector
'
;
import
*
as
instanceGroupSelector
from
'
src/app/metamodel/selectors/instance-group.selector
'
;
import
{
AppConfigService
}
from
'
src/app/app-config.service
'
;
/**
...
...
@@ -40,6 +41,7 @@ export class PortalHomeComponent implements OnInit {
public
userProfile
:
Observable
<
UserProfile
>
;
public
userRoles
:
Observable
<
string
[]
>
;
public
instanceList
:
Observable
<
Instance
[]
>
;
public
instanceGroupList
:
Observable
<
InstanceGroup
[]
>
;
public
url
:
Observable
<
string
>
;
public
userRolesSubscription
:
Subscription
;
...
...
@@ -48,6 +50,7 @@ export class PortalHomeComponent implements OnInit {
this
.
userProfile
=
store
.
select
(
authSelector
.
selectUserProfile
);
this
.
userRoles
=
store
.
select
(
authSelector
.
selectUserRoles
);
this
.
instanceList
=
store
.
select
(
instanceSelector
.
selectAllInstances
);
this
.
instanceGroupList
=
store
.
select
(
instanceGroupSelector
.
selectAllInstanceGroups
);
this
.
url
=
store
.
select
(
fromRouter
.
getSelectors
().
selectUrl
);
}
...
...
docker-compose.yml
View file @
dcf243b6
...
...
@@ -35,7 +35,7 @@ services:
SSO_AUTH_URL
:
"
http://localhost:8180/auth"
SSO_REALM
:
"
anis"
SSO_CLIENT_ID
:
"
anis-client"
TOKEN_ENABLED
:
0
TOKEN_ENABLED
:
1
TOKEN_JWKS_URL
:
"
http://keycloak:8180/auth/realms/anis/protocol/openid-connect/certs"
TOKEN_ADMIN_ROLES
:
anis_admin,superuser
RMQ_HOST
:
rmq
...
...
server/src/Action/InstanceListAction.php
View file @
dcf243b6
...
...
@@ -63,8 +63,8 @@ final class InstanceListAction extends AbstractAction
}
if
(
$request
->
getMethod
()
===
GET
)
{
//
$instances = $this->em->getRepository('App\Entity\Instance')->findAll();
$instances
=
$this
->
getInstanceList
(
$request
->
getAttribute
(
'token'
));
$instances
=
$this
->
em
->
getRepository
(
'App\Entity\Instance'
)
->
findAll
();
//
$instances = $this->getInstanceList($request->getAttribute('token'));
$payload
=
json_encode
(
$instances
);
}
...
...
@@ -90,34 +90,34 @@ final class InstanceListAction extends AbstractAction
return
$response
;
}
private
function
getInstanceList
(
$token
)
{
$qb
=
$this
->
em
->
createQueryBuilder
();
$qb
->
select
(
'i'
)
->
from
(
'App\Entity\Instance'
,
'i'
);
if
(
boolval
(
$this
->
settings
[
'enabled'
]))
{
if
(
!
$token
)
{
// If user is not connected return public instances
$qb
->
andWhere
(
$qb
->
expr
()
->
eq
(
'i.public'
,
'true'
));
}
else
{
$adminRoles
=
explode
(
','
,
$this
->
settings
[
'admin_roles'
]);
$roles
=
$token
->
realm_access
->
roles
;
if
(
!
$this
->
isAdmin
(
$adminRoles
,
$roles
))
{
// If user is not an admin return public datasets
// And returns datasets from user's groups
$qb
->
andWhere
(
$qb
->
expr
()
->
eq
(
'i.public'
,
'true'
));
$qb2
=
$this
->
em
->
createQueryBuilder
();
$qb2
->
select
(
'i2.name'
)
->
from
(
'App\Entity\InstanceGroup'
,
'ig'
)
->
join
(
'ig.instances'
,
'i2'
)
->
where
(
$qb2
->
expr
()
->
in
(
'ig.role'
,
$roles
));
$qb
->
orWhere
(
$qb
->
expr
()
->
in
(
'i.name'
,
$qb2
->
getDQL
()));
}
}
}
return
$qb
->
getQuery
()
->
getResult
();
}
//
private function getInstanceList($token)
//
{
//
$qb = $this->em->createQueryBuilder();
//
$qb->select('i')->from('App\Entity\Instance', 'i');
//
if (boolval($this->settings['enabled'])) {
//
if (!$token) {
//
// If user is not connected return public instances
//
$qb->andWhere($qb->expr()->eq('i.public', 'true'));
//
} else {
//
$adminRoles = explode(',', $this->settings['admin_roles']);
//
$roles = $token->realm_access->roles;
//
if (!$this->isAdmin($adminRoles, $roles)) {
//
// If user is not an admin return public datasets
//
// And returns datasets from user's groups
//
$qb->andWhere($qb->expr()->eq('i.public', 'true'));
//
$qb2 = $this->em->createQueryBuilder();
//
$qb2->select('i2.name')
//
->from('App\Entity\InstanceGroup', 'ig')
//
->join('ig.instances', 'i2')
//
->where($qb2->expr()->in('ig.role', $roles));
//
$qb->orWhere($qb->expr()->in('i.name', $qb2->getDQL()));
//
}
//
}
//
}
//
return $qb->getQuery()->getResult();
//
}
/**
* Add a new instance into the metamodel
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment