Пример #1
0
 /**
  * Handles all GET requests.
  *
  * @return array
  */
 protected function handleGET()
 {
     $this->parent->authenticateAdminUser();
     $groupName = $this->resource;
     $username = $this->request->getParameter('user');
     $fields = $this->request->getParameter(ApiOptions::FIELDS, ApiOptions::FIELDS_ALL);
     $attributes = [];
     if ('*' !== $fields) {
         $attributes = explode(',', $fields);
     }
     if (!empty($username)) {
         $asList = $this->request->getParameterAsBool(ApiOptions::AS_LIST);
         if ($asList) {
             $attributes = ['samaccountname'];
         }
         $resources = $this->provider->getGroups($username, $attributes);
     } else {
         if (empty($groupName)) {
             $asList = $this->request->getParameterAsBool(ApiOptions::AS_LIST);
             if ($asList) {
                 $attributes = ['samaccountname'];
             }
             $resources = $this->provider->listGroup($attributes);
         } else {
             $adGroup = $this->provider->getGroupByCn($groupName);
             $resources = $adGroup->getData($attributes);
         }
     }
     return ResourcesWrapper::cleanResources($resources);
 }
Пример #2
0
 public function getApiDocInfo()
 {
     $base = parent::getApiDocInfo();
     $wrapper = ResourcesWrapper::getWrapper();
     $models = ['TableSchemas' => ['id' => 'TableSchemas', 'properties' => [$wrapper => ['type' => 'Array', 'description' => 'An array of table definitions.', 'items' => ['$ref' => 'TableSchema']]]], 'TableSchema' => ['id' => 'TableSchema', 'properties' => ['name' => ['type' => 'string', 'description' => 'Identifier/Name for the table.'], 'label' => ['type' => 'string', 'description' => 'Displayable singular name for the table.'], 'plural' => ['type' => 'string', 'description' => 'Displayable plural name for the table.'], 'primary_key' => ['type' => 'string', 'description' => 'Field(s), if any, that represent the primary key of each record.'], 'name_field' => ['type' => 'string', 'description' => 'Field(s), if any, that represent the name of each record.'], 'field' => ['type' => 'Array', 'description' => 'An array of available fields in each record.', 'items' => ['$ref' => 'FieldSchema']]]], 'FieldSchema' => ['id' => 'FieldSchema', 'properties' => ['name' => ['type' => 'string', 'description' => 'The API name of the field.'], 'label' => ['type' => 'string', 'description' => 'The displayable label for the field.'], 'type' => ['type' => 'string', 'description' => 'The DSP abstract data type for this field.'], 'db_type' => ['type' => 'string', 'description' => 'The native database type used for this field.'], 'is_primary_key' => ['type' => 'boolean', 'description' => 'Is this field used as/part of the primary key.'], 'validation' => ['type' => 'Array', 'description' => 'validations to be performed on this field.', 'items' => ['type' => 'string']], 'picklist' => ['type' => 'Array', 'description' => 'Selectable string values for client menus and picklist validation.', 'items' => ['type' => 'string']]]]];
     $base['models'] = array_merge($base['models'], $models);
     return $base;
 }
Пример #3
0
 public function getApiDocInfo()
 {
     $path = '/' . $this->getServiceName() . '/' . $this->getFullPathName();
     $eventPath = $this->getServiceName() . '.' . $this->getFullPathName('.');
     $name = Inflector::camelize($this->name);
     $plural = Inflector::pluralize($name);
     $words = str_replace('_', ' ', $this->name);
     $pluralWords = Inflector::pluralize($words);
     $wrapper = ResourcesWrapper::getWrapper();
     $apis = [['path' => $path, 'description' => "Operations for {$words} administration.", 'operations' => [['method' => 'GET', 'summary' => 'get' . $plural . '() - Retrieve one or more ' . $pluralWords . '.', 'nickname' => 'get' . $plural, 'type' => $plural . 'Response', 'event_name' => [$eventPath . '.list'], 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [ApiOptions::documentOption(ApiOptions::FIELDS)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'List Active Directory ' . strtolower($pluralWords)]]], ['path' => $path . '/{' . strtolower($name) . '_name}', 'operations' => [['method' => 'GET', 'summary' => 'get' . $name . '() - Retrieve one ' . $words . '.', 'nickname' => 'get' . $name, 'type' => $name . 'Response', 'event_name' => $eventPath . '.read', 'parameters' => [['name' => strtolower($name) . '_name', 'description' => 'Identifier of the record to retrieve.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Use the \'fields\' parameter to limit properties that are returned. By default, all fields are returned.']], 'description' => "Operations for individual {$words} administration."]];
     $models = [$plural . 'Response' => ['id' => $plural . 'Response', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of records.', 'items' => ['$ref' => $name . 'Response']]]], $name . 'Response' => ['id' => $name . 'Response', 'properties' => ['objectclass' => ['type' => 'array', 'description' => 'This property identifies the class of which the object is an instance, as well as all structural or abstract superclasses from which that class is derived.'], 'cn' => ['type' => 'string', 'description' => 'Common name of the object'], 'dn' => ['type' => 'string', 'description' => 'Distinguished name of the object'], 'distinguishedname' => ['type' => 'string', 'description' => 'Distinguished name of the object'], 'whencreated' => ['type' => 'string', 'description' => 'Date/Time when object was created'], 'whenchanged' => ['type' => 'string', 'description' => 'Date/Time when object was changed'], 'objectcategory' => ['type' => 'string', 'description' => 'Shows objectCagetory attribute.']]]];
     return ['apis' => $apis, 'models' => $models];
 }
Пример #4
0
<?php

if (\Request::method() === 'POST') {
    $pin = \Request::input('pin');
    $state = \Request::input('state');
    if (empty($pin) && $pin !== 0 || empty($state) && $state !== 0) {
        throw new \DreamFactory\Core\Exceptions\BadRequestException('Please provide pin and state data');
    }
    $gpio = new \a15lam\RpiGpio\GPIO();
    $result = $gpio->write($pin, $state);
    $result = empty($result) ? ['success' => true] : $result;
    return \DreamFactory\Core\Utility\ResourcesWrapper::cleanResources($result);
} else {
    throw new \DreamFactory\Core\Exceptions\BadRequestException('Only POST is accepted');
}
Пример #5
0
 /**
  * Returns CSV payload data
  *
  * @param null $key
  * @param null $default
  *
  * @return array|mixed|null
  * @throws \DreamFactory\Core\Exceptions\BadRequestException
  */
 protected function csv($key = null, $default = null)
 {
     if (!empty($this->contentAsArray)) {
         if (null === $key) {
             return $this->contentAsArray;
         } else {
             return ArrayUtils::get($this->contentAsArray, $key, $default);
         }
     }
     $content = $this->getContent();
     $data = DataFormatter::csvToArray($content);
     if (!empty($content) && empty($data)) {
         throw new BadRequestException('Invalid CSV payload supplied.');
     }
     $payload = ResourcesWrapper::wrapResources($data);
     // Store the content so that formatting is only done once.
     $this->contentAsArray = empty($payload) ? [] : $payload;
     $this->content = $content;
     if (null === $key) {
         if (empty($payload)) {
             return [];
         } else {
             return $payload;
         }
     } else {
         if (empty($payload)) {
             return $default;
         } else {
             return ArrayUtils::get($payload, $key, $default);
         }
     }
 }
Пример #6
0
 public function getApiDocModels()
 {
     $name = Inflector::camelize($this->name);
     $plural = Inflector::pluralize($name);
     $wrapper = ResourcesWrapper::getWrapper();
     return ['ResourceList' => ['id' => 'ResourceList', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of accessible resources available to this service.', 'items' => ['type' => 'string']]]], $name . 'Response' => ['id' => $name . 'Response', 'properties' => [$this->getResourceIdentifier() => ['type' => 'string', 'description' => 'Identifier of the resource.']]], $plural . 'Response' => ['id' => $plural . 'Response', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of resources available to this service.', 'items' => ['$ref' => $name . 'Response']]]], 'Success' => ['id' => 'Success', 'properties' => ['success' => ['type' => 'boolean', 'description' => 'True when API call was successful, false or error otherwise.']]]];
 }
Пример #7
0
 /**
  * {@inheritdoc}
  */
 protected function commitTransaction($extras = null)
 {
     if (empty($this->batchRecords) && empty($this->batchIds)) {
         return null;
     }
     $updates = ArrayUtils::get($extras, 'updates');
     $ssFilters = ArrayUtils::get($extras, 'ss_filters');
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $requireMore = ArrayUtils::get($extras, 'require_more');
     $out = [];
     switch ($this->getAction()) {
         case Verbs::POST:
             $result = $this->collection->batchInsert($this->batchRecords, ['continueOnError' => false]);
             static::processResult($result);
             $out = static::cleanRecords($this->batchRecords, $fields, static::DEFAULT_ID_FIELD);
             break;
         case Verbs::PUT:
             if (empty($updates)) {
                 throw new BadRequestException('Batch operation not supported for update by records.');
             }
             $filter = [static::DEFAULT_ID_FIELD => ['$in' => $this->batchIds]];
             $criteria = static::buildCriteriaArray($filter, null, $ssFilters);
             $result = $this->collection->update($criteria, $updates, ['multiple' => true]);
             $rows = static::processResult($result);
             if (0 === $rows) {
                 throw new NotFoundException('No requested records were found to update.');
             }
             if (count($this->batchIds) !== $rows) {
                 throw new BadRequestException('Batch Error: Not all requested records were found to update.');
             }
             if ($requireMore) {
                 $fieldArray = static::buildFieldArray($fields);
                 /** @var \MongoCursor $result */
                 $result = $this->collection->find($criteria, $fieldArray);
                 $out = static::cleanRecords(iterator_to_array($result));
             } else {
                 $out = static::idsAsRecords(static::mongoIdsToIds($this->batchIds), static::DEFAULT_ID_FIELD);
             }
             break;
         case Verbs::MERGE:
         case Verbs::PATCH:
             if (empty($updates)) {
                 throw new BadRequestException('Batch operation not supported for patch by records.');
             }
             $updates = ['$set' => $updates];
             $filter = [static::DEFAULT_ID_FIELD => ['$in' => $this->batchIds]];
             $criteria = static::buildCriteriaArray($filter, null, $ssFilters);
             $result = $this->collection->update($criteria, $updates, ['multiple' => true]);
             $rows = static::processResult($result);
             if (0 === $rows) {
                 throw new NotFoundException('No requested records were found to patch.');
             }
             if (count($this->batchIds) !== $rows) {
                 throw new BadRequestException('Batch Error: Not all requested records were found to patch.');
             }
             if ($requireMore) {
                 $fieldArray = static::buildFieldArray($fields);
                 /** @var \MongoCursor $result */
                 $result = $this->collection->find($criteria, $fieldArray);
                 $out = static::cleanRecords(iterator_to_array($result));
             } else {
                 $out = static::idsAsRecords(static::mongoIdsToIds($this->batchIds), static::DEFAULT_ID_FIELD);
             }
             break;
         case Verbs::DELETE:
             $filter = [static::DEFAULT_ID_FIELD => ['$in' => $this->batchIds]];
             $criteria = static::buildCriteriaArray($filter, null, $ssFilters);
             if ($requireMore) {
                 $fieldArray = static::buildFieldArray($fields);
                 $result = $this->collection->find($criteria, $fieldArray);
                 $result = static::cleanRecords(iterator_to_array($result));
                 if (empty($result)) {
                     throw new NotFoundException('No records were found using the given identifiers.');
                 }
                 if (count($this->batchIds) !== count($result)) {
                     $errors = [];
                     foreach ($this->batchIds as $index => $id) {
                         $found = false;
                         foreach ($result as $record) {
                             if ($id == ArrayUtils::get($record, static::DEFAULT_ID_FIELD)) {
                                 $out[$index] = $record;
                                 $found = true;
                                 continue;
                             }
                         }
                         if (!$found) {
                             $errors[] = $index;
                             $out[$index] = "Record with identifier '" . print_r($id, true) . "' not found.";
                         }
                     }
                 } else {
                     $out = $result;
                 }
             } else {
                 $out = static::idsAsRecords(static::mongoIdsToIds($this->batchIds), static::DEFAULT_ID_FIELD);
             }
             $result = $this->collection->remove($criteria);
             $rows = static::processResult($result);
             if (0 === $rows) {
                 throw new NotFoundException('No records were found using the given identifiers.');
             }
             if (count($this->batchIds) !== $rows) {
                 throw new BadRequestException('Batch Error: Not all requested records were deleted.');
             }
             break;
         case Verbs::GET:
             $filter = [static::DEFAULT_ID_FIELD => ['$in' => $this->batchIds]];
             $criteria = static::buildCriteriaArray($filter, null, $ssFilters);
             $fieldArray = static::buildFieldArray($fields);
             $result = $this->collection->find($criteria, $fieldArray);
             $result = static::cleanRecords(iterator_to_array($result));
             if (empty($result)) {
                 throw new NotFoundException('No records were found using the given identifiers.');
             }
             if (count($this->batchIds) !== count($result)) {
                 $errors = [];
                 foreach ($this->batchIds as $index => $id) {
                     $found = false;
                     foreach ($result as $record) {
                         if ($id == ArrayUtils::get($record, static::DEFAULT_ID_FIELD)) {
                             $out[$index] = $record;
                             $found = true;
                             continue;
                         }
                     }
                     if (!$found) {
                         $errors[] = $index;
                         $out[$index] = "Record with identifier '" . print_r($id, true) . "' not found.";
                     }
                 }
                 if (!empty($errors)) {
                     $wrapper = ResourcesWrapper::getWrapper();
                     $context = ['error' => $errors, $wrapper => $out];
                     throw new NotFoundException('Batch Error: Not all records could be retrieved.', null, null, $context);
                 }
             }
             $out = $result;
             break;
         default:
             break;
     }
     $this->batchIds = [];
     $this->batchRecords = [];
     return $out;
 }
Пример #8
0
 /**
  * Handles DELETE action
  *
  * @return \DreamFactory\Core\Utility\ServiceResponse
  * @throws BadRequestException
  * @throws \Exception
  */
 protected function handleDELETE()
 {
     $deleteStorage = $this->request->getParameterAsBool('delete_storage');
     $fields = $this->request->getParameter('fields');
     if ($deleteStorage) {
         if (empty($fields)) {
             $fields = 'id,storage_service_id,storage_container';
         } else {
             if ($fields !== '*') {
                 $fields = explode(',', $fields);
                 if (!in_array('id', $fields)) {
                     $fields[] = 'id';
                 }
                 if (!in_array('storage_service_id', $fields)) {
                     $fields[] = 'storage_service_id';
                 }
                 if (!in_array('storage_container', $fields)) {
                     $fields[] = 'storage_container';
                 }
                 $fields = implode(',', $fields);
             }
         }
         $this->request->setParameter('fields', $fields);
     }
     $result = parent::handleDELETE();
     if ($deleteStorage) {
         $temp = $result;
         $wrapper = ResourcesWrapper::getWrapper();
         if (isset($result[$wrapper])) {
             $temp = ResourcesWrapper::unwrapResources($temp);
         }
         if (ArrayUtils::isArrayNumeric($temp)) {
             foreach ($temp as $app) {
                 static::deleteHostedAppStorage($app['id'], $app['storage_service_id'], $app['storage_container']);
             }
         } else {
             static::deleteHostedAppStorage($temp['id'], $temp['storage_service_id'], $temp['storage_container']);
         }
     }
     return $result;
 }
Пример #9
0
 public static function getApiDocCommonModels()
 {
     $wrapper = ResourcesWrapper::getWrapper();
     return ['TableSchemas' => ['id' => 'TableSchemas', 'properties' => [$wrapper => ['type' => 'Array', 'description' => 'An array of table definitions.', 'items' => ['$ref' => 'TableSchema']]]], 'TableSchema' => ['id' => 'TableSchema', 'properties' => ['name' => ['type' => 'string', 'description' => 'Identifier/Name for the table.'], 'label' => ['type' => 'string', 'description' => 'Displayable singular name for the table.'], 'plural' => ['type' => 'string', 'description' => 'Displayable plural name for the table.'], 'primary_key' => ['type' => 'string', 'description' => 'Field(s), if any, that represent the primary key of each record.'], 'name_field' => ['type' => 'string', 'description' => 'Field(s), if any, that represent the name of each record.'], 'field' => ['type' => 'Array', 'description' => 'An array of available fields in each record.', 'items' => ['$ref' => 'FieldSchema']], 'related' => ['type' => 'Array', 'description' => 'An array of available relationships to other tables.', 'items' => ['$ref' => 'RelatedSchema']]]], 'FieldSchema' => ['id' => 'FieldSchema', 'properties' => ['name' => ['type' => 'string', 'description' => 'The API name of the field.'], 'label' => ['type' => 'string', 'description' => 'The displayable label for the field.'], 'type' => ['type' => 'string', 'description' => 'The DSP abstract data type for this field.'], 'db_type' => ['type' => 'string', 'description' => 'The native database type used for this field.'], 'length' => ['type' => 'integer', 'format' => 'int32', 'description' => 'The maximum length allowed (in characters for string, displayed for numbers).'], 'precision' => ['type' => 'integer', 'format' => 'int32', 'description' => 'Total number of places for numbers.'], 'scale' => ['type' => 'integer', 'format' => 'int32', 'description' => 'Number of decimal places allowed for numbers.'], 'default_value' => ['type' => 'string', 'description' => 'Default value for this field.'], 'required' => ['type' => 'boolean', 'description' => 'Is a value required for record creation.'], 'allow_null' => ['type' => 'boolean', 'description' => 'Is null allowed as a value.'], 'fixed_length' => ['type' => 'boolean', 'description' => 'Is the length fixed (not variable).'], 'supports_multibyte' => ['type' => 'boolean', 'description' => 'Does the data type support multibyte characters.'], 'auto_increment' => ['type' => 'boolean', 'description' => 'Does the integer field value increment upon new record creation.'], 'is_primary_key' => ['type' => 'boolean', 'description' => 'Is this field used as/part of the primary key.'], 'is_foreign_key' => ['type' => 'boolean', 'description' => 'Is this field used as a foreign key.'], 'ref_table' => ['type' => 'string', 'description' => 'For foreign keys, the referenced table name.'], 'ref_fields' => ['type' => 'string', 'description' => 'For foreign keys, the referenced table field name.'], 'validation' => ['type' => 'Array', 'description' => 'validations to be performed on this field.', 'items' => ['type' => 'string']], 'value' => ['type' => 'Array', 'description' => 'Selectable string values for client menus and picklist validation.', 'items' => ['type' => 'string']]]], 'RelatedSchema' => ['id' => 'RelatedSchema', 'properties' => ['name' => ['type' => 'string', 'description' => 'Name of the relationship.'], 'type' => ['type' => 'string', 'description' => 'Relationship type - belongs_to, has_many, many_many.'], 'ref_table' => ['type' => 'string', 'description' => 'The table name that is referenced by the relationship.'], 'ref_fields' => ['type' => 'string', 'description' => 'The field name that is referenced by the relationship.'], 'join' => ['type' => 'string', 'description' => 'The intermediate joining table used for many_many relationships.'], 'field' => ['type' => 'string', 'description' => 'The current table field that is used in the relationship.']]]];
 }
Пример #10
0
 /**
  * Handles GET action
  *
  * @return mixed
  */
 protected function handleGET()
 {
     $resources = $this->getResources();
     if (is_array($resources)) {
         $includeAccess = $this->request->getParameterAsBool(ApiOptions::INCLUDE_ACCESS);
         $asList = $this->request->getParameterAsBool(ApiOptions::AS_LIST);
         $idField = $this->request->getParameter(ApiOptions::ID_FIELD, $this->getResourceIdentifier());
         $fields = $this->request->getParameter(ApiOptions::FIELDS);
         if (!$asList && $includeAccess) {
             foreach ($resources as &$resource) {
                 if (is_array($resource)) {
                     $name = ArrayUtils::get($resource, $idField);
                     $resource['access'] = VerbsMask::maskToArray($this->getPermissions($name));
                 }
             }
         }
         return ResourcesWrapper::cleanResources($resources, $asList, $idField, $fields);
     }
     return $resources;
 }
Пример #11
0
 /**
  * Handles GET action
  *
  * @return array
  * @throws NotFoundException
  */
 protected function handleGET()
 {
     if (empty($this->resource)) {
         $service = $this->request->getParameter('service');
         $type = $this->request->getParameter('type');
         $onlyScripted = $this->request->getParameterAsBool('only_scripted');
         if ($onlyScripted) {
             switch ($type) {
                 case 'process':
                     $scripts = EventScript::where('affects_process', 1)->lists('name')->all();
                     break;
                 case 'broadcast':
                     $scripts = EventScript::where('affects_process', 0)->lists('name')->all();
                     break;
                 default:
                     $scripts = EventScript::lists('name')->all();
                     break;
             }
             return ResourcesWrapper::cleanResources(array_values(array_unique($scripts)));
         }
         $results = $this->getEventMap();
         $allEvents = [];
         switch ($type) {
             case 'process':
                 $results = ArrayUtils::get($results, 'process', []);
                 foreach ($results as $serviceKey => $apis) {
                     if (!empty($service) && 0 !== strcasecmp($service, $serviceKey)) {
                         unset($results[$serviceKey]);
                     } else {
                         foreach ($apis as $path => $operations) {
                             foreach ($operations['verb'] as $method => $events) {
                                 $allEvents = array_merge($allEvents, $events);
                             }
                         }
                     }
                 }
                 break;
             case 'broadcast':
                 $results = ArrayUtils::get($results, 'broadcast', []);
                 foreach ($results as $serviceKey => $apis) {
                     if (!empty($service) && 0 !== strcasecmp($service, $serviceKey)) {
                         unset($results[$serviceKey]);
                     } else {
                         foreach ($apis as $path => $operations) {
                             foreach ($operations['verb'] as $method => $events) {
                                 $allEvents = array_merge($allEvents, $events);
                             }
                         }
                     }
                 }
                 break;
             default:
                 foreach ($results as $type => $services) {
                     foreach ($services as $serviceKey => $apis) {
                         if (!empty($service) && 0 !== strcasecmp($service, $serviceKey)) {
                             unset($results[$type][$serviceKey]);
                         } else {
                             foreach ($apis as $path => $operations) {
                                 foreach ($operations['verb'] as $method => $events) {
                                     $allEvents = array_merge($allEvents, $events);
                                 }
                             }
                         }
                     }
                 }
                 break;
         }
         if (!$this->request->getParameterAsBool(ApiOptions::AS_LIST)) {
             return $results;
         }
         return ResourcesWrapper::cleanResources(array_values(array_unique($allEvents)));
     }
     $related = $this->request->getParameter(ApiOptions::RELATED);
     if (!empty($related)) {
         $related = explode(',', $related);
     } else {
         $related = [];
     }
     //	Single script by name
     $fields = [ApiOptions::FIELDS_ALL];
     if (null !== ($value = $this->request->getParameter(ApiOptions::FIELDS))) {
         $fields = explode(',', $value);
     }
     if (null === ($foundModel = EventScript::with($related)->find($this->resource, $fields))) {
         throw new NotFoundException("Script not found.");
     }
     return ResponseFactory::create($foundModel->toArray(), $this->nativeFormat);
 }
Пример #12
0
 /**
  * @param array $array
  *
  * @return string
  */
 public static function arrayToCsv($array)
 {
     if (!is_array($array) || empty($array)) {
         return '';
     }
     $array = ArrayUtils::get($array, ResourcesWrapper::getWrapper(), ArrayUtils::get($array, 'error', $array));
     $data = [];
     if (!isset($array[0])) {
         $data[] = $array;
     } else {
         $data = $array;
     }
     $keys = array_keys(ArrayUtils::get($data, 0, []));
     // currently need to write out to file to use parser
     $tmpDir = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
     $filename = $tmpDir . 'csv_export' . time() . '.csv';
     $handle = fopen($filename, 'w');
     // build header row
     fputcsv($handle, $keys);
     foreach ($data as $row) {
         foreach ($row as $key => $value) {
             // handle objects and array non-conformist to csv output
             if (is_array($value) || is_object($value)) {
                 $row[$key] = json_encode($value);
             }
         }
         fputcsv($handle, $row);
     }
     fclose($handle);
     $csv = file_get_contents($filename);
     unlink($filename);
     return $csv;
 }
Пример #13
0
 public function getApiDocModels()
 {
     $name = Inflector::camelize($this->name);
     $plural = Inflector::pluralize($name);
     $wrapper = ResourcesWrapper::getWrapper();
     return [$plural . 'List' => ['id' => $plural . 'List', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of accessible resources available to this path.', 'items' => ['type' => 'string']]]], $name . 'Response' => ['id' => $name . 'Response', 'properties' => [$this->getResourceIdentifier() => ['type' => 'string', 'description' => 'Identifier of the resource.']]], $plural . 'Response' => ['id' => $plural . 'Response', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of resources available to this path.', 'items' => ['$ref' => $name . 'Response']]]]];
 }
Пример #14
0
 /**
  * {@inheritdoc}
  */
 protected function commitTransaction($extras = null)
 {
     if (empty($this->batchRecords) && empty($this->batchIds)) {
         if (isset($this->transaction)) {
             $this->transaction->commit();
         }
         return null;
     }
     $updates = ArrayUtils::get($extras, 'updates');
     $ssFilters = ArrayUtils::get($extras, 'ss_filters');
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $idFields = ArrayUtils::get($extras, 'id_fields');
     $related = ArrayUtils::get($extras, 'related');
     $requireMore = ArrayUtils::getBool($extras, 'require_more') || !empty($related);
     $allowRelatedDelete = ArrayUtils::getBool($extras, 'allow_related_delete', false);
     $relatedInfo = $this->describeTableRelated($this->transactionTable);
     $where = [];
     $params = [];
     $idName = isset($this->tableIdsInfo, $this->tableIdsInfo[0], $this->tableIdsInfo[0]->name) ? $this->tableIdsInfo[0]->name : null;
     if (empty($idName)) {
         throw new BadRequestException('No valid identifier found for this table.');
     }
     if (!empty($this->batchRecords)) {
         if (is_array($this->batchRecords[0])) {
             $temp = [];
             foreach ($this->batchRecords as $record) {
                 $temp[] = ArrayUtils::get($record, $idName);
             }
             $where[] = ['in', $idName, $temp];
         } else {
             $where[] = ['in', $idName, $this->batchRecords];
         }
     } else {
         $where[] = ['in', $idName, $this->batchIds];
     }
     $serverFilter = $this->buildQueryStringFromData($ssFilters, $params);
     if (!empty($serverFilter)) {
         $where[] = $serverFilter;
     }
     if (count($where) > 1) {
         array_unshift($where, 'AND');
     } else {
         $where = $where[0];
     }
     $out = [];
     $action = $this->getAction();
     if (!empty($this->batchRecords)) {
         if (1 == count($this->tableIdsInfo)) {
             // records are used to retrieve extras
             // ids array are now more like records
             $fields = empty($fields) ? $idFields : $fields;
             $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
             $bindings = ArrayUtils::get($result, 'bindings');
             $fields = ArrayUtils::get($result, 'fields');
             $fields = empty($fields) ? '*' : $fields;
             $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
             if (empty($result)) {
                 throw new NotFoundException('No records were found using the given identifiers.');
             }
             $out = $result;
         } else {
             $out = $this->retrieveRecords($this->transactionTable, $this->batchRecords, $extras);
         }
         $this->batchRecords = [];
     } elseif (!empty($this->batchIds)) {
         /** @var Command $command */
         $command = $this->dbConn->createCommand();
         switch ($action) {
             case Verbs::PUT:
             case Verbs::MERGE:
             case Verbs::PATCH:
                 if (!empty($updates)) {
                     $parsed = $this->parseRecord($updates, $this->tableFieldsInfo, $ssFilters, true);
                     if (!empty($parsed)) {
                         $rows = $command->update($this->transactionTable, $parsed, $where, $params);
                         if (0 >= $rows) {
                             throw new NotFoundException('No records were found using the given identifiers.');
                         }
                         if (count($this->batchIds) !== $rows) {
                             throw new BadRequestException('Batch Error: Not all requested records could be updated.');
                         }
                     }
                     foreach ($this->batchIds as $id) {
                         if (!empty($relatedInfo)) {
                             $this->updateRelations($this->transactionTable, $updates, $id, $relatedInfo, $allowRelatedDelete);
                         }
                     }
                     if ($requireMore) {
                         $fields = empty($fields) ? $idFields : $fields;
                         $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
                         $bindings = ArrayUtils::get($result, 'bindings');
                         $fields = ArrayUtils::get($result, 'fields');
                         $fields = empty($fields) ? '*' : $fields;
                         $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
                         if (empty($result)) {
                             throw new NotFoundException('No records were found using the given identifiers.');
                         }
                         $out = $result;
                     }
                 }
                 break;
             case Verbs::DELETE:
                 if ($requireMore) {
                     $fields = empty($fields) ? $idFields : $fields;
                     $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
                     $bindings = ArrayUtils::get($result, 'bindings');
                     $fields = ArrayUtils::get($result, 'fields');
                     $fields = empty($fields) ? '*' : $fields;
                     $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
                     if (count($this->batchIds) !== count($result)) {
                         $errors = [];
                         foreach ($this->batchIds as $index => $id) {
                             $found = false;
                             if (empty($result)) {
                                 foreach ($result as $record) {
                                     if ($id == ArrayUtils::get($record, $idName)) {
                                         $out[$index] = $record;
                                         $found = true;
                                         continue;
                                     }
                                 }
                             }
                             if (!$found) {
                                 $errors[] = $index;
                                 $out[$index] = "Record with identifier '" . print_r($id, true) . "' not found.";
                             }
                         }
                     } else {
                         $out = $result;
                     }
                 }
                 $rows = $command->delete($this->transactionTable, $where, $params);
                 if (count($this->batchIds) !== $rows) {
                     throw new BadRequestException('Batch Error: Not all requested records were deleted.');
                 }
                 break;
             case Verbs::GET:
                 $fields = empty($fields) ? $idFields : $fields;
                 $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
                 $bindings = ArrayUtils::get($result, 'bindings');
                 $fields = ArrayUtils::get($result, 'fields');
                 $fields = empty($fields) ? '*' : $fields;
                 $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
                 if (empty($result)) {
                     throw new NotFoundException('No records were found using the given identifiers.');
                 }
                 if (count($this->batchIds) !== count($result)) {
                     $errors = [];
                     foreach ($this->batchIds as $index => $id) {
                         $found = false;
                         foreach ($result as $record) {
                             if ($id == ArrayUtils::get($record, $idName)) {
                                 $out[$index] = $record;
                                 $found = true;
                                 continue;
                             }
                         }
                         if (!$found) {
                             $errors[] = $index;
                             $out[$index] = "Record with identifier '" . print_r($id, true) . "' not found.";
                         }
                     }
                     if (!empty($errors)) {
                         $context = ['error' => $errors, ResourcesWrapper::getWrapper() => $out];
                         throw new NotFoundException('Batch Error: Not all records could be retrieved.', null, null, $context);
                     }
                 }
                 $out = $result;
                 break;
             default:
                 break;
         }
         if (empty($out)) {
             $out = [];
             foreach ($this->batchIds as $id) {
                 $out[] = [$idName => $id];
             }
         }
         $this->batchIds = [];
     }
     if (isset($this->transaction)) {
         $this->transaction->commit();
     }
     return $out;
 }
Пример #15
0
 public function getApiDocInfo()
 {
     $path = '/' . $this->getServiceName() . '/' . $this->getFullPathName();
     $eventPath = $this->getServiceName() . '.' . $this->getFullPathName('.');
     $base = parent::getApiDocInfo();
     $tables = $this->listResources();
     $commonResponses = ApiDocUtilities::getCommonResponses();
     $wrapper = ResourcesWrapper::getWrapper();
     $apis = [['path' => $path . '/{table_name}', 'description' => 'Operations for table records administration.', 'operations' => [['method' => 'GET', 'summary' => 'getRecords() - Retrieve one or more records.', 'nickname' => 'getRecords', 'notes' => 'Set the <b>filter</b> parameter to a SQL WHERE clause (optional native filter accepted in some scenarios) ' . 'to limit records returned or leave it blank to return all records up to the maximum limit.<br/> ' . 'Set the <b>limit</b> parameter with or without a filter to return a specific amount of records.<br/> ' . 'Use the <b>offset</b> parameter along with the <b>limit</b> parameter to page through sets of records.<br/> ' . 'Set the <b>order</b> parameter to SQL ORDER_BY clause containing field and optional direction (<field_name> [ASC|DESC]) to order the returned records.<br/> ' . 'Alternatively, to send the <b>filter</b> with or without <b>params</b> as posted data, ' . 'use the getRecordsByPost() POST request and post a filter with or without params.<br/>' . 'Pass the identifying field values as a comma-separated list in the <b>ids</b> parameter.<br/> ' . 'Use the <b>id_field</b> and <b>id_type</b> parameters to override or specify detail for identifying fields where applicable.<br/> ' . 'Alternatively, to send the <b>ids</b> as posted data, use the getRecordsByPost() POST request.<br/> ' . 'Use the <b>fields</b> parameter to limit properties returned for each record. ' . 'By default, all fields are returned for all records. ', 'type' => 'RecordsResponse', 'event_name' => [$eventPath . '.{table_name}.select', $eventPath . '.table_selected'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ApiOptions::documentOption(ApiOptions::FILTER), ApiOptions::documentOption(ApiOptions::LIMIT), ApiOptions::documentOption(ApiOptions::ORDER), ApiOptions::documentOption(ApiOptions::GROUP), ApiOptions::documentOption(ApiOptions::OFFSET), ApiOptions::documentOption(ApiOptions::INCLUDE_COUNT), ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::CONTINUES), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED), ApiOptions::documentOption(ApiOptions::INCLUDE_SCHEMA), ApiOptions::documentOption(ApiOptions::FILE)], 'responseMessages' => $commonResponses], ['method' => 'POST', 'summary' => 'createRecords() - Create one or more records.', 'nickname' => 'createRecords', 'notes' => 'Posted data should be an array of records wrapped in a <b>record</b> element.<br/> ' . 'By default, only the id property of the record is returned on success. ' . 'Use <b>fields</b> parameter to return more info.', 'type' => 'RecordsResponse', 'event_name' => [$eventPath . '.{table_name}.insert', $eventPath . '.table_inserted'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'body', 'description' => 'Data containing name-value pairs of records to create.', 'allowMultiple' => false, 'type' => 'RecordsRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::CONTINUES), ApiOptions::documentOption(ApiOptions::ROLLBACK), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED), ['name' => 'X-HTTP-METHOD', 'description' => 'Override request using POST to tunnel other http request, such as DELETE or GET passing a payload.', 'enum' => ['GET'], 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'header', 'required' => false]], 'responseMessages' => $commonResponses], ['method' => 'PUT', 'summary' => 'replaceRecords() - Update (replace) one or more records.', 'nickname' => 'replaceRecords', 'notes' => 'Post data should be an array of records wrapped in a <b>' . $wrapper . '</b> tag.<br/> ' . 'If ids or filter is used, posted body should be a single record with name-value pairs ' . 'to update, wrapped in a <b>' . $wrapper . '</b> tag.<br/> ' . 'Ids can be included via URL parameter or included in the posted body.<br/> ' . 'Filter can be included via URL parameter or included in the posted body.<br/> ' . 'By default, only the id property of the record is returned on success. ' . 'Use <b>fields</b> parameter to return more info.', 'type' => 'RecordsResponse', 'event_name' => [$eventPath . '.{table_name}.update', $eventPath . '.table_updated'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'body', 'description' => 'Data containing name-value pairs of records to update.', 'allowMultiple' => false, 'type' => 'RecordsRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::CONTINUES), ApiOptions::documentOption(ApiOptions::ROLLBACK), ApiOptions::documentOption(ApiOptions::FILTER), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => $commonResponses], ['method' => 'PATCH', 'summary' => 'updateRecords() - Update (patch) one or more records.', 'nickname' => 'updateRecords', 'notes' => 'Post data should be an array of records containing at least the identifying fields for each record.<br/> ' . 'Posted body should be a single record with name-value pairs to update wrapped in a <b>record</b> tag.<br/> ' . 'Ids can be included via URL parameter or included in the posted body.<br/> ' . 'Filter can be included via URL parameter or included in the posted body.<br/> ' . 'By default, only the id property of the record is returned on success. ' . 'Use <b>fields</b> parameter to return more info.', 'type' => 'RecordsResponse', 'event_name' => [$eventPath . '.{table_name}.update', $eventPath . '.table_updated'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'body', 'description' => 'A single record containing name-value pairs of fields to update.', 'allowMultiple' => false, 'type' => 'RecordsRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::CONTINUES), ApiOptions::documentOption(ApiOptions::ROLLBACK), ApiOptions::documentOption(ApiOptions::FILTER), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => $commonResponses], ['method' => 'DELETE', 'summary' => 'deleteRecords() - Delete one or more records.', 'nickname' => 'deleteRecords', 'notes' => 'Set the <b>ids</b> parameter to a list of record identifying (primary key) values to delete specific records.<br/> ' . 'Alternatively, to delete records by a large list of ids, pass the ids in the <b>body</b>.<br/> ' . 'By default, only the id property of the record is returned on success, use <b>fields</b> to return more info. ' . 'Set the <b>filter</b> parameter to a SQL WHERE clause to delete specific records, ' . 'otherwise set <b>force</b> to true to clear the table.<br/> ' . 'Alternatively, to delete by a complicated filter or to use parameter replacement, pass the filter with or without params as the <b>body</b>.<br/> ' . 'By default, only the id property of the record is returned on success, use <b>fields</b> to return more info. ' . 'Set the <b>body</b> to an array of records, minimally including the identifying fields, to delete specific records.<br/> ' . 'By default, only the id property of the record is returned on success, use <b>fields</b> to return more info. ', 'type' => 'RecordsResponse', 'event_name' => [$eventPath . '.{table_name}.delete', $eventPath . '.table_deleted'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'body', 'description' => 'Data containing ids of records to delete.', 'allowMultiple' => false, 'type' => 'RecordsRequest', 'paramType' => 'body', 'required' => false], ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::CONTINUES), ApiOptions::documentOption(ApiOptions::ROLLBACK), ApiOptions::documentOption(ApiOptions::FILTER), ApiOptions::documentOption(ApiOptions::FORCE), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => $commonResponses]]], ['path' => $path . '/{table_name}/{id}', 'description' => 'Operations for single record administration.', 'operations' => [['method' => 'GET', 'summary' => 'getRecord() - Retrieve one record by identifier.', 'nickname' => 'getRecord', 'notes' => 'Use the <b>fields</b> parameter to limit properties that are returned. ' . 'By default, all fields are returned.', 'type' => 'RecordResponse', 'event_name' => [$eventPath . '.{table_name}.{id}.select', $eventPath . '.record_selected'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'id', 'description' => 'Identifier of the record to retrieve.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => $commonResponses], ['method' => 'PUT', 'summary' => 'replaceRecord() - Replace the content of one record by identifier.', 'nickname' => 'replaceRecord', 'notes' => 'Post data should be an array of fields for a single record.<br/> ' . 'Use the <b>fields</b> parameter to return more properties. By default, the id is returned.', 'type' => 'RecordResponse', 'event_name' => [$eventPath . '.{table_name}.{id}.update', $eventPath . '.record_updated'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'id', 'description' => 'Identifier of the record to update.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ['name' => 'body', 'description' => 'Data containing name-value pairs of the replacement record.', 'allowMultiple' => false, 'type' => 'RecordRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => $commonResponses], ['method' => 'PATCH', 'summary' => 'updateRecord() - Update (patch) one record by identifier.', 'nickname' => 'updateRecord', 'notes' => 'Post data should be an array of fields for a single record.<br/> ' . 'Use the <b>fields</b> parameter to return more properties. By default, the id is returned.', 'type' => 'RecordResponse', 'event_name' => [$eventPath . '.{table_name}.{id}.update', $eventPath . '.record_updated'], 'parameters' => [['name' => 'table_name', 'description' => 'The name of the table you want to update.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'id', 'description' => 'Identifier of the record to update.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ['name' => 'body', 'description' => 'Data containing name-value pairs of the fields to update.', 'allowMultiple' => false, 'type' => 'RecordRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::FIELDS)], 'responseMessages' => $commonResponses], ['method' => 'DELETE', 'summary' => 'deleteRecord() - Delete one record by identifier.', 'nickname' => 'deleteRecord', 'notes' => 'Use the <b>fields</b> parameter to return more deleted properties. By default, the id is returned.', 'type' => 'RecordResponse', 'event_name' => [$eventPath . '.{table_name}.{id}.delete', $eventPath . '.record_deleted'], 'parameters' => [['name' => 'table_name', 'description' => 'Name of the table to perform operations on.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true, 'enum' => $tables], ['name' => 'id', 'description' => 'Identifier of the record to delete.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::ID_FIELD), ApiOptions::documentOption(ApiOptions::ID_TYPE), ApiOptions::documentOption(ApiOptions::FIELDS)], 'responseMessages' => $commonResponses]]]];
     $base['apis'] = array_merge($base['apis'], $apis);
     return $base;
 }
Пример #16
0
 /**
  * @param       $records
  * @param array $params
  * @param bool  $singlePayload
  *
  * @return array|mixed
  * @throws BadRequestException
  * @throws \Exception
  */
 public static function bulkDelete($records, $params = [], $singlePayload = false)
 {
     if (empty($records)) {
         throw new BadRequestException('There is no record in the request.');
     }
     $response = [];
     $transaction = null;
     $errors = [];
     $singleRow = 1 === count($records) ? true : false;
     $rollback = ArrayUtils::getBool($params, ApiOptions::ROLLBACK);
     $continue = ArrayUtils::getBool($params, ApiOptions::CONTINUES);
     try {
         //	Start a transaction
         if (!$singleRow && $rollback) {
             DB::beginTransaction();
             $transaction = true;
         }
         foreach ($records as $key => $record) {
             try {
                 $m = new static();
                 $pk = $m->getPrimaryKey();
                 $id = ArrayUtils::get($record, $pk);
                 $response[$key] = static::deleteInternal($id, $record, $params);
             } catch (\Exception $ex) {
                 if ($singleRow) {
                     throw $ex;
                 }
                 if ($rollback && $transaction) {
                     DB::rollBack();
                     throw $ex;
                 }
                 // track the index of the error and copy error to results
                 $errors[] = $key;
                 $response[$key] = $ex->getMessage();
                 if (!$continue) {
                     break;
                 }
             }
         }
     } catch (\Exception $ex) {
         throw $ex;
     }
     if (!empty($errors)) {
         $msg = ['errors' => $errors, ResourcesWrapper::getWrapper() => $response];
         throw new BadRequestException("Batch Error: Not all parts of the request were successful.", null, null, $msg);
     }
     //	Commit
     if ($transaction) {
         try {
             DB::commit();
         } catch (\Exception $ex) {
             throw $ex;
         }
     }
     return $singlePayload ? current($response) : $response;
 }
Пример #17
0
 public function getApiDocModels()
 {
     $wrapper = ResourcesWrapper::getWrapper();
     $base = parent::getApiDocModels();
     $models = ['Tables' => ['id' => 'Tables', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of tables and their properties.', 'items' => ['$ref' => 'Table']]]], 'Table' => ['id' => 'Table', 'properties' => ['name' => ['type' => 'string', 'description' => 'Name of the table.']]]];
     return array_merge($base, $models);
 }
Пример #18
0
 /**
  * Execute the console command.
  *
  * @return mixed
  */
 public function handle()
 {
     if (!class_exists('DreamFactory\\Core\\ADLdap\\Services\\ADLdap')) {
         $this->error('Command unavailable. Please install \'dreamfactory/df-adldap\' package to use this command.');
         return;
     }
     try {
         $serviceName = $this->argument('service');
         $username = $this->option('username');
         $password = $this->option('password');
         /** @type ADLdap $service */
         $service = ServiceHandler::getService($serviceName);
         $serviceModel = Service::find($service->getServiceId());
         $serviceType = $serviceModel->serviceType()->first();
         $serviceGroup = $serviceType->group;
         if ($serviceGroup !== ServiceTypeGroups::LDAP) {
             throw new BadRequestException('Invalid service name [' . $serviceName . ']. Please use a valid Active Directory service');
         }
         $this->line('Contacting your Active Directory server...');
         $service->authenticateAdminUser($username, $password);
         $this->line('Fetching Active Directory groups...');
         $groups = $service->getDriver()->listGroup(['dn', 'description']);
         $roles = [];
         foreach ($groups as $group) {
             $dfRole = RoleADLdap::whereDn($group['dn'])->first();
             if (empty($dfRole)) {
                 $role = ['name' => static::dnToRoleName($group['dn']), 'description' => $group['description'], 'is_active' => true, 'role_adldap_by_role_id' => [['dn' => $group['dn']]]];
                 $this->info('|--------------------------------------------------------------------');
                 $this->info('| DN: ' . $group['dn']);
                 $this->info('| Role Name: ' . $role['name']);
                 $this->info('| Description: ' . $role['description']);
                 $this->info('|--------------------------------------------------------------------');
                 $roles[] = $role;
             }
         }
         $roleCount = count($roles);
         if ($roleCount > 0) {
             $this->warn('Total Roles to import: [' . $roleCount . ']');
             if ($this->confirm('The above roles will be imported into your DreamFactroy instance based on your Active Directory groups. Do you wish to continue?')) {
                 $this->line('Importing Roles...');
                 $payload = ResourcesWrapper::wrapResources($roles);
                 ServiceHandler::handleRequest(Verbs::POST, 'system', 'role', ['continue' => true], $payload);
                 $this->info('Successfully imported all Active Directory groups as Roles.');
             } else {
                 $this->info('Aborted import process. No Roles were imported');
             }
         } else {
             if (count($groups) > 0 && $roleCount === 0) {
                 $this->info('All groups found on the Active Directory server are already imported.');
             } else {
                 $this->warn('No group was found on Active Directory server.');
             }
         }
     } catch (RestException $e) {
         $this->error($e->getMessage());
         if ($this->option('verbose')) {
             $this->error(print_r($e->getContext(), true));
         }
     } catch (\Exception $e) {
         $this->error($e->getMessage());
     }
 }
Пример #19
0
 public function getApiDocInfo()
 {
     $path = '/' . $this->getServiceName() . '/' . $this->getFullPathName();
     $eventPath = $this->getServiceName() . '.' . $this->getFullPathName('.');
     $name = Inflector::camelize($this->name);
     $plural = Inflector::pluralize($name);
     $words = str_replace('_', ' ', $this->name);
     $pluralWords = Inflector::pluralize($words);
     $wrapper = ResourcesWrapper::getWrapper();
     $apis = [['path' => $path, 'description' => "Operations for {$words} administration.", 'operations' => [['method' => 'GET', 'summary' => 'get' . $plural . '() - Retrieve one or more ' . $pluralWords . '.', 'nickname' => 'get' . $plural, 'type' => $plural . 'Response', 'event_name' => [$eventPath . '.list'], 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::FILTER), ApiOptions::documentOption(ApiOptions::LIMIT), ApiOptions::documentOption(ApiOptions::ORDER), ApiOptions::documentOption(ApiOptions::GROUP), ApiOptions::documentOption(ApiOptions::OFFSET), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED), ApiOptions::documentOption(ApiOptions::INCLUDE_COUNT), ApiOptions::documentOption(ApiOptions::INCLUDE_SCHEMA), ApiOptions::documentOption(ApiOptions::FILE)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Use the \'ids\' or \'filter\' parameter to limit records that are returned. ' . 'By default, all records up to the maximum are returned. <br>' . 'Use the \'fields\' and \'related\' parameters to limit properties returned for each record. ' . 'By default, all fields and no relations are returned for each record. <br>' . 'Alternatively, to retrieve by record, a large list of ids, or a complicated filter, ' . 'use the POST request with X-HTTP-METHOD = GET header and post records or ids.'], ['method' => 'POST', 'summary' => 'create' . $plural . '() - Create one or more ' . $pluralWords . '.', 'nickname' => 'create' . $plural, 'type' => $plural . 'Response', 'event_name' => $eventPath . '.create', 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [['name' => 'body', 'description' => 'Data containing name-value pairs of records to create.', 'allowMultiple' => false, 'type' => $plural . 'Request', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED), ['name' => 'X-HTTP-METHOD', 'description' => 'Override request using POST to tunnel other http request, such as DELETE.', 'enum' => ['GET', 'PUT', 'PATCH', 'DELETE'], 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'header', 'required' => false]], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Post data should be a single record or an array of records (shown). ' . 'By default, only the id property of the record affected is returned on success, ' . 'use \'fields\' and \'related\' to return more info.'], ['method' => 'PATCH', 'summary' => 'update' . $plural . '() - Update one or more ' . $pluralWords . '.', 'nickname' => 'update' . $plural, 'type' => $plural . 'Response', 'event_name' => $eventPath . '.update', 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [['name' => 'body', 'description' => 'Data containing name-value pairs of records to update.', 'allowMultiple' => false, 'type' => $plural . 'Request', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Post data should be a single record or an array of records (shown). ' . 'By default, only the id property of the record is returned on success, ' . 'use \'fields\' and \'related\' to return more info.'], ['method' => 'DELETE', 'summary' => 'delete' . $plural . '() - Delete one or more ' . $pluralWords . '.', 'nickname' => 'delete' . $plural, 'type' => $plural . 'Response', 'event_name' => $eventPath . '.delete', 'parameters' => [['name' => 'force', 'description' => 'Set force to true to delete all records in this table, otherwise \'ids\' parameter is required.', 'allowMultiple' => false, 'type' => 'boolean', 'paramType' => 'query', 'required' => false, 'default' => false], ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'By default, only the id property of the record deleted is returned on success. ' . 'Use \'fields\' and \'related\' to return more properties of the deleted records. <br>' . 'Alternatively, to delete by record or a large list of ids, ' . 'use the POST request with X-HTTP-METHOD = DELETE header and post records or ids.']]], ['path' => $path . '/{id}', 'operations' => [['method' => 'GET', 'summary' => 'get' . $name . '() - Retrieve one ' . $words . '.', 'nickname' => 'get' . $name, 'type' => $name . 'Response', 'event_name' => $eventPath . '.read', 'parameters' => [['name' => 'id', 'description' => 'Identifier of the record to retrieve.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Use the \'fields\' and/or \'related\' parameter to limit properties that are returned. By default, all fields and no relations are returned.'], ['method' => 'PATCH', 'summary' => 'update' . $name . '() - Update one ' . $words . '.', 'nickname' => 'update' . $name, 'type' => $name . 'Response', 'event_name' => $eventPath . '.update', 'parameters' => [['name' => 'id', 'description' => 'Identifier of the record to update.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ['name' => 'body', 'description' => 'Data containing name-value pairs of fields to update.', 'allowMultiple' => false, 'type' => $name . 'Request', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Post data should be an array of fields to update for a single record. <br>' . 'By default, only the id is returned. Use the \'fields\' and/or \'related\' parameter to return more properties.'], ['method' => 'DELETE', 'summary' => 'delete' . $name . '() - Delete one ' . $words . '.', 'nickname' => 'delete' . $name, 'type' => $name . 'Response', 'event_name' => $eventPath . '.delete', 'parameters' => [['name' => 'id', 'description' => 'Identifier of the record to delete.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'By default, only the id is returned. Use the \'fields\' and/or \'related\' parameter to return deleted properties.']], 'description' => "Operations for individual {$words} administration."]];
     $models = [$plural . 'Request' => ['id' => $plural . 'Request', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => $name . 'Request']], ApiOptions::IDS => ['type' => 'array', 'description' => 'Array of system record identifiers, used for batch GET, PUT, PATCH, and DELETE.', 'items' => ['type' => 'integer', 'format' => 'int32']]]], $plural . 'Response' => ['id' => $plural . 'Response', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => $name . 'Response']], 'meta' => ['type' => 'Metadata', 'description' => 'Array of metadata returned for GET requests.']]], 'Metadata' => ['id' => 'Metadata', 'properties' => ['schema' => ['type' => 'array', 'description' => 'Array of table schema.', 'items' => ['type' => 'string']], 'count' => ['type' => 'integer', 'format' => 'int32', 'description' => 'Record count returned for GET requests.']]]];
     $model = $this->getModel();
     if ($model) {
         $temp = $model->toApiDocsModel($name);
         if ($temp) {
             $models = array_merge($models, $temp);
         }
     }
     return ['apis' => $apis, 'models' => $models];
 }
Пример #20
0
 public function getApiDocInfo()
 {
     $path = '/' . $this->getServiceName() . '/' . $this->getFullPathName();
     $eventPath = $this->getServiceName() . '.' . $this->getFullPathName('.');
     $name = Inflector::camelize($this->name);
     $plural = Inflector::pluralize($name);
     $words = str_replace('_', ' ', $this->name);
     $pluralWords = Inflector::pluralize($words);
     $wrapper = ResourcesWrapper::getWrapper();
     $apis = [['path' => $path, 'description' => "Operations for retrieving system environment.", 'operations' => [['method' => 'GET', 'summary' => 'getEnvironment() - Retrieve system environment.', 'nickname' => 'getEnvironment', 'type' => 'EnvironmentResponse', 'event_name' => $eventPath . '.list', 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [], 'responseMessages' => [], 'notes' => 'Minimum environment information given without a valid user session.' . ' More information given based on user privileges.']]]];
     $models = ['EnvironmentResponse' => ['id' => 'EnvironmentResponse', 'properties' => ['platform' => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => $name . 'Response']], 'authentication' => ['type' => 'Metadata', 'description' => 'Array of metadata returned for GET requests.'], 'app_group' => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => $name . 'Response']], 'no_app_group' => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => $name . 'Response']], 'config' => ['type' => 'Metadata', 'description' => 'Array of metadata returned for GET requests.'], 'server' => ['type' => 'Metadata', 'description' => 'Array of metadata returned for GET requests.']]]];
     return ['apis' => $apis, 'models' => $models];
 }
Пример #21
0
 /**
  * Handles DELETE actions.
  *
  * @return \DreamFactory\Core\Utility\ServiceResponse
  * @throws BadRequestException
  */
 protected function handleDELETE()
 {
     $force = $this->request->getParameterAsBool('force', false);
     if (empty($this->folderPath)) {
         // delete just folders and files from the container
         if (!empty($content = ResourcesWrapper::unwrapResources($this->request->getPayloadData()))) {
             $result = $this->deleteFolderContent($content, '', $force);
         } else {
             throw new BadRequestException('No resources given for delete.');
         }
     } else {
         if (empty($this->filePath)) {
             // delete directory of files and the directory itself
             // multi-file or folder delete via post data
             if (!empty($content = ResourcesWrapper::unwrapResources($this->request->getPayloadData()))) {
                 $result = $this->deleteFolderContent($content, $this->folderPath, $force);
             } else {
                 $this->driver->deleteFolder($this->container, $this->folderPath, $force);
                 $result = ['name' => basename($this->folderPath), 'path' => $this->folderPath];
             }
         } else {
             // delete file from permanent storage
             $this->driver->deleteFile($this->container, $this->filePath);
             $result = ['name' => basename($this->filePath), 'path' => $this->filePath];
         }
     }
     return ResourcesWrapper::cleanResources($result);
 }
Пример #22
0
 public function getApiDocInfo()
 {
     //        $alwaysWrap = \Config::get('df.always_wrap_resources', false);
     $wrapper = ResourcesWrapper::getWrapper();
     $apis = [['path' => '/' . $this->name, 'operations' => [['method' => 'GET', 'summary' => 'getEventSubscribers() - Retrieve one or more subscribers.', 'nickname' => 'getEventSubscribers', 'type' => 'SubscribersResponse', 'event_name' => $this->name . '.subscriber.list', 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::FILTER), ApiOptions::documentOption(ApiOptions::LIMIT), ApiOptions::documentOption(ApiOptions::ORDER), ApiOptions::documentOption(ApiOptions::GROUP), ApiOptions::documentOption(ApiOptions::OFFSET), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED), ApiOptions::documentOption(ApiOptions::INCLUDE_COUNT), ApiOptions::documentOption(ApiOptions::INCLUDE_SCHEMA), ApiOptions::documentOption(ApiOptions::FILE)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Use the \'ids\' or \'filter\' parameter to limit records that are returned. ' . 'By default, all records up to the maximum are returned. <br>' . 'Use the \'fields\' and \'related\' parameters to limit properties returned for each record. ' . 'By default, all fields and no relations are returned for each record. <br>' . 'Alternatively, to retrieve by record, a large list of ids, or a complicated filter, ' . 'use the POST request with X-HTTP-METHOD = GET header and post records or ids.'], ['method' => 'POST', 'summary' => 'createEventSubscribers() - Create one or more subscribers.', 'nickname' => 'createEventSubscribers', 'type' => 'SubscribersResponse', 'event_name' => $this->name . '.subscriber.create', 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [['name' => 'body', 'description' => 'Data containing name-value pairs of records to create.', 'allowMultiple' => false, 'type' => 'UsersRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED), ['name' => 'X-HTTP-METHOD', 'description' => 'Override request using POST to tunnel other http request, such as DELETE.', 'enum' => ['GET', 'PUT', 'PATCH', 'DELETE'], 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'header', 'required' => false]], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Post data should be a single record or an array of records (shown). ' . 'By default, only the id property of the record affected is returned on success, ' . 'use \'fields\' and \'related\' to return more info.'], ['method' => 'PATCH', 'summary' => 'updateEventSubscribers() - Update one or more subscribers.', 'nickname' => 'updateEventSubscribers', 'type' => 'SubscribersResponse', 'event_name' => $this->name . '.subscriber.update', 'consumes' => ['application/json', 'application/xml', 'text/csv'], 'produces' => ['application/json', 'application/xml', 'text/csv'], 'parameters' => [['name' => 'body', 'description' => 'Data containing name-value pairs of records to update.', 'allowMultiple' => false, 'type' => 'UsersRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Post data should be a single record or an array of records (shown). ' . 'By default, only the id property of the record is returned on success, ' . 'use \'fields\' and \'related\' to return more info.'], ['method' => 'DELETE', 'summary' => 'deleteEventSubscribers() - Delete one or more subscribers.', 'nickname' => 'deleteEventSubscribers', 'type' => 'SubscribersResponse', 'event_name' => $this->name . '.subscriber.delete', 'parameters' => [ApiOptions::documentOption(ApiOptions::IDS), ApiOptions::documentOption(ApiOptions::FORCE), ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'By default, only the id property of the record deleted is returned on success. ' . 'Use \'fields\' and \'related\' to return more properties of the deleted records. <br>' . 'Alternatively, to delete by record or a large list of ids, ' . 'use the POST request with X-HTTP-METHOD = DELETE header and post records or ids.']], 'description' => 'Operations for user administration.'], ['path' => '/' . $this->name . '/{id}', 'operations' => [['method' => 'GET', 'summary' => 'getEventSubscriber() - Retrieve one subscriber.', 'nickname' => 'getEventSubscriber', 'type' => 'Subscriber', 'event_name' => $this->name . '.subscriber.read', 'parameters' => [['name' => 'id', 'description' => 'Identifier of the record to retrieve.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Use the \'fields\' and/or \'related\' parameter to limit properties that are returned. By default, all fields and no relations are returned.'], ['method' => 'PATCH', 'summary' => 'updateEventSubscriber() - Update one subscriber.', 'nickname' => 'updateEventSubscriber', 'type' => 'Subscriber', 'event_name' => $this->name . '.subscriber.update', 'parameters' => [['name' => 'id', 'description' => 'Identifier of the record to update.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ['name' => 'body', 'description' => 'Data containing name-value pairs of fields to update.', 'allowMultiple' => false, 'type' => 'UserRequest', 'paramType' => 'body', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'Post data should be an array of fields to update for a single record. <br>' . 'By default, only the id is returned. Use the \'fields\' and/or \'related\' parameter to return more properties.'], ['method' => 'DELETE', 'summary' => 'deleteEventSubscriber() - Delete one subscriber.', 'nickname' => 'deleteEventSubscriber', 'type' => 'Subscriber', 'event_name' => $this->name . '.subscriber.delete', 'parameters' => [['name' => 'id', 'description' => 'Identifier of the record to delete.', 'allowMultiple' => false, 'type' => 'string', 'paramType' => 'path', 'required' => true], ApiOptions::documentOption(ApiOptions::FIELDS), ApiOptions::documentOption(ApiOptions::RELATED)], 'responseMessages' => ApiDocUtilities::getCommonResponses([400, 401, 500]), 'notes' => 'By default, only the id is returned. Use the \'fields\' and/or \'related\' parameter to return deleted properties.']], 'description' => 'Operations for individual user administration.']];
     $models = ['SubscribersRequest' => ['id' => 'SubscribersRequest', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => 'Subscriber']], ApiOptions::IDS => ['type' => 'array', 'description' => 'Array of system record identifiers, used for batch GET, PUT, PATCH, and DELETE.', 'items' => ['type' => 'integer', 'format' => 'int32']]]], 'SubscribersResponse' => ['id' => 'SubscribersResponse', 'properties' => [$wrapper => ['type' => 'array', 'description' => 'Array of system records.', 'items' => ['$ref' => 'Subscriber']], 'meta' => ['type' => 'Metadata', 'description' => 'Array of metadata returned for GET requests.']]]];
     return ['apis' => $apis, 'models' => $models];
 }
Пример #23
0
 /**
  *
  * @return array
  */
 public static function listServices()
 {
     return ResourcesWrapper::wrapResources(Service::available());
 }