Skip to content

Commit

Permalink
Merge pull request #69 from ConductionNL/development
Browse files Browse the repository at this point in the history
Development to main
  • Loading branch information
remko48 authored Nov 21, 2024
2 parents b725a03 + d4c141c commit cfabf6c
Show file tree
Hide file tree
Showing 38 changed files with 659 additions and 500 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/pull-request-from-branch-check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Main Branch Protection

on:
pull_request:
branches:
- main

jobs:
check-branch:
runs-on: ubuntu-latest
steps:
- name: Check branch
run: |
if [[ ${GITHUB_HEAD_REF} != development ]] && [[ ${GITHUB_HEAD_REF} != documentation ]] && ! [[ ${GITHUB_HEAD_REF} =~ ^hotfix/ ]];
then
echo "Error: Pull request must come from 'development', 'documentation' or 'hotfix/' branch"
exit 1
fi
21 changes: 21 additions & 0 deletions .github/workflows/pull-request-lint-check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Lint Check

on:
pull_request:
branches:
- development
- main

jobs:
lint-check:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install dependencies
run: npm i

- name: Linting
run: npm run lint
2 changes: 2 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
['name' => 'dashboard#page', 'url' => '/', 'verb' => 'GET'],
['name' => 'registers#objects', 'url' => '/api/registers-objects/{register}/{schema}', 'verb' => 'GET'],
['name' => 'objects#logs', 'url' => '/api/objects-logs/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'objects#mappings', 'url' => '/api/objects/mappings', 'verb' => 'GET'],
['name' => 'objects#auditTrails', 'url' => '/api/objects/audit-trails/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'schemas#upload', 'url' => '/api/schemas/upload', 'verb' => 'POST'],
['name' => 'schemas#uploadUpdate', 'url' => '/api/schemas/{id}/upload', 'verb' => 'PUT', 'requirements' => ['id' => '[^/]+']],
['name' => 'schemas#download', 'url' => '/api/schemas/{id}/download', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ services:
- TZ=Europe/Amsterdam
- NEXTCLOUD_ADMIN_USER=admin
- NEXTCLOUD_ADMIN_PASSWORD=admin
depends_on:
init-ubuntu:
condition: service_completed_successfully
105 changes: 94 additions & 11 deletions lib/Controller/ObjectsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
use OCP\AppFramework\Http\JSONResponse;
use OCP\DB\Exception;
use OCP\IAppConfig;
use OCP\IRequest;
use OCP\IRequest;
use OCP\App\IAppManager;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Opis\JsonSchema\Errors\ErrorFormatter;
use Symfony\Component\Uid\Uuid;
use Psr\Container\ContainerInterface;

class ObjectsController extends Controller
{
Expand All @@ -32,6 +36,8 @@ public function __construct(
$appName,
IRequest $request,
private readonly IAppConfig $config,
private readonly IAppManager $appManager,
private readonly ContainerInterface $container,
private readonly ObjectEntityMapper $objectEntityMapper,
private readonly AuditTrailMapper $auditTrailMapper,
private readonly ObjectAuditLogMapper $objectAuditLogMapper
Expand Down Expand Up @@ -111,20 +117,24 @@ public function show(string $id): JSONResponse
}
}

/**
* Creates a new object
*
* This method creates a new object based on POST data.
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @return JSONResponse A JSON response containing the created object
*/
/**
* Creates a new object
*
* This method creates a new object based on POST data.
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @return JSONResponse A JSON response containing the created object
* @throws Exception
*/
public function create(ObjectService $objectService): JSONResponse
{
$data = $this->request->getParams();
$object = $data['object'];
$mapping = $data['mapping'] ?? null;
$register = $data['register'];
$schema = $data['schema'];

foreach ($data as $key => $value) {
if (str_starts_with($key, '_')) {
Expand All @@ -136,6 +146,17 @@ public function create(ObjectService $objectService): JSONResponse
unset($data['id']);
}

// If mapping ID is provided, transform the object using the mapping
$mappingService = $this->getOpenConnectorMappingService();

if ($mapping !== null && $mappingService !== null) {
$mapping = $mappingService->getMapping($mapping);

$object = $mappingService->executeMapping($mapping, $object);
$data['register'] = $register;
$data['schema'] = $schema;
}

// Save the object
try {
$objectEntity = $objectService->saveObject(register: $data['register'], schema: $data['schema'], object: $object);
Expand Down Expand Up @@ -163,6 +184,7 @@ public function update(int $id): JSONResponse
{
$data = $this->request->getParams();
$object = $data['object'];
$mapping = $data['mapping'] ?? null;

foreach ($data as $key => $value) {
if (str_starts_with($key, '_')) {
Expand All @@ -173,6 +195,14 @@ public function update(int $id): JSONResponse
unset($data['id']);
}

// If mapping ID is provided, transform the object using the mapping
$mappingService = $this->getOpenConnectorMappingService();

if ($mapping !== null && $mappingService !== null) {
$mapping = $mappingService->getMapping($mapping);
$data = $mappingService->executeMapping($mapping, $object);
}

// save it
$oldObject = $this->objectEntityMapper->find($id);
$objectEntity = $this->objectEntityMapper->updateFromArray(id: $id, object: $data);
Expand Down Expand Up @@ -265,4 +295,57 @@ public function logs(int $id): JSONResponse
return new JSONResponse(['error' => 'Logs not found'], 404);
}
}



/**
* Retrieves all available mappings
*
* This method returns a JSON response containing all available mappings in the system.
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @return JSONResponse A JSON response containing the list of mappings
*/
public function mappings(): JSONResponse
{
// Get mapping service, which will return null based on implementation
$mappingService = $this->getOpenConnectorMappingService();

// Initialize results array
$results = [];

// If mapping service exists, get all mappings using find() method
if ($mappingService !== null) {
$results = $mappingService->getMappings();
}

// Return response with results array and total count
return new JSONResponse([
'results' => $results,
'total' => count($results)
]);
}

/**
* Attempts to retrieve the OpenRegister service from the container.
*
* @return mixed|null The OpenRegister service if available, null otherwise.
* @throws ContainerExceptionInterface|NotFoundExceptionInterface
*/
public function getOpenConnectorMappingService(): ?\OCA\OpenConnector\Service\MappingService
{
if (in_array(needle: 'openconnector', haystack: $this->appManager->getInstalledApps()) === true) {
try {
// Attempt to get the OpenRegister service from the container
return $this->container->get('OCA\OpenConnector\Service\MappingService');
} catch (Exception $e) {
// If the service is not available, return null
return null;
}
}

return null;
}
}
10 changes: 5 additions & 5 deletions lib/Db/ObjectEntityMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/**
* The ObjectEntityMapper class
*
*
* @package OCA\OpenRegister\Db
*/
class ObjectEntityMapper extends QBMapper
Expand All @@ -35,7 +35,7 @@ public function __construct(IDBConnection $db, MySQLJsonService $mySQLJsonServic
{
parent::__construct($db, 'openregister_objects');

if($db->getDatabasePlatform() instanceof MySQLPlatform === true) {
if ($db->getDatabasePlatform() instanceof MySQLPlatform === true) {
$this->databaseJsonService = $mySQLJsonService;
}
}
Expand Down Expand Up @@ -235,15 +235,15 @@ public function updateFromArray(int $id, array $object): ObjectEntity
*/
public function getFacets(array $filters = [], ?string $search = null)
{
if(key_exists(key: 'register', array: $filters) === true) {
if (key_exists(key: 'register', array: $filters) === true) {
$register = $filters['register'];
}
if(key_exists(key: 'schema', array: $filters) === true) {
if (key_exists(key: 'schema', array: $filters) === true) {
$schema = $filters['schema'];
}

$fields = [];
if(isset($filters['_queries'])) {
if (isset($filters['_queries'])) {
$fields = $filters['_queries'];
}

Expand Down
6 changes: 3 additions & 3 deletions lib/Db/SchemaMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

/**
* The SchemaMapper class
*
*
* @package OCA\OpenRegister\Db
*/
class SchemaMapper extends QBMapper
Expand Down Expand Up @@ -54,7 +54,7 @@ public function find(int $id): Schema
public function findMultiple(array $ids): array
{
$result = [];
foreach($ids as $id) {
foreach ($ids as $id) {
$result[] = $this->find($id);
}

Expand Down Expand Up @@ -116,7 +116,7 @@ public function createFromArray(array $object): Schema
if ($schema->getUuid() === null) {
$schema->setUuid(Uuid::v4());
}

return $this->insert(entity: $schema);
}

Expand Down
12 changes: 6 additions & 6 deletions lib/Service/MySQLJsonService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
* Service class for handling MySQL JSON operations
*
*
* This class provides methods for querying and filtering JSON data stored in MySQL,
* including complex filtering, searching, ordering and aggregation functionality.
*/
Expand All @@ -23,7 +23,7 @@ class MySQLJsonService implements IDatabaseJsonService
public function orderJson(IQueryBuilder $builder, array $order = []): IQueryBuilder
{
// Loop through each ordering field and direction
foreach($order as $item=>$direction) {
foreach ($order as $item=>$direction) {
// Create parameters for the JSON path and sort direction
$builder->createNamedParameter(value: "$.$item", placeHolder: ":path$item");
$builder->createNamedParameter(value: $direction, placeHolder: ":direction$item");
Expand Down Expand Up @@ -108,7 +108,7 @@ private function jsonFilterArray(IQueryBuilder $builder, string $filter, array $
private function getMultipleContains (array $values, string $filter, IQueryBuilder $builder): string
{
$orString = '';
foreach($values as $key=>$value)
foreach ($values as $key=>$value)
{
// Create parameter for each value
$builder->createNamedParameter(value: $value, type: IQueryBuilder::PARAM_STR, placeHolder: ":value$filter$key");
Expand All @@ -126,7 +126,7 @@ private function getMultipleContains (array $values, string $filter, IQueryBuild
* - Complex filters (after/before)
* - Array filters
* - Simple equality filters
*
*
* @param IQueryBuilder $builder The query builder instance
* @param array $filters Array of filters to apply
* @return IQueryBuilder The modified query builder
Expand All @@ -136,7 +136,7 @@ public function filterJson(IQueryBuilder $builder, array $filters): IQueryBuilde
// Remove special system fields from filters
unset($filters['register'], $filters['schema'], $filters['updated'], $filters['created'], $filters['_queries']);

foreach($filters as $filter=>$value) {
foreach ($filters as $filter=>$value) {
// Create parameter for JSON path
$builder->createNamedParameter(value: "$.$filter", placeHolder: ":path$filter");

Expand Down Expand Up @@ -179,7 +179,7 @@ public function getAggregations(IQueryBuilder $builder, array $fields, int $regi
{
$facets = [];

foreach($fields as $field) {
foreach ($fields as $field) {
// Create parameter for JSON path
$builder->createNamedParameter(value: "$.$field", placeHolder: ":$field");

Expand Down
Loading

0 comments on commit cfabf6c

Please sign in to comment.