Skip to content

Commit

Permalink
adds privacy plugin (#2484)
Browse files Browse the repository at this point in the history
* commit du soir bonsoir

* PrivacyBundle

* corrections suite review PR

* Update bundles.ini-dist
  • Loading branch information
Noelle-M authored May 17, 2023
1 parent 5cf9906 commit 87535da
Show file tree
Hide file tree
Showing 21 changed files with 359 additions and 0 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
},
"autoload": {
"psr-4": {
"Claroline\\PrivacyBundle\\": "src/main/privacy",
"Claroline\\AgendaBundle\\": "src/plugin/agenda",
"Claroline\\AnalyticsBundle\\": "src/plugin/analytics",
"Claroline\\AnnouncementBundle\\": "src/plugin/announcement",
Expand Down
1 change: 1 addition & 0 deletions src/main/installation/Resources/config/bundles.ini-dist
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ Claroline\CursusBundle\ClarolineCursusBundle = true
Claroline\BigBlueButtonBundle\ClarolineBigBlueButtonBundle = false
Claroline\PeerTubeBundle\ClarolinePeerTubeBundle = false
Claroline\LogBundle\ClarolineLogBundle=true
Claroline\PrivacyBundle\ClarolinePrivacyBundle=true
9 changes: 9 additions & 0 deletions src/main/privacy/ClarolinePrivacyBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Claroline\PrivacyBundle;

use Claroline\KernelBundle\Bundle\DistributionPluginBundle;

class ClarolinePrivacyBundle extends DistributionPluginBundle
{
}
56 changes: 56 additions & 0 deletions src/main/privacy/Controller/PrivacyController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Claroline\PrivacyBundle\Controller;

use Claroline\AppBundle\API\Utils\ArrayUtils;
use Claroline\AppBundle\Controller\AbstractSecurityController;
use Claroline\AppBundle\Controller\RequestDecoderTrait;
use Claroline\CoreBundle\API\Serializer\ParametersSerializer;
use Claroline\CoreBundle\Library\Configuration\PlatformConfigurationHandler;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

class PrivacyController extends AbstractSecurityController
{
use RequestDecoderTrait;

private AuthorizationCheckerInterface $authorization;

private PlatformConfigurationHandler $config;

private ParametersSerializer $serializer;

public function __construct(
AuthorizationCheckerInterface $authorization,
PlatformConfigurationHandler $ch,
ParametersSerializer $serializer
) {
$this->authorization = $authorization;
$this->config = $ch;
$this->serializer = $serializer;
}

/**
* @Route("/privacy", name="apiv2_privacy_update", methods={"PUT"})
*/
public function updateAction(Request $request): JsonResponse
{
$this->canOpenAdminTool('privacy');

$parametersData = $this->decodeRequest($request);

ArrayUtils::remove($parametersData, 'lockedParameters');

$locked = $this->config->getParameter('lockedParameters') ?? [];
foreach ($locked as $lockedParam) {
ArrayUtils::remove($parametersData, $lockedParam);
}

$parameters = $this->serializer->deserialize($parametersData);
$this->config->setParameters($parameters);

return new JsonResponse($parameters);
}
}
33 changes: 33 additions & 0 deletions src/main/privacy/DependencyInjection/ClarolinePrivacyExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/*
* This file is part of the Claroline Connect package.
*
* (c) Claroline Consortium <consortium@claroline.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Claroline\PrivacyBundle\DependencyInjection;

use Exception;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class ClarolinePrivacyExtension extends Extension
{
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function load(array $configs, ContainerBuilder $container)
{
$locator = new FileLocator(__DIR__.'/../Resources/config');
$loader = new YamlFileLoader($container, $locator);
$loader->load('services.yml');
}
}
4 changes: 4 additions & 0 deletions src/main/privacy/Resources/config/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
plugin:
admin_tools:
- name: privacy
class: shield
6 changes: 6 additions & 0 deletions src/main/privacy/Resources/config/routing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
claro_privacy:
resource: "@ClarolinePrivacyBundle/Controller/"
prefix: apiv2
type: api
options:
expose: true
4 changes: 4 additions & 0 deletions src/main/privacy/Resources/config/services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
imports:
- { resource: services/controller.yml }
- { resource: services/subscriber.yml }
- { resource: services/serializer.yml }
8 changes: 8 additions & 0 deletions src/main/privacy/Resources/config/services/controller.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
Claroline\PrivacyBundle\Controller\PrivacyController:
parent: Claroline\AppBundle\Controller\AbstractSecurityController
public: true
arguments:
- '@security.authorization_checker'
- '@Claroline\CoreBundle\Library\Configuration\PlatformConfigurationHandler'
- '@Claroline\CoreBundle\API\Serializer\ParametersSerializer'
5 changes: 5 additions & 0 deletions src/main/privacy/Resources/config/services/serializer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
_defaults:
autowire: false
autoconfigure: false
public: true
5 changes: 5 additions & 0 deletions src/main/privacy/Resources/config/services/subscriber.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
Claroline\PrivacyBundle\Subscriber\Administration\PrivacySubscriber:
tags: [ kernel.event_subscriber ]
arguments:
- '@Claroline\CoreBundle\API\Serializer\ParametersSerializer'
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React from 'react'
import {PropTypes as T} from 'prop-types'

import {LINK_BUTTON} from '#/main/app/buttons'
import {FormData} from '#/main/app/content/form/containers/data'
import {ToolPage} from '#/main/core/tool/containers/page'
import {selectors} from '#/main/privacy/administration/privacy/store'
import get from 'lodash/get'

import {trans} from '#/main/app/intl/translation'

const PrivacyTool = (props) =>
<ToolPage>
<FormData
level={2}
name={selectors.FORM_NAME}
target={['apiv2_privacy_update']}
buttons={true}
cancel={{
type: LINK_BUTTON,
target: props.path,
exact: true
}}
locked={props.lockedParameters}
sections={[
{
title: trans('general'),
primary: true,
fields: [
{
name: 'privacy.countryStorage',
label: trans('Pays de stockage des données'),
type: 'country'
}
]
}, {
icon: 'fa fa-fw fa-user-shield',
title: trans('dpo'),
fields: [
{
name: 'privacy.dpo.name',
label: trans('name'),
type: 'string'
}, {
name: 'privacy.dpo.email',
label: trans('email'),
type: 'email'
}, {
name: 'privacy.dpo.phone',
label: trans('phone'),
type: 'string'
}, {
name: 'privacy.dpo.address',
label: trans('address'),
type: 'address'
}
]
}, {
icon: 'fa fa-fw fa-copyright',
title: trans('terms_of_service'),
fields: [
{
name: 'tos.enabled',
type: 'boolean',
label: trans('terms_of_service_activation_message'),
help: trans('terms_of_service_activation_help'),
linked: [
{
name: 'tos.text',
type: 'translated',
label: trans('terms_of_service'),
required: true,
displayed: get(props.parameters, 'tos.enabled')
}
]
}
]
}
]}
/>
</ToolPage>

PrivacyTool.propTypes = {
path: T.string.isRequired,
lockedParameters: T.arrayOf(T.string),
parameters: T.shape({
tos: T.shape({
enabled: T.bool
})
})
}

export {
PrivacyTool
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {connect} from 'react-redux'

import {selectors} from '#/main/privacy/administration/privacy/store/selectors'
import {selectors as toolSelectors} from '#/main/core/tool/store'

import {PrivacyTool as PrivacyToolComponent} from '#/main/privacy/administration/privacy/components/tool'

const PrivacyTool = connect(
(state) => ({
path: toolSelectors.path(state),
lockedParameters: selectors.lockedParameters(state),
parameters: selectors.parameters(state)
})
)(PrivacyToolComponent)

export {
PrivacyTool
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {PrivacyTool} from '#/main/privacy/administration/privacy/components/tool'

import {reducer} from '#/main/privacy/administration/privacy/store/reducer'

export default {
component: PrivacyTool,
store: reducer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {reducer} from '#/main/privacy/administration/privacy/store/reducer'
import {selectors} from '#/main/privacy/administration/privacy/store/selectors'

export {reducer, selectors}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {makeFormReducer} from '#/main/app/content/form/store/reducer'
import {makeInstanceAction} from '#/main/app/store/actions'
import {makeReducer, combineReducers} from '#/main/app/store/reducer'

import {TOOL_LOAD} from '#/main/core/tool/store/actions'

import {selectors} from '#/main/privacy/administration/privacy/store/selectors'

const reducer = combineReducers({
lockedParameters: makeReducer([], {
[makeInstanceAction(TOOL_LOAD, 'privacy')]: (state, action) => action.toolData.lockedParameters
}),
parameters: makeFormReducer(selectors.FORM_NAME, {}, {
originalData: makeReducer({}, {
[makeInstanceAction(TOOL_LOAD, 'privacy')]: (state, action) => action.toolData.parameters
}),
data: makeReducer({}, {
[makeInstanceAction(TOOL_LOAD, 'privacy')]: (state, action) => action.toolData.parameters
})
})
})

export {
reducer
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {createSelector} from 'reselect'
import {selectors as formSelectors} from '#/main/app/content/form/store/selectors'

const STORE_NAME = 'privacy'
const FORM_NAME = STORE_NAME+'.parameters'
const store = (state) => state[STORE_NAME]

const lockedParameters = createSelector(
[store],
(store) => store.lockedParameters
)

const parameters = (state) => formSelectors.data(formSelectors.form(state, FORM_NAME))


export const selectors = {
STORE_NAME,
store,
lockedParameters,
parameters,
FORM_NAME
}
9 changes: 9 additions & 0 deletions src/main/privacy/Resources/modules/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {registry} from '#/main/app/plugins/registry'

registry.add('ClarolinePrivacyBundle', {
administration: {
'privacy': () => {
return import(/* webpackChunkName: "main-privacy-admin-privacy" */ '#/main/privacy/administration/privacy')
}
}
})
3 changes: 3 additions & 0 deletions src/main/privacy/Resources/translations/tools.en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"privacy": "Private life"
}
3 changes: 3 additions & 0 deletions src/main/privacy/Resources/translations/tools.fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"privacy": "Vie privée"
}
39 changes: 39 additions & 0 deletions src/main/privacy/Subscriber/Administration/PrivacySubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Claroline\PrivacyBundle\Subscriber\Administration;

use Claroline\CoreBundle\API\Serializer\ParametersSerializer;
use Claroline\CoreBundle\Entity\Tool\Tool;
use Claroline\CoreBundle\Event\CatalogEvents\ToolEvents;
use Claroline\CoreBundle\Event\Tool\OpenToolEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PrivacySubscriber implements EventSubscriberInterface
{
const NAME = 'privacy';

private ParametersSerializer $serializer;

public function __construct(
ParametersSerializer $serializer,
) {
$this->serializer = $serializer;
}

public static function getSubscribedEvents(): array
{
return [
ToolEvents::getEventName(ToolEvents::OPEN, Tool::ADMINISTRATION, static::NAME) => 'onOpen',
];
}

public function onOpen(OpenToolEvent $event): void
{
$parameters = $this->serializer->serialize();

$event->setData([
'lockedParameters' => $parameters['lockedParameters'] ?? [],
'parameters' => $parameters,
]);
}
}

0 comments on commit 87535da

Please sign in to comment.