Commit d69ae409 authored by Tifenn Guillas's avatar Tifenn Guillas

Merge branch 'develop' into 'master'

Develop

See merge request !56
parents 9c885f3e e7662337
......@@ -6,12 +6,12 @@ stages:
- deploy
variables:
VERSION: "3.3"
VERSION: "3.5"
SONARQUBE_URL: https://sonarqube.lam.fr
CONTAINER_IMAGE: portus.lam.fr/anis/anis-server
install:
image: jakzal/phpqa
image: jakzal/phpqa:php7.4
stage: install
script:
- composer install --ignore-platform-reqs
......@@ -24,7 +24,7 @@ install:
- develop
phpunit:
image: jakzal/phpqa
image: jakzal/phpqa:php7.4
stage: test
script:
- phpdbg -qrr ./vendor/bin/phpunit --bootstrap ./tests/bootstrap.php --whitelist src --coverage-clover ./coverage/clover.xml --log-junit ./coverage/junit-logfile.xml --colors=never ./tests
......
......@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.5.0]
### Added
- #7: Protected routes with SSO JWT
- #58: Add datasets privileges
## [3.4.0]
### Added
- #56: Added config attribute to Instance entity
......
FROM php:7.3-apache
FROM php:7.4-apache
# Install modules
RUN apt-get update \
......
......@@ -23,7 +23,7 @@ install:
@docker run --init -it --rm --user $(UID):$(GID) \
-e COMPOSER_CACHE_DIR=/dev/null \
-v $(CURDIR):/project \
-w /project jakzal/phpqa composer install --ignore-platform-reqs
-w /project jakzal/phpqa:php7.4 composer install --ignore-platform-reqs
rebuild:
@docker-compose up --build -d
......@@ -49,15 +49,16 @@ shell:
phpunit:
@docker run --init -it --rm --user $(UID):$(GID) \
-v $(CURDIR):/project \
-w /project jakzal/phpqa phpdbg -qrr ./vendor/bin/phpunit --bootstrap ./tests/bootstrap.php \
-w /project jakzal/phpqa:php7.4 phpdbg -qrr ./vendor/bin/phpunit --bootstrap ./tests/bootstrap.php \
--whitelist src --colors --coverage-html ./phpunit-coverage ./tests
phpcs:
@docker run --init -it --rm --user $(UID):$(GID) \
-v $(CURDIR):/project \
-w /project jakzal/phpqa phpcs --standard=PSR12 --extensions=php --colors src tests
-w /project jakzal/phpqa:php7.4 phpcs --standard=PSR12 --extensions=php --colors src tests
create-db:
@docker-compose exec php sh ./conf-dev/init-keycloak.sh
@docker-compose exec php sh ./conf-dev/create-db.sh
remove-pgdata:
......
3.4.0
\ No newline at end of file
3.5.0
\ No newline at end of file
......@@ -56,6 +56,22 @@ $container->set('App\Action\RootAction', function () {
return new App\Action\RootAction();
});
$container->set('App\Action\SelectListAction', function (ContainerInterface $c) {
return new App\Action\SelectListAction($c->get('em'));
});
$container->set('App\Action\SelectAction', function (ContainerInterface $c) {
return new App\Action\SelectAction($c->get('em'));
});
$container->set('App\Action\OptionListAction', function (ContainerInterface $c) {
return new App\Action\OptionListAction($c->get('em'));
});
$container->set('App\Action\OptionAction', function (ContainerInterface $c) {
return new App\Action\OptionAction($c->get('em'));
});
$container->set('App\Action\DatabaseListAction', function (ContainerInterface $c) {
return new App\Action\DatabaseListAction($c->get('em'));
});
......@@ -76,6 +92,14 @@ $container->set('App\Action\ProjectAction', function (ContainerInterface $c) {
return new App\Action\ProjectAction($c->get('em'));
});
$container->set('App\Action\GroupListAction', function (ContainerInterface $c) {
return new App\Action\GroupListAction($c->get('em'));
});
$container->set('App\Action\GroupAction', function (ContainerInterface $c) {
return new App\Action\GroupAction($c->get('em'));
});
$container->set('App\Action\FamilyListAction', function (ContainerInterface $c) {
return new App\Action\FamilyListAction($c->get('em'));
});
......@@ -97,7 +121,7 @@ $container->set('App\Action\DatasetFamilyListAction', function (ContainerInterfa
});
$container->set('App\Action\DatasetListByInstanceAction', function (ContainerInterface $c) {
return new App\Action\DatasetListByInstanceAction($c->get('em'));
return new App\Action\DatasetListByInstanceAction($c->get('em'), $c->get(SETTINGS)['token']);
});
$container->set('App\Action\DatasetFamilyAction', function (ContainerInterface $c) {
......@@ -156,15 +180,11 @@ $container->set('App\Action\SearchAction', function (ContainerInterface $c) {
return new App\Action\SearchAction(
$c->get('em'),
new App\Utils\DBALConnectionFactory(),
new App\Utils\Operator\OperatorFactory()
new App\Utils\Operator\OperatorFactory(),
$c->get(SETTINGS)['token']
);
});
$container->set('App\Action\DownloadFileAction', function (ContainerInterface $c) {
return new App\Action\DownloadFileAction($c->get('em'));
});
// Middlewares
$container->set('App\Middleware\AuthorizationMiddleware', function (ContainerInterface $c) {
return new App\Middleware\AuthorizationMiddleware($c->get('em'), $c->get(SETTINGS)['token_options']);
return new App\Action\DownloadFileAction($c->get('em'), $c->get(SETTINGS)['token']);
});
......@@ -14,3 +14,4 @@ $app->add(new App\Middleware\JsonBodyParserMiddleware());
$app->add(new App\Middleware\ContentTypeJsonMiddleware());
$app->add(new App\Middleware\CorsMiddleware());
$app->add(new App\Middleware\MetamodelSqlLoggerMiddleware($container->get('logger'), $container->get('em')));
$app->add(new App\Middleware\AuthorizationMiddleware($container->get(SETTINGS)['token']));
......@@ -13,27 +13,48 @@ declare(strict_types=1);
use Slim\Routing\RouteCollectorProxy;
$app->get('/', App\Action\RootAction::class);
$app->map([OPTIONS, GET, POST], '/database', App\Action\DatabaseListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/database/{id}', App\Action\DatabaseAction::class);
$app->map([OPTIONS, GET], '/database/{id}/table', App\Action\TableListAction::class);
$app->map([OPTIONS, GET, POST], '/project', App\Action\ProjectListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/project/{name}', App\Action\ProjectAction::class);
$app->map([OPTIONS, GET, POST], '/instance', App\Action\InstanceListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/instance/{name}', App\Action\InstanceAction::class);
$app->map([OPTIONS, GET, POST], '/instance/{name}/dataset-family', App\Action\DatasetFamilyListAction::class);
$app->map([OPTIONS, GET], '/instance/{name}/dataset', App\Action\DatasetListByInstanceAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/dataset-family/{id}', App\Action\DatasetFamilyAction::class);
$app->map([OPTIONS, GET, POST], '/dataset-family/{id}/dataset', App\Action\DatasetListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/dataset/{name}', App\Action\DatasetAction::class);
$app->map([OPTIONS, GET, POST], '/dataset/{name}/criteria-family', App\Action\CriteriaFamilyListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/criteria-family/{id}', App\Action\CriteriaFamilyAction::class);
$app->map([OPTIONS, GET, POST], '/dataset/{name}/output-family', App\Action\OutputFamilyListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/output-family/{id}', App\Action\OutputFamilyAction::class);
$app->map([OPTIONS, GET], '/dataset/{name}/output-category', App\Action\OutputCategoryListByDatasetAction::class);
$app->map([OPTIONS, GET, POST], '/output-family/{id}/output-category', App\Action\OutputCategoryListAction::class);
$app->map([OPTIONS, GET, PUT, DELETE], '/output-category/{id}', App\Action\OutputCategoryAction::class);
$app->map([OPTIONS, GET], '/dataset/{name}/attribute', App\Action\AttributeListAction::class);
$app->map([OPTIONS, GET, PUT], '/dataset/{name}/attribute/{id}', App\Action\AttributeAction::class);
$app->map([OPTIONS, GET, PUT], '/dataset/{name}/attribute/{id}/distinct', App\Action\AttributeDistinctAction::class);
$app->group('', function (RouteCollectorProxy $group) {
$group->map([OPTIONS, GET, POST], '/select', App\Action\SelectListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/select/{name}', App\Action\SelectAction::class);
$group->map([OPTIONS, GET, POST], '/option', App\Action\OptionListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/option/{id}', App\Action\OptionAction::class);
$group->map([OPTIONS, GET, POST], '/database', App\Action\DatabaseListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/database/{id}', App\Action\DatabaseAction::class);
$group->map([OPTIONS, GET], '/database/{id}/table', App\Action\TableListAction::class);
})->add(new App\Middleware\AdminMiddleware($container->get(SETTINGS)['token'], false));
$app->group('', function (RouteCollectorProxy $group) {
$group->map([OPTIONS, GET, POST], '/project', App\Action\ProjectListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/project/{name}', App\Action\ProjectAction::class);
$group->map([OPTIONS, GET, POST], '/instance', App\Action\InstanceListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/instance/{name}', App\Action\InstanceAction::class);
$group->map([OPTIONS, GET, POST], '/instance/{name}/group', App\Action\GroupListAction::class);
$group->map([OPTIONS, GET, POST], '/instance/{name}/dataset-family', App\Action\DatasetFamilyListAction::class);
$group->map([OPTIONS, GET], '/instance/{name}/dataset', App\Action\DatasetListByInstanceAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/group/{id}', App\Action\GroupAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/dataset-family/{id}', App\Action\DatasetFamilyAction::class);
$group->map([OPTIONS, GET, POST], '/dataset-family/{id}/dataset', App\Action\DatasetListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/dataset/{name}', App\Action\DatasetAction::class);
$group->map([OPTIONS, GET, POST], '/dataset/{name}/criteria-family', App\Action\CriteriaFamilyListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/criteria-family/{id}', App\Action\CriteriaFamilyAction::class);
$group->map([OPTIONS, GET, POST], '/dataset/{name}/output-family', App\Action\OutputFamilyListAction::class);
$group->map([OPTIONS, GET, PUT, DELETE], '/output-family/{id}', App\Action\OutputFamilyAction::class);
$group->map([OPTIONS, GET], '/dataset/{name}/output-category', App\Action\OutputCategoryListByDatasetAction::class);
$group->map(
[OPTIONS, GET, POST],
'/output-family/{id}/output-category',
App\Action\OutputCategoryListAction::class
);
$group->map([OPTIONS, GET, PUT, DELETE], '/output-category/{id}', App\Action\OutputCategoryAction::class);
$group->map([OPTIONS, GET], '/dataset/{name}/attribute', App\Action\AttributeListAction::class);
$group->map([OPTIONS, GET, PUT], '/dataset/{name}/attribute/{id}', App\Action\AttributeAction::class);
$group->map(
[OPTIONS, GET, PUT],
'/dataset/{name}/attribute/{id}/distinct',
App\Action\AttributeDistinctAction::class
);
})->add(new App\Middleware\AdminMiddleware($container->get(SETTINGS)['token'], true));
$app->get('/search/{dname}', App\Action\SearchAction::class);
$app->get('/download-file/{dname}/[{fpath:.*}]', App\Action\DownloadFileAction::class);
......@@ -29,5 +29,11 @@ return [
'name' => getenv('LOGGER_NAME'),
'path' => getenv('LOGGER_PATH'),
'level' => getenv('LOGGER_LEVEL')
],
'token' => [
//'issuer' => getenv('TOKEN_ISSUER'),
'enabled' => getenv('TOKEN_ENABLED'),
'public_key_file' => getenv('TOKEN_PUBLIC_KEY_FILE'),
'admin_role' => getenv('TOKEN_ADMIN_ROLE')
]
];
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "41b0ad136ffb7b6f8f4c93825e72e5be",
"content-hash": "9f060118c163df9ee6fc4a2bb7d5c005",
"packages": [
{
"name": "doctrine/annotations",
......@@ -900,6 +900,7 @@
"keywords": [
"reflection"
],
"abandoned": "roave/better-reflection",
"time": "2018-06-14T14:45:07+00:00"
},
{
......@@ -958,8 +959,74 @@
"serialize",
"tokenizer"
],
"abandoned": "opis/closure",
"time": "2018-03-21T22:21:57+00:00"
},
{
"name": "lcobucci/jwt",
"version": "3.3.3",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "c1123697f6a2ec29162b82f170dd4a491f524773"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/c1123697f6a2ec29162b82f170dd4a491f524773",
"reference": "c1123697f6a2ec29162b82f170dd4a491f524773",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
],
"funding": [
{
"url": "https://github.com/lcobucci",
"type": "github"
},
{
"url": "https://www.patreon.com/lcobucci",
"type": "patreon"
}
],
"time": "2020-08-20T13:22:28+00:00"
},
{
"name": "monolog/monolog",
"version": "2.0.1",
......@@ -3620,5 +3687,6 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
"platform-dev": [],
"plugin-api-version": "1.1.0"
}
FROM php:7.3-apache
FROM php:7.4-apache
# Install modules
RUN apt-get update \
&& apt-get install -y zlib1g zlib1g-dev libpq-dev libpq5 libzip-dev zip unzip \
&& apt-get install -y zlib1g zlib1g-dev libpq-dev libpq5 libzip-dev zip unzip jq \
&& docker-php-ext-install pgsql pdo_pgsql zip bcmath
# Install pecl modules
......
This diff is collapsed.
#!/bin/sh
set -e
# Get Keycloak Admin token
admin_token=$(curl --location --request POST 'http://keycloak:8180/auth/realms/master/protocol/openid-connect/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'username=admin' --data-urlencode 'password=admin' --data-urlencode 'grant_type=password' --data-urlencode 'client_id=admin-cli' | jq -r '.access_token')
# Create cesamsi user
curl --location --request POST 'http://keycloak:8180/auth/admin/realms/anis/users' --header 'Content-Type: application/json' --header "Authorization: Bearer $admin_token" --data-raw '{"firstName":"cesam-si","lastName":"cesam-si", "email":"cesamsi@lam.fr", "enabled":"true", "emailVerified":"true", "credentials":[{"type":"password","value":"admin","temporary":false}]}'
# Get anis_admin role and id_user
anis_admin_role=$(curl --location --request GET 'http://keycloak:8180/auth/admin/realms/anis/roles/anis_admin' --header 'Content-Type: application/json' --header "Authorization: Bearer $admin_token")
id_user=$(curl --location --request GET 'http://keycloak:8180/auth/admin/realms/anis/users' --header 'Content-Type: application/json' --header "Authorization: Bearer $admin_token" | jq -r '.[0]' | jq -r '.id')
# Add anis_admin role to cesamsi user
curl --location --request POST "http://keycloak:8180/auth/admin/realms/anis/users/${id_user}/role-mappings/realm" --header 'Content-Type: application/json' --header "Authorization: Bearer $admin_token" --data-raw "[${anis_admin_role}]"
......@@ -3,8 +3,10 @@ set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER anis LOGIN PASSWORD 'anis';
CREATE USER keycloak LOGIN PASSWORD 'keycloak';
CREATE DATABASE anis_metamodel;
CREATE DATABASE anis_test;
CREATE DATABASE keycloakdb;
GRANT ALL PRIVILEGES ON DATABASE anis_metamodel TO anis;
GRANT ALL PRIVILEGES ON DATABASE anis_test TO anis;
EOSQL
......
This diff is collapsed.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1PHpi8f0iWxr1M9lwlL9tWwfZCIfO/oUFvtAPz94wOJCnISVe1AZDvHba2+Zn6fGQ9iXBkxjjz0Qn/p4YiV1zM/TaPme/LFrefTyrI8fhIQmucMSGWm37DgWPJrb5aZDJIdt7GKoEpAAMFFhh0qAH1BZ9s9vVNBCTSyhpsela9+XLTwIDGU0pAyEBNyc8/AOLiNv9LgPJoe/GHixJKcGkoyEacKJfhfzM36EpZedHBMvIv/ENUanMcD4aHhSIm44i6uEcZvFnQUtYCj9MluyJhfCw+arDja8bghB/6Wwzg7hq3H1oLfOJotpPculNaRA2ppTD/qIkdyiBmLw/puSEQIDAQAB
-----END PUBLIC KEY-----
......@@ -17,6 +17,9 @@ services:
LOGGER_NAME: "anis-metamodel"
LOGGER_PATH: "php://stderr"
LOGGER_LEVEL: "debug"
TOKEN_ENABLED: 1
TOKEN_PUBLIC_KEY_FILE: /data/public_key
TOKEN_ADMIN_ROLE: anis_admin
ports:
- 8080:80
volumes:
......@@ -24,6 +27,25 @@ services:
- ./conf-dev/dev-php.ini:/usr/local/etc/php/conf.d/dev-php.ini
- ./conf-dev/vhost.conf:/etc/apache2/sites-available/000-default.conf
- ./conf-dev/data-dev:/data/ASPIC
- ./conf-dev/public_key:/data/public_key
keycloak:
image: jboss/keycloak
environment:
DB_VENDOR: POSTGRES
DB_ADDR: db
DB_DATABASE: keycloakdb
DB_USER: keycloak
DB_PASSWORD: keycloak
DB_SCHEMA: public
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
KEYCLOAK_IMPORT: /tmp/keycloak-anis-realm.json
ports:
- 8180:8180
volumes:
- ./conf-dev/keycloak-anis-realm.json:/tmp/keycloak-anis-realm.json
command: -b 0.0.0.0 -Djboss.http.port=8180
db:
image: postgres
......@@ -44,5 +66,10 @@ services:
ports:
- 8083:8080
mailer:
image: djfarrelly/maildev
ports:
- 1080:80
volumes:
pgdata:
\ No newline at end of file
......@@ -64,10 +64,10 @@ class Dataset extends \App\Entity\Dataset implements \Doctrine\ORM\Proxy\Proxy
public function __sleep()
{
if ($this->__isInitialized__) {
return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'selectableRow', 'project', 'datasetFamily', 'attributes'];
return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'config', 'public', 'project', 'datasetFamily', 'attributes'];
}
return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'selectableRow', 'project', 'datasetFamily', 'attributes'];
return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'config', 'public', 'project', 'datasetFamily', 'attributes'];
}
/**
......@@ -345,23 +345,45 @@ class Dataset extends \App\Entity\Dataset implements \Doctrine\ORM\Proxy\Proxy
/**
* {@inheritDoc}
*/
public function getSelectableRow()
public function getConfig()
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getSelectableRow', []);
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getConfig', []);
return parent::getSelectableRow();
return parent::getConfig();
}
/**
* {@inheritDoc}
*/
public function setSelectableRow($selectableRow)
public function setConfig($config)
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setSelectableRow', [$selectableRow]);
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setConfig', [$config]);
return parent::setSelectableRow($selectableRow);
return parent::setConfig($config);
}
/**
* {@inheritDoc}
*/
public function getPublic()
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getPublic', []);
return parent::getPublic();
}
/**
* {@inheritDoc}
*/
public function setPublic($public)
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setPublic', [$public]);
return parent::setPublic($public);
}
/**
......
......@@ -232,6 +232,17 @@ class DatasetFamily extends \App\Entity\DatasetFamily implements \Doctrine\ORM\P
return parent::setDisplay($display);
}
/**
* {@inheritDoc}
*/
public function getInstance()
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getInstance', []);
return parent::getInstance();
}
/**
* {@inheritDoc}
*/
......
......@@ -64,10 +64,10 @@ class Group extends \App\Entity\Group implements \Doctrine\ORM\Proxy\Proxy
public function __sleep()
{
if ($this->__isInitialized__) {
return ['__isInitialized__', 'id', 'label', 'datasetPrivileges'];
return ['__isInitialized__', 'id', 'role', 'instance', 'datasets'];
}
return ['__isInitialized__', 'id', 'label', 'datasetPrivileges'];
return ['__isInitialized__', 'id', 'role', 'instance', 'datasets'];
}
/**
......@@ -191,34 +191,56 @@ class Group extends \App\Entity\Group implements \Doctrine\ORM\Proxy\Proxy
/**
* {@inheritDoc}
*/
public function getLabel()
public function getRole()
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getLabel', []);
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getRole', []);
return parent::getLabel();
return parent::getRole();
}
/**
* {@inheritDoc}
*/
public function setLabel($label)
public function setRole($role)
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setLabel', [$label]);
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setRole', [$role]);
return parent::setLabel($label);
return parent::setRole($role);
}
/**
* {@inheritDoc}
*/
public function getDatasetPrivileges()
public function getInstance()
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasetPrivileges', []);
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getInstance', []);
return parent::getDatasetPrivileges();
return parent::getInstance();
}
/**
* {@inheritDoc}
*/
public function getDatasets()
{
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasets', []);
return parent::getDatasets();
}