From a093fc5a01c3f4eb3853d0f17812c552100d7dfa Mon Sep 17 00:00:00 2001 From: Sebastian Marcet Date: Wed, 9 Sep 2015 18:14:28 -0300 Subject: [PATCH] Summit Application API WIP - Added Summit API Change-Id: I5494db9414809a3ca5e278919d084e895b2ed05a --- .env.example | 8 +- .env.testing | 6 +- .gitignore | 6 +- app/Events/MyScheduleAdd.php | 45 + app/Events/MyScheduleRemove.php | 12 + app/Exceptions/Handler.php | 64 +- app/Http/Controllers/JsonController.php | 187 +- .../Controllers/OAuth2ProtectedController.php | 59 +- .../summit/CheckAttendeeStrategyFactory.php | 51 + .../summit/CheckSpeakerStrategyFactory.php | 47 + .../summit/ICheckAttendeeStrategy.php | 32 + .../summit/ICheckSpeakerStrategy.php | 32 + .../summit/ISummitFinderStrategy.php | 30 + .../summit/OAuth2SummitApiController.php | 1518 +++++++++++++++++ .../summit/SummitFinderStrategyFactory.php | 33 + .../strategies/CheckMeAttendeeStrategy.php | 60 + .../strategies/CheckMeSpeakerStrategy.php | 60 + .../strategies/CheckMyOwnAttendeeStrategy.php | 43 + .../CurrentSummitFinderStrategy.php | 46 + .../HTTP401UnauthorizedException.php | 18 + app/Http/Kernel.php | 57 +- app/Http/Middleware/CacheMiddleware.php | 118 ++ app/Http/Middleware/ETagsMiddleware.php | 77 +- ...Auth2BearerAccessTokenRequestValidator.php | 501 +++--- app/Http/Middleware/RateLimitMiddleware.php | 169 +- .../SecurityHTTPHeadersWriterMiddleware.php | 2 +- app/Http/Utils/AbstractFilterElement.php | 36 + app/Http/Utils/Filter.php | 183 ++ app/Http/Utils/FilterElement.php | 106 ++ app/Http/Utils/FilterParser.php | 115 ++ app/Http/Utils/Order.php | 66 + app/Http/Utils/OrderElement.php | 74 + app/Http/Utils/OrderParser.php | 57 + app/Http/Utils/PagingInfo.php | 59 + app/Http/Utils/PagingResponse.php | 105 ++ app/Http/routes.php | 128 +- app/Libs/oauth2/OAuth2Protocol.php | 163 +- .../OAuth2WWWAuthenticateErrorResponse.php | 114 +- app/Libs/utils/DateTimeUtils.php | 33 + app/Libs/utils/ITransactionService.php | 34 + app/Libs/utils/JsonUtils.php | 75 + app/Models/Marketplace/CompanyService.php | 38 - app/Models/Marketplace/Consultant.php | 28 - .../Marketplace/ICompanyServiceRepository.php | 45 - app/Models/Marketplace/PublicCloudService.php | 30 - .../ResourceServer/AccessTokenService.php | 154 -- .../ResourceServer/IAccessTokenService.php | 30 - app/Models/ResourceServer/IApiEndpoint.php | 91 - app/Models/Utils/BaseModelEloquent.php | 251 ++- app/Models/Utils/EloquentBaseRepository.php | 62 + app/Models/Utils/IBaseRepository.php | 47 +- app/Models/Utils/SilverstripeBaseModel.php | 53 + .../exceptions/EntityNotFoundException.php | 19 + app/Models/exceptions/ValidationException.php | 26 + app/Models/main/Company.php | 27 + app/Models/main/File.php | 48 + app/Models/main/Image.php | 26 + app/Models/main/Member.php | 38 + app/Models/main/Tag.php | 33 + app/Models/marketplace/CompanyService.php | 39 + app/Models/marketplace/Consultant.php | 29 + .../DataCenterLocation.php | 0 .../DataCenterRegion.php | 0 .../ICloudService.php | 0 .../ICloudServiceRepository.php | 0 .../marketplace/ICompanyServiceRepository.php | 47 + .../IConsultant.php | 0 .../IConsultantRepository.php | 0 .../IPrivateCloudServiceRepository.php | 0 .../IPublicCloudServiceRepository.php | 0 .../{Marketplace => marketplace}/Office.php | 0 .../PrivateCloudService.php | 0 app/Models/marketplace/PublicCloudService.php | 32 + app/Models/oauth2/AccessToken.php | 221 +-- app/Models/oauth2/IResourceServerContext.php | 103 +- app/Models/oauth2/ResourceServerContext.php | 143 +- app/Models/oauth2/Token.php | 141 +- .../resource_server/AccessTokenService.php | 199 +++ .../Api.php | 0 .../ApiEndpoint.php | 9 + .../ApiScope.php | 0 .../resource_server/IAccessTokenService.php | 31 + .../IApi.php | 0 app/Models/resource_server/IApiEndpoint.php | 93 + .../IApiEndpointRepository.php | 0 .../IApiScope.php | 0 app/Models/summit/ISpeakerRepository.php | 35 + app/Models/summit/ISummitEventRepository.php | 30 + app/Models/summit/ISummitRepository.php | 23 + app/Models/summit/Presentation.php | 137 ++ app/Models/summit/PresentationCategory.php | 57 + .../summit/PresentationCategoryGroup.php | 67 + app/Models/summit/PresentationMaterial.php | 41 + app/Models/summit/PresentationSlide.php | 59 + app/Models/summit/PresentationSpeaker.php | 99 ++ app/Models/summit/PresentationVideo.php | 38 + app/Models/summit/Summit.php | 490 ++++++ app/Models/summit/SummitAbstractLocation.php | 49 + app/Models/summit/SummitAirport.php | 21 + app/Models/summit/SummitAttendee.php | 190 +++ app/Models/summit/SummitAttendeeTicket.php | 61 + app/Models/summit/SummitEntityEvent.php | 36 + app/Models/summit/SummitEvent.php | 455 +++++ app/Models/summit/SummitEventFactory.php | 32 + app/Models/summit/SummitEventFeedback.php | 92 + app/Models/summit/SummitEventType.php | 47 + app/Models/summit/SummitExternalLocation.php | 23 + .../summit/SummitGeoLocatedLocation.php | 67 + app/Models/summit/SummitHotel.php | 24 + app/Models/summit/SummitLocationMap.php | 59 + app/Models/summit/SummitTicketType.php | 62 + app/Models/summit/SummitType.php | 47 + app/Models/summit/SummitVenue.php | 56 + app/Models/summit/SummitVenueRoom.php | 34 + app/Providers/AppServiceProvider.php | 119 +- app/Providers/EventServiceProvider.php | 130 +- app/Providers/RouteServiceProvider.php | 4 +- app/Repositories/RepositoriesProvider.php | 94 +- .../EloquentCompanyServiceRepository.php | 148 +- .../EloquentConsultantRepository.php | 43 +- .../EloquentPrivateCloudServiceRepository.php | 47 +- .../EloquentPublicCloudServiceRepository.php | 47 +- .../EloquentApiEndpointRepository.php | 102 +- .../summit/EloquentSpeakerRepository.php | 120 ++ .../summit/EloquentSummitEventRepository.php | 52 + .../summit/EloquentSummitRepository.php | 42 + app/Services/ServicesProvider.php | 51 +- app/Services/model/ISummitService.php | 100 ++ app/Services/model/SummitService.php | 864 ++++++++++ .../utils/EloquentTransactionService.php | 39 + config/app.php | 2 +- config/server.php | 23 + database/seeds/ApiEndpointsSeeder.php | 649 +++++-- database/seeds/ApiScopesSeeder.php | 187 +- database/seeds/ApiSeeder.php | 97 +- database/seeds/DatabaseSeeder.php | 28 +- database/seeds/TestSeeder.php | 44 +- tests/FilterParserTest.php | 27 + tests/OAuth2PublicCloudApiTest.php | 182 +- tests/OAuth2SummitApiTest.php | 849 +++++++++ tests/ProtectedApiTest.php | 145 +- 141 files changed, 11173 insertions(+), 2255 deletions(-) create mode 100644 app/Events/MyScheduleAdd.php create mode 100644 app/Events/MyScheduleRemove.php create mode 100644 app/Http/Controllers/apis/protected/summit/CheckAttendeeStrategyFactory.php create mode 100644 app/Http/Controllers/apis/protected/summit/CheckSpeakerStrategyFactory.php create mode 100644 app/Http/Controllers/apis/protected/summit/ICheckAttendeeStrategy.php create mode 100644 app/Http/Controllers/apis/protected/summit/ICheckSpeakerStrategy.php create mode 100644 app/Http/Controllers/apis/protected/summit/ISummitFinderStrategy.php create mode 100644 app/Http/Controllers/apis/protected/summit/OAuth2SummitApiController.php create mode 100644 app/Http/Controllers/apis/protected/summit/SummitFinderStrategyFactory.php create mode 100644 app/Http/Controllers/apis/protected/summit/strategies/CheckMeAttendeeStrategy.php create mode 100644 app/Http/Controllers/apis/protected/summit/strategies/CheckMeSpeakerStrategy.php create mode 100644 app/Http/Controllers/apis/protected/summit/strategies/CheckMyOwnAttendeeStrategy.php create mode 100644 app/Http/Controllers/apis/protected/summit/strategies/CurrentSummitFinderStrategy.php create mode 100644 app/Http/Exceptions/HTTP401UnauthorizedException.php create mode 100644 app/Http/Middleware/CacheMiddleware.php create mode 100644 app/Http/Utils/AbstractFilterElement.php create mode 100644 app/Http/Utils/Filter.php create mode 100644 app/Http/Utils/FilterElement.php create mode 100644 app/Http/Utils/FilterParser.php create mode 100644 app/Http/Utils/Order.php create mode 100644 app/Http/Utils/OrderElement.php create mode 100644 app/Http/Utils/OrderParser.php create mode 100644 app/Http/Utils/PagingInfo.php create mode 100644 app/Http/Utils/PagingResponse.php create mode 100644 app/Libs/utils/DateTimeUtils.php create mode 100644 app/Libs/utils/ITransactionService.php create mode 100644 app/Libs/utils/JsonUtils.php delete mode 100644 app/Models/Marketplace/CompanyService.php delete mode 100644 app/Models/Marketplace/Consultant.php delete mode 100644 app/Models/Marketplace/ICompanyServiceRepository.php delete mode 100644 app/Models/Marketplace/PublicCloudService.php delete mode 100644 app/Models/ResourceServer/AccessTokenService.php delete mode 100644 app/Models/ResourceServer/IAccessTokenService.php delete mode 100644 app/Models/ResourceServer/IApiEndpoint.php create mode 100644 app/Models/Utils/EloquentBaseRepository.php create mode 100644 app/Models/Utils/SilverstripeBaseModel.php create mode 100644 app/Models/exceptions/EntityNotFoundException.php create mode 100644 app/Models/exceptions/ValidationException.php create mode 100644 app/Models/main/Company.php create mode 100644 app/Models/main/File.php create mode 100644 app/Models/main/Image.php create mode 100644 app/Models/main/Member.php create mode 100644 app/Models/main/Tag.php create mode 100644 app/Models/marketplace/CompanyService.php create mode 100644 app/Models/marketplace/Consultant.php rename app/Models/{Marketplace => marketplace}/DataCenterLocation.php (100%) rename app/Models/{Marketplace => marketplace}/DataCenterRegion.php (100%) rename app/Models/{Marketplace => marketplace}/ICloudService.php (100%) rename app/Models/{Marketplace => marketplace}/ICloudServiceRepository.php (100%) create mode 100644 app/Models/marketplace/ICompanyServiceRepository.php rename app/Models/{Marketplace => marketplace}/IConsultant.php (100%) rename app/Models/{Marketplace => marketplace}/IConsultantRepository.php (100%) rename app/Models/{Marketplace => marketplace}/IPrivateCloudServiceRepository.php (100%) rename app/Models/{Marketplace => marketplace}/IPublicCloudServiceRepository.php (100%) rename app/Models/{Marketplace => marketplace}/Office.php (100%) rename app/Models/{Marketplace => marketplace}/PrivateCloudService.php (100%) create mode 100644 app/Models/marketplace/PublicCloudService.php create mode 100644 app/Models/resource_server/AccessTokenService.php rename app/Models/{ResourceServer => resource_server}/Api.php (100%) rename app/Models/{ResourceServer => resource_server}/ApiEndpoint.php (96%) rename app/Models/{ResourceServer => resource_server}/ApiScope.php (100%) create mode 100644 app/Models/resource_server/IAccessTokenService.php rename app/Models/{ResourceServer => resource_server}/IApi.php (100%) create mode 100644 app/Models/resource_server/IApiEndpoint.php rename app/Models/{ResourceServer => resource_server}/IApiEndpointRepository.php (100%) rename app/Models/{ResourceServer => resource_server}/IApiScope.php (100%) create mode 100644 app/Models/summit/ISpeakerRepository.php create mode 100644 app/Models/summit/ISummitEventRepository.php create mode 100644 app/Models/summit/ISummitRepository.php create mode 100644 app/Models/summit/Presentation.php create mode 100644 app/Models/summit/PresentationCategory.php create mode 100644 app/Models/summit/PresentationCategoryGroup.php create mode 100644 app/Models/summit/PresentationMaterial.php create mode 100644 app/Models/summit/PresentationSlide.php create mode 100644 app/Models/summit/PresentationSpeaker.php create mode 100644 app/Models/summit/PresentationVideo.php create mode 100644 app/Models/summit/Summit.php create mode 100644 app/Models/summit/SummitAbstractLocation.php create mode 100644 app/Models/summit/SummitAirport.php create mode 100644 app/Models/summit/SummitAttendee.php create mode 100644 app/Models/summit/SummitAttendeeTicket.php create mode 100644 app/Models/summit/SummitEntityEvent.php create mode 100644 app/Models/summit/SummitEvent.php create mode 100644 app/Models/summit/SummitEventFactory.php create mode 100644 app/Models/summit/SummitEventFeedback.php create mode 100644 app/Models/summit/SummitEventType.php create mode 100644 app/Models/summit/SummitExternalLocation.php create mode 100644 app/Models/summit/SummitGeoLocatedLocation.php create mode 100644 app/Models/summit/SummitHotel.php create mode 100644 app/Models/summit/SummitLocationMap.php create mode 100644 app/Models/summit/SummitTicketType.php create mode 100644 app/Models/summit/SummitType.php create mode 100644 app/Models/summit/SummitVenue.php create mode 100644 app/Models/summit/SummitVenueRoom.php create mode 100644 app/Repositories/summit/EloquentSpeakerRepository.php create mode 100644 app/Repositories/summit/EloquentSummitEventRepository.php create mode 100644 app/Repositories/summit/EloquentSummitRepository.php create mode 100644 app/Services/model/ISummitService.php create mode 100644 app/Services/model/SummitService.php create mode 100644 app/Services/utils/EloquentTransactionService.php create mode 100644 config/server.php create mode 100644 tests/FilterParserTest.php create mode 100644 tests/OAuth2SummitApiTest.php diff --git a/.env.example b/.env.example index dc5cd0e1..5bb339eb 100644 --- a/.env.example +++ b/.env.example @@ -43,4 +43,10 @@ CORS_EXPOSED_HEADERS= CURL_TIMEOUT=60 CURL_ALLOWS_REDIRECT=false -CURL_VERIFY_SSL_CERT=true \ No newline at end of file +CURL_VERIFY_SSL_CERT=true + +SSL_ENABLED=false +OAUTH2_ENABLED=true +DB_LOG_ENABLED=false +ASSETS_BASE_URL=http://www.openstack.org +API_RESPONSE_CACHE_LIFETIME=10000 \ No newline at end of file diff --git a/.env.testing b/.env.testing index 0119b429..ecb26bce 100644 --- a/.env.testing +++ b/.env.testing @@ -12,7 +12,7 @@ DB_USERNAME=root DB_PASSWORD=Koguryo@1981 SS_DB_HOST=localhost -SS_DATABASE=os_local +SS_DATABASE=os_production2 SS_DB_USERNAME=root SS_DB_PASSWORD=Koguryo@1981 @@ -47,4 +47,6 @@ CORS_EXPOSED_HEADERS= CURL_TIMEOUT=3600 CURL_ALLOWS_REDIRECT=false -CURL_VERIFY_SSL_CERT=false \ No newline at end of file +CURL_VERIFY_SSL_CERT=false +DB_LOG_ENABLED=true +ASSETS_BASE_URL=http://www.openstack.org/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index f352365b..56caf5ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /vendor /node_modules -.env composer.phar composer.lock .DS_Storeapp/storage @@ -23,6 +22,5 @@ ChangeLog doc/build *.egg *.egg-info - - -.env.testing \ No newline at end of file +.env.testing +.env \ No newline at end of file diff --git a/app/Events/MyScheduleAdd.php b/app/Events/MyScheduleAdd.php new file mode 100644 index 00000000..cac5dc78 --- /dev/null +++ b/app/Events/MyScheduleAdd.php @@ -0,0 +1,45 @@ +attendee = $attendee; + $this->event_id = $event_id; + } + + /** + * @return SummitAttendee + */ + public function getAttendee(){ return $this->attendee;} + + /** + * @return int + */ + public function getEventId(){ return $this->event_id;} +} \ No newline at end of file diff --git a/app/Events/MyScheduleRemove.php b/app/Events/MyScheduleRemove.php new file mode 100644 index 00000000..03b5710b --- /dev/null +++ b/app/Events/MyScheduleRemove.php @@ -0,0 +1,12 @@ +view('errors.404', [], 404); + } } diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 8a328614..38973ddd 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -1,99 +1,124 @@ 'server error'), 500); - } + protected function error500(Exception $ex) + { + Log::error($ex); - protected function created($data = 'ok') - { - $res = Response::json($data, 201); - //jsonp - if (Input::has('callback')) - { - $res->setCallback(Input::get('callback')); - } - return $res; - } + return Response::json(array('message' => 'server error'), 500); + } - protected function deleted($data = 'ok') - { - $res = Response::json($data, 204); - //jsonp - if (Input::has('callback')) - { - $res->setCallback(Input::get('callback')); - } - return $res; - } + protected function created($data = 'ok') + { + $res = Response::json($data, 201); + //jsonp + if (Input::has('callback')) { + $res->setCallback(Input::get('callback')); + } - protected function ok($data = 'ok') - { - $res = Response::json($data, 200); - //jsonp - if (Input::has('callback')) - { - $res->setCallback(Input::get('callback')); - } - return $res; - } + return $res; + } - protected function error400($data) - { - return Response::json($data, 400); - } + protected function deleted($data = 'ok') + { + $res = Response::json($data, 204); + //jsonp + if (Input::has('callback')) { + $res->setCallback(Input::get('callback')); + } - protected function error404($data = array('message' => 'Entity Not Found')) - { - return Response::json($data, 404); - } + return $res; + } - /** - * { - "message": "Validation Failed", - "errors": [ - { - "resource": "Issue", - "field": "title", - "code": "missing_field" - } - ] - } - * @param $messages - * @return mixed - */ - protected function error412($messages) - { - return Response::json(array('message' => 'Validation Failed', 'errors' => $messages), 412); - } + protected function updated($data = 'ok') + { + $res = Response::json($data, 204); + //jsonp + if (Input::has('callback')) { + $res->setCallback(Input::get('callback')); + } + + return $res; + } + + + protected function ok($data = 'ok') + { + $res = Response::json($data, 200); + //jsonp + if (Input::has('callback')) { + $res->setCallback(Input::get('callback')); + } + + return $res; + } + + protected function error400($data) + { + return Response::json($data, 400); + } + + protected function error404($data = array('message' => 'Entity Not Found')) + { + return Response::json($data, 404); + } + + protected function error403($data = array('message' => 'Forbidden')) + { + return Response::json($data, 403); + } + + protected function error401($data = array('message' => 'You don\'t have access to this item through the API.')) + { + return Response::json($data, 401); + } + + /** + * { + * "message": "Validation Failed", + * "errors": [ + * { + * "resource": "Issue", + * "field": "title", + * "code": "missing_field" + * } + * ] + * } + * @param $messages + * @return mixed + */ + protected function error412($messages) + { + return Response::json(array('message' => 'Validation Failed', 'errors' => $messages), 412); + } } \ No newline at end of file diff --git a/app/Http/Controllers/OAuth2ProtectedController.php b/app/Http/Controllers/OAuth2ProtectedController.php index 190a6fb4..a5225ba9 100644 --- a/app/Http/Controllers/OAuth2ProtectedController.php +++ b/app/Http/Controllers/OAuth2ProtectedController.php @@ -1,40 +1,45 @@ resource_server_context = $resource_server_context; - } + /** + * @param IResourceServerContext $resource_server_context + */ + public function __construct(IResourceServerContext $resource_server_context) + { + parent::__construct(); + $this->resource_server_context = $resource_server_context; + } } \ No newline at end of file diff --git a/app/Http/Controllers/apis/protected/summit/CheckAttendeeStrategyFactory.php b/app/Http/Controllers/apis/protected/summit/CheckAttendeeStrategyFactory.php new file mode 100644 index 00000000..30f6e6ae --- /dev/null +++ b/app/Http/Controllers/apis/protected/summit/CheckAttendeeStrategyFactory.php @@ -0,0 +1,51 @@ +repository = $summit_repository; + $this->speaker_repository = $speaker_repository; + $this->service = $service; + } + + + + public function getSummits() + { + try { + $summits = $this->repository->getAll(); + return $this->ok($summits); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + /** + * @param $summit_id + * @return mixed + */ + public function getSummit($summit_id) + { + $expand = Request::input('expand', ''); + + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $data = $summit->toArray(); + // summit types + $summit_types = array(); + foreach ($summit->summit_types() as $type) { + array_push($summit_types, $type->toArray()); + } + $data['summit_types'] = $summit_types; + // tickets + $ticket_types = array(); + foreach ($summit->ticket_types() as $ticket) { + array_push($ticket_types, $ticket->toArray()); + } + $data['ticket_types'] = $ticket_types; + //locations + $locations = array(); + foreach ($summit->locations() as $location) { + array_push($locations, $location->toArray()); + } + $data['locations'] = $locations; + + $data['ticket_types'] = $ticket_types; + if (!empty($expand)) { + $expand = explode(',', $expand); + foreach ($expand as $relation) { + switch (trim($relation)) { + case 'attendees': { + $attendees = array(); + list($total, $per_page, $current_page, $last_page, $items) = $summit->attendees(1, + PHP_INT_MAX); + foreach ($items as $attendee) { + array_push($attendees, $attendee->toArray()); + } + $data['attendees'] = $attendees; + } + break; + case 'schedule': { + $event_types = array(); + foreach ($summit->event_types() as $event_type) { + array_push($event_types, $event_type->toArray()); + } + $data['event_types'] = $event_types; + + $sponsors = array(); + foreach ($summit->sponsors() as $company) { + array_push($sponsors, $company->toArray()); + } + $data['sponsors'] = $sponsors; + + $speakers = array(); + $res = $this->speaker_repository->getSpeakersBySummit($summit, new PagingInfo(1 , PHP_INT_MAX)); + + foreach ($res->getItems() as $speaker) { + array_push($speakers, $speaker->toArray()); + } + $data['speakers'] = $speakers; + + $presentation_categories = array(); + foreach ($summit->presentation_categories() as $cat) { + array_push($presentation_categories, $cat->toArray()); + } + $data['tracks'] = $presentation_categories; + + // track_groups + $track_groups = array(); + foreach ($summit->category_groups() as $group) { + array_push($track_groups, $group->toArray()); + } + $data['track_groups'] = $track_groups; + $schedule = array(); + list($total, $per_page, $current_page, $last_page, $items) = $summit->schedule(1, + PHP_INT_MAX); + foreach ($items as $event) { + array_push($schedule, $event->toArray()); + } + $data['schedule'] = $schedule; + + } + break; + } + } + } + $data['timestamp'] = time(); + return $this->ok($data); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * Attendees endpoints + */ + + /** + * @param $summit_id + * @return mixed + */ + public function getAttendees($summit_id) + { + try { + + $values = Input::all(); + + $rules = array + ( + 'page' => 'integer|min:1', + 'per_page' => 'required_with:page|integer|min:5|max:100', + ); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + return $this->error412($messages); + } + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + // default values + $page = 1; + $per_page = 5; + + if (Input::has('page')) { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $filter = null; + if (Input::has('filter')) { + $filter = FilterParser::parse(Input::get('filter'), array + ( + 'first_name' => array('=@', '=='), + 'last_name' => array('=@', '=='), + 'email' => array('=@', '=='), + )); + } + + $order = null; + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), array + ( + 'first_name', + 'last_name', + )); + } + + list($total, $per_page, $current_page, $last_page, $items) = $summit->attendees($page, $per_page, $filter, $order); + + return $this->ok + ( + array + ( + 'total' => $total, + 'per_page' => $per_page, + 'current_page' => $current_page, + 'last_page' => $last_page, + 'data' => $items, + ) + ); + + } + catch (Exception $ex) + { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $attendee_id + * @return mixed + */ + public function getAttendee($summit_id, $attendee_id) + { + $expand = Request::input('expand', ''); + + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = CheckAttendeeStrategyFactory::build(CheckAttendeeStrategyFactory::Own, $this->resource_server_context)->check($attendee_id, $summit); + if(is_null($attendee)) return $this->error404(); + + $data = $attendee->toArray(); + $speaker = $summit->getSpeakerByMemberId(intval($data['member_id'])); + + if (!is_null($speaker)) { + $data['speaker_id'] = intval($speaker->ID); + } + + if (!empty($expand)) { + $expand = explode(',', $expand); + foreach ($expand as $relation) { + switch (trim($relation)) { + case 'schedule': { + unset($data['schedule']); + $schedule = array(); + foreach ($attendee->schedule() as $event) { + $event->setFromAttendee(); + array_push($schedule, $event->toArray()); + } + $data['schedule'] = $schedule; + } + break; + case 'ticket_type': { + unset($data['tickets']); + $tickets = array(); + foreach($attendee->tickets() as $t) + { + array_push($tickets, $t->ticket_type()->toArray()); + } + $data['tickets'] = $tickets; + } + break; + case 'speaker': { + if (!is_null($speaker)) + { + unset($data['speaker_id']); + $data['speaker'] = $speaker->toArray(); + } + } + break; + case 'feedback': { + $feedback = array(); + foreach ($attendee->emitted_feedback() as $f) { + array_push($feedback, $f->toArray()); + } + $data['feedback'] = $feedback; + } + break; + } + } + } + + return $this->ok($data); + } + catch (\HTTP401UnauthorizedException $ex1) { + Log::error($ex1); + return $this->error401(); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $attendee_id + * @return mixed + */ + public function getAttendeeSchedule($summit_id, $attendee_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = CheckAttendeeStrategyFactory::build(CheckAttendeeStrategyFactory::Own, $this->resource_server_context)->check($attendee_id, $summit); + if(is_null($attendee)) return $this->error404(); + + $schedule = array(); + foreach ($attendee->schedule() as $event) { + $event->setFromAttendee(); + array_push($schedule, $event->toArray()); + } + + return $this->ok($schedule); + } + catch (\HTTP401UnauthorizedException $ex1) + { + Log::error($ex1); + return $this->error401(); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $attendee_id + * @param $event_id + * @return mixed + */ + public function addEventToAttendeeSchedule($summit_id, $attendee_id, $event_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = CheckAttendeeStrategyFactory::build(CheckAttendeeStrategyFactory::Own, $this->resource_server_context)->check($attendee_id, $summit); + if (is_null($attendee)) return $this->error404(); + + $res = $this->service->addEventToAttendeeSchedule($summit, $attendee, intval($event_id)); + + return $res ? $this->created() : $this->error400(); + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array( $ex1->getMessage())); + } + catch (EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message' => $ex2->getMessage())); + } + catch(\HTTP401UnauthorizedException $ex3) + { + Log::error($ex3); + return $this->error401(); + } + catch (Exception $ex) + { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $attendee_id + * @param $event_id + * @return mixed + */ + public function removeEventFromAttendeeSchedule($summit_id, $attendee_id, $event_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = CheckAttendeeStrategyFactory::build(CheckAttendeeStrategyFactory::Own, $this->resource_server_context)->check($attendee_id, $summit); + if (is_null($attendee)) return $this->error404(); + + $res = $this->service->removeEventFromAttendeeSchedule($summit, $attendee, intval($event_id)); + + return $res ? $this->deleted() : $this->error400(); + + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array( $ex1->getMessage())); + } + catch (EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message' => $ex2->getMessage())); + } + catch(\HTTP401UnauthorizedException $ex3) + { + Log::error($ex3); + return $this->error401(); + } + catch (Exception $ex) + { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $attendee_id + * @param $event_id + * @return mixed + */ + public function checkingAttendeeOnEvent($summit_id, $attendee_id, $event_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = CheckAttendeeStrategyFactory::build(CheckAttendeeStrategyFactory::Own, $this->resource_server_context)->check($attendee_id, $summit); + if (is_null($attendee)) return $this->error404(); + + $res = $this->service->checkInAttendeeOnEvent($summit, $attendee, intval($event_id)); + + return $res ? $this->updated() : $this->error400(); + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array( $ex1->getMessage())); + } + catch (EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message' => $ex2->getMessage())); + } + catch(\HTTP401UnauthorizedException $ex3) + { + Log::error($ex3); + return $this->error401(); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * Speakers endpoints + */ + + /** + * @param $summit_id + * @return mixed + */ + public function getSpeakers($summit_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $values = Input::all(); + + $rules = array + ( + 'page' => 'integer|min:1', + 'per_page' => 'required_with:page|integer|min:10|max:100', + ); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) + { + $messages = $validation->messages()->toArray(); + + return $this->error412($messages); + } + + // default values + $page = 1; + $per_page = 10; + + if (Input::has('page')) + { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $filter = null; + if (Input::has('filter')) + { + $filter = FilterParser::parse(Input::get('filter'), array + ( + 'first_name' => array('=@', '=='), + 'last_name' => array('=@', '=='), + 'email' => array('=@', '=='), + )); + } + + + $order = null; + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), array + ( + 'first_name', + 'last_name', + )); + } + + $result = $this->speaker_repository->getSpeakersBySummit($summit, new PagingInfo($page, $per_page), $filter, $order); + + return $this->ok + ( + $result->toArray() + ); + } + catch (Exception $ex) + { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $speaker_id + * @return mixed + */ + public function getSpeaker($summit_id, $speaker_id) + { + $expand = Request::input('expand', ''); + + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $speaker = CheckSpeakerStrategyFactory::build(CheckSpeakerStrategyFactory::Me, $this->resource_server_context)->check($speaker_id, $summit); + if (is_null($speaker)) return $this->error404(); + + $data = $speaker->toArray(); + + if (!empty($expand)) { + $expand = explode(',', $expand); + foreach ($expand as $relation) { + switch (trim($relation)) { + case 'presentations': { + $presentations = array(); + unset($data['presentations']); + foreach ($speaker->presentations() as $event) { + $event->setFromSpeaker(); + array_push($presentations, $event->toArray()); + } + $data['presentations'] = $presentations; + } + break; + } + } + } + + return $this->ok($data); + + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * Events endpoints + */ + + /** + * @param $summit_id + * @return mixed + */ + public function getEvents($summit_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $values = Input::all(); + + $rules = array + ( + 'page' => 'integer|min:1', + 'per_page' => 'required_with:page|integer|min:5|max:100', + ); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412($messages); + } + + $expand = Request::input('expand', ''); + + // default values + $page = 1; + $per_page = 5; + + if (Input::has('page')) { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $filter = null; + if (Input::has('filter')) { + $filter = FilterParser::parse(Input::get('filter'), array + ( + 'title' => array('=@', '=='), + 'tags' => array('=@', '=='), + 'start_date' => array('>', '<', '<=', '>=', '=='), + 'end_date' => array('>', '<', '<=', '>=', '=='), + )); + } + + $schedule = array(); + list($total, $per_page, $current_page, $last_page, $items) = $summit->events($page, $per_page, $filter); + + foreach ($items as $event) { + $data = $event->toArray(); + if (!empty($expand)) { + foreach (explode(',', $expand) as $relation) { + switch (trim($relation)) { + case 'feedback': { + $feedback = array(); + list($total, $per_page, $current_page, $last_page, $items) = $event->feedback(1, + PHP_INT_MAX); + foreach ($items as $f) { + array_push($feedback, $f->toArray()); + } + $data['feedback'] = $feedback; + } + break; + } + } + } + array_push($schedule, $data); + } + + return $this->ok + ( + array + ( + 'total' => $total, + 'per_page' => $per_page, + 'current_page' => $current_page, + 'last_page' => $last_page, + 'data' => $schedule, + ) + ); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @return mixed + */ + public function getScheduleEvents($summit_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $values = Input::all(); + + $rules = array + ( + 'page' => 'integer|min:1', + 'per_page' => 'required_with:page|integer|min:5|max:100', + ); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412($messages); + } + + $expand = Request::input('expand', ''); + + // default values + $page = 1; + $per_page = 5; + + if (Input::has('page')) { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $filter = null; + if (Input::has('filter')) { + $filter = FilterParser::parse(Input::get('filter'), array + ( + 'title' => array('=@', '=='), + 'tags' => array('=@', '=='), + 'start_date' => array('>', '<', '<=', '>=', '=='), + 'end_date' => array('>', '<', '<=', '>=', '=='), + )); + } + + $schedule = array(); + list($total, $per_page, $current_page, $last_page, $items) = $summit->schedule($page, $per_page, $filter); + + foreach ($items as $event) { + $data = $event->toArray(); + if (!empty($expand)) { + foreach (explode(',', $expand) as $relation) { + switch (trim($relation)) { + case 'feedback': { + $feedback = array(); + list($total, $per_page, $current_page, $last_page, $items) = $event->feedback(1, + PHP_INT_MAX); + foreach ($items as $f) { + array_push($feedback, $f->toArray()); + } + $data['feedback'] = $feedback; + } + break; + } + } + } + array_push($schedule, $data); + } + + return $this->ok + ( + array + ( + 'total' => $total, + 'per_page' => $per_page, + 'current_page' => $current_page, + 'last_page' => $last_page, + 'data' => $schedule, + ) + ); + } catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + + + /** + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function getEvent($summit_id, $event_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $expand = Request::input('expand', ''); + + $event = $summit->getEvent(intval($event_id)); + + if (is_null($event)) { + return $this->error404(); + } + + $data = $event->toArray(); + + if (!empty($expand)) { + foreach (explode(',', $expand) as $relation) { + switch (trim($relation)) { + case 'feedback': { + $feedback = array(); + list($total, $per_page, $current_page, $last_page, $items) = $event->feedback(1, + PHP_INT_MAX); + foreach ($items as $f) { + array_push($feedback, $f->toArray()); + } + $data['feedback'] = $feedback; + } + break; + case 'speakers':{ + if($event instanceof Presentation){ + unset($data['speakers']); + $speakers = array(); + foreach($event->speakers() as $speaker) + { + array_push($speakers, $speaker->toArray()); + } + $data['speakers'] = $speakers; + } + } + break; + } + } + } + return $this->ok($data); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function getScheduleEvent($summit_id, $event_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $expand = Request::input('expand', ''); + + $event = $summit->getScheduleEvent(intval($event_id)); + + if (is_null($event)) { + return $this->error404(); + } + + $data = $event->toArray(); + + if (!empty($expand)) { + foreach (explode(',', $expand) as $relation) { + switch (trim($relation)) { + case 'feedback': { + $feedback = array(); + list($total, $per_page, $current_page, $last_page, $items) = $event->feedback(1, + PHP_INT_MAX); + foreach ($items as $f) { + array_push($feedback, $f->toArray()); + } + $data['feedback'] = $feedback; + } + break; + case 'speakers':{ + if($event instanceof Presentation){ + unset($data['speakers']); + $speakers = array(); + foreach($event->speakers() as $speaker) + { + array_push($speakers, $speaker->toArray()); + } + $data['speakers'] = $speakers; + } + } + break; + } + } + } + return $this->ok($data); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @return mixed + */ + public function addEvent($summit_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + if(!Request::isJson()) return $this->error403(); + $data = Input::json(); + + $rules = array + ( + 'title' => 'required|string|max:300', + 'description' => 'required|string', + 'location_id' => 'sometimes|required|integer', + 'start_date' => 'sometimes|required|date_format:U', + 'end_date' => 'sometimes|required_with:start_date|date_format:U|after:start_date', + 'allow_feedback' => 'sometimes|required|boolean', + 'type_id' => 'required|integer', + 'summit_types_id' => 'required|int_array', + 'tags' => 'sometimes|required|string_array', + ); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data->all(), $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $event = $this->service->addEvent($summit, $data->all()); + + return $this->created($event); + } + catch (ValidationException $ex1) { + Log::error($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function updateEvent($summit_id, $event_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + if(!Request::isJson()) return $this->error403(); + $data = Input::json(); + + $rules = array + ( + 'title' => 'sometimes|required|string|max:300', + 'description' => 'sometimes|required|string', + 'location_id' => 'sometimes|required|integer', + 'start_date' => 'sometimes|required|date_format:U', + 'end_date' => 'sometimes|required_with:start_date|date_format:U|after:start_date', + 'allow_feedback' => 'sometimes|required|boolean', + 'type_id' => 'sometimes|required|integer', + 'summit_types_id' => 'sometimes|required|int_array', + 'tags' => 'sometimes|required|string_array', + ); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data->all(), $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $event = $this->service->updateEvent($summit, $event_id, $data->all()); + + return $this->ok($event); + + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function publishEvent($summit_id, $event_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + if(!Request::isJson()) return $this->error403(); + $data = Input::json(); + + $rules = array + ( + 'location_id' => 'sometimes|required|integer', + 'start_date' => 'sometimes|required|date_format:U', + 'end_date' => 'sometimes|required_with:start_date|date_format:U|after:start_date', + ); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data->all(), $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $this->service->publishEvent($summit, $event_id, $data->all()); + + return $this->updated(); + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + + /** + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function unPublishEvent($summit_id, $event_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + if(!Request::isJson()) return $this->error403(); + + + $this->service->unPublishEvent($summit, $event_id); + + return $this->deleted(); + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function deleteEvent($summit_id, $event_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $this->service->deleteEvent($summit, $event_id); + + return $this->deleted(); + } + catch (ValidationException $ex1) + { + Log::error($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::error($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + /** + * @param $summit_id + * @param $event_id + * @param $attendee_id + * @return mixed + */ + public function getEventFeedback($summit_id, $event_id, $attendee_id = null) + { + + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $expand = Request::input('expand', ''); + + $values = Input::all(); + + $rules = array + ( + 'page' => 'integer|min:1', + 'per_page' => 'required_with:page|integer|min:5|max:100', + ); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412($messages); + } + + $event = $summit->getScheduleEvent(intval($event_id)); + + if (is_null($event)) { + return $this->error404(); + } + + $filter = null; + if (!is_null($attendee_id)) // add filter by attendee, this case me + { + if($attendee_id !== 'me') return $this->error403(); + $member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($member_id)) return $this->error404(); + + $filter = FilterParser::parse(array('owner_id' => $member_id), array + ( + 'owner_id' => array('=='), + )); + } + + // default values + $page = 1; + $per_page = 5; + + if (Input::has('page')) + { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $order = null; + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), array + ( + 'created_date', + 'owner_id', + 'rate', + 'id', + )); + } + + list($total, $per_page, $current_page, $last_page, $feedback) = $event->feedback($page, $per_page, $filter, $order); + + if (!empty($expand)) + { + foreach (explode(',', $expand) as $relation) + { + switch (trim($relation)) { + case 'owner': + { + $res = array(); + foreach($feedback as $f) + { + array_push($res, $f->toArray(true)); + } + $feedback = $res; + } + break; + } + } + } + + return $this->ok + ( + array + ( + 'total' => $total, + 'per_page' => $per_page, + 'current_page' => $current_page, + 'last_page' => $last_page, + 'data' => $feedback, + ) + ); + + } catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + + /** + * @param LaravelRequest $request + * @param $summit_id + * @param $event_id + * @return mixed + */ + public function addEventFeedback(LaravelRequest $request, $summit_id, $event_id) + { + try { + if (!$request->isJson()) { + return $this->error412(array('invalid content type!')); + } + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + if(!Request::isJson()) return $this->error403(); + + $data = Input::json(); + + $rules = array + ( + 'rate' => 'required|integer|digits_between:0,10', + 'note' => 'required|max:500', + 'attendee_id' => 'required' + ); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data->all(), $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $event = $summit->getScheduleEvent(intval($event_id)); + + if (is_null($event)) { + return $this->error404(); + } + + $data = $data->all(); + $attendee_id = $data['attendee_id']; + + $attendee = CheckAttendeeStrategyFactory::build(CheckAttendeeStrategyFactory::Own, $this->resource_server_context)->check($attendee_id, $summit); + if (is_null($attendee)) return $this->error404(); + + $data['attendee_id'] = intval($attendee->ID); + + $res = $this->service->addEventFeedback + ( + $summit, + $event, + $data + ); + + return !is_null($res) ? $this->created($res->ID) : $this->error400(); + } + catch (EntityNotFoundException $ex1) { + Log::error($ex1); + return $this->error404(); + } + catch(ValidationException $ex2) + { + Log::error($ex2); + return $this->error412(array($ex2->getMessage())); + } + catch(\HTTP401UnauthorizedException $ex3) + { + Log::error($ex3); + return $this->error401(); + } + catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @return mixed + */ + public function getSummitEntityEvents($summit_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $last_event_id = Request::input('last_event_id', null); + $from_date = Request::input('from_date', null); + + $rules = array + ( + 'last_event_id' => 'sometimes|required|integer', + 'from_date' => 'sometimes|required|integer', + ); + + $data = array(); + + if (!is_null($last_event_id)) + { + $data['last_event_id'] = $last_event_id; + } + + if (!is_null($from_date)) + { + $data['from_date'] = $from_date; + } + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data, $rules); + + if ($validation->fails()) + { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + if (!is_null($from_date)) + { + $from_date = new \DateTime("@$from_date"); + } + + list($last_event_id, $last_event_date, $list) = $this->service->getSummitEntityEvents + ( + $summit, + $this->resource_server_context->getCurrentUserExternalId(), + $from_date, + $last_event_id + ); + + return $this->ok + ( + //todo: send this new response once that testing is done! + /*array + ( + 'events' => $list, + 'last_event_id' => $last_event_id, + 'last_event_date' => $last_event_date->getTimestamp() + )*/ + $list + ); + } + catch (Exception $ex) + { + Log::error($ex); + return $this->error500($ex); + } + } + + //venues + + public function getLocations($summit_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + //locations + $locations = array(); + foreach ($summit->locations() as $location) { + array_push($locations, $location->toArray()); + } + + return $this->ok($locations); + } catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @param $location_id + * @return mixed + */ + public function getLocation($summit_id, $location_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $location = $summit->getLocation($location_id); + if (is_null($location)) { + return $this->error404(); + } + return $this->ok($location); + } catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @return mixed + */ + public function getEventTypes($summit_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + //event types + $list = array(); + foreach ($summit->event_types() as $et) { + array_push($list, $et->toArray()); + } + + return $this->ok($list); + } catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @return mixed + */ + public function getSummitTypes($summit_id) + { + try { + $summit = SummitFinderStrategyFactory::build($this->repository)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + //summit types + $list = array(); + foreach ($summit->summit_types() as $st) { + array_push($list, $st->toArray()); + } + return $this->ok($list); + } catch (Exception $ex) { + Log::error($ex); + + return $this->error500($ex); + } + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/apis/protected/summit/SummitFinderStrategyFactory.php b/app/Http/Controllers/apis/protected/summit/SummitFinderStrategyFactory.php new file mode 100644 index 00000000..d2ec19a1 --- /dev/null +++ b/app/Http/Controllers/apis/protected/summit/SummitFinderStrategyFactory.php @@ -0,0 +1,33 @@ +resource_server_context = $resource_server_context; + } + + /** + * @param $attendee_id + * @param Summit $summit + * @return null|SummitAttendee + */ + public function check($attendee_id, Summit $summit) + { + if (strtolower($attendee_id) === 'me') { + $member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($member_id)) { + return null; + } + $attendee = $summit->getAttendeeByMemberId($member_id); + } else { + $attendee = $summit->getAttendeeById(intval($attendee_id)); + } + + return $attendee; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/apis/protected/summit/strategies/CheckMeSpeakerStrategy.php b/app/Http/Controllers/apis/protected/summit/strategies/CheckMeSpeakerStrategy.php new file mode 100644 index 00000000..488d2a96 --- /dev/null +++ b/app/Http/Controllers/apis/protected/summit/strategies/CheckMeSpeakerStrategy.php @@ -0,0 +1,60 @@ +resource_server_context = $resource_server_context; + } + + /** + * @param mixed $speaker_id + * @param Summit $summit + * @return null|PresentationSpeaker + */ + public function check($speaker_id, Summit $summit) + { + if (strtolower($speaker_id) === 'me') { + $member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($member_id)) { + return $this->error404(); + } + $speaker = $summit->getSpeakerByMemberId($member_id); + } else { + $speaker = $summit->getSpeakerById(intval($speaker_id)); + } + return $speaker; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/apis/protected/summit/strategies/CheckMyOwnAttendeeStrategy.php b/app/Http/Controllers/apis/protected/summit/strategies/CheckMyOwnAttendeeStrategy.php new file mode 100644 index 00000000..1daf66fd --- /dev/null +++ b/app/Http/Controllers/apis/protected/summit/strategies/CheckMyOwnAttendeeStrategy.php @@ -0,0 +1,43 @@ +member()->ID); + $member_id = $this->resource_server_context->getCurrentUserExternalId(); + if(is_null($member_id) || ($attendee_member_id !== $member_id)) throw new \HTTP401UnauthorizedException; + return $attendee; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/apis/protected/summit/strategies/CurrentSummitFinderStrategy.php b/app/Http/Controllers/apis/protected/summit/strategies/CurrentSummitFinderStrategy.php new file mode 100644 index 00000000..2481b3d1 --- /dev/null +++ b/app/Http/Controllers/apis/protected/summit/strategies/CurrentSummitFinderStrategy.php @@ -0,0 +1,46 @@ +repository = $repository; + } + + /** + * @param mixed $summit_id + * @return null|Summit + */ + public function find($summit_id) + { + $summit = $summit_id === 'current' ? $this->repository->getCurrent() : $this->repository->getById(intval($summit_id)); + return $summit; + } +} \ No newline at end of file diff --git a/app/Http/Exceptions/HTTP401UnauthorizedException.php b/app/Http/Exceptions/HTTP401UnauthorizedException.php new file mode 100644 index 00000000..d14555e9 --- /dev/null +++ b/app/Http/Exceptions/HTTP401UnauthorizedException.php @@ -0,0 +1,18 @@ + 'App\Http\Middleware\Authenticate', - 'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth', - 'guest' => 'App\Http\Middleware\RedirectIfAuthenticated', - 'oauth2.protected' => 'App\Http\Middleware\OAuth2BearerAccessTokenRequestValidator', - 'rate.limit' => 'App\Http\Middleware\RateLimitMiddleware', - 'etags' => 'App\Http\Middleware\ETagsMiddleware', - ]; + /** + * The application's route middleware. + * @var array + */ + protected $routeMiddleware = [ + 'auth' => 'App\Http\Middleware\Authenticate', + 'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth', + 'guest' => 'App\Http\Middleware\RedirectIfAuthenticated', + 'oauth2.protected' => 'App\Http\Middleware\OAuth2BearerAccessTokenRequestValidator', + 'rate.limit' => 'App\Http\Middleware\RateLimitMiddleware', + 'etags' => 'App\Http\Middleware\ETagsMiddleware', + 'cache' => 'App\Http\Middleware\CacheMiddleware', + ]; } \ No newline at end of file diff --git a/app/Http/Middleware/CacheMiddleware.php b/app/Http/Middleware/CacheMiddleware.php new file mode 100644 index 00000000..3eae6bff --- /dev/null +++ b/app/Http/Middleware/CacheMiddleware.php @@ -0,0 +1,118 @@ +context = $context; + $this->cache_service = $cache_service; + } + + + /** + * Handle an incoming request. + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, Closure $next) + { + if ($request->getMethod() !== 'GET') + { + // shortcircuit + return $next($request); + } + + $key = $request->getPathInfo(); + $query = $request->getQueryString(); + $current_time = time(); + + if(!empty($query)) + { + $query = explode('&', $query); + foreach($query as $q) + { + $q = explode('=',$q); + if(strtolower($q[0]) === 'access_token'|| strtolower($q[0]) === 'token_type' ) continue; + $key .= ".".implode("=",$q); + } + } + + $cache_lifetime = intval(Config::get('server.response_cache_lifetime', 300)); + + if (str_contains($request->getPathInfo(), '/me')) + { + $key .= ':' . $this->context->getCurrentUserExternalId(); + } + + $data = $this->cache_service->getSingleValue($key); + $time = $this->cache_service->getSingleValue($key.".generated"); + + if (empty($data) || empty($time)) + { + $time = $current_time; + Log::debug(sprintf("cache value not found for key %s , getting from api...", $key)); + // normal flow ... + $response = $next($request); + if ($response instanceof JsonResponse && $response->getStatusCode() === 200) + { + // and if its json, store it on cache ... + $data = $response->getData(true); + $this->cache_service->setSingleValue($key, json_encode($data), $cache_lifetime); + $this->cache_service->setSingleValue($key.".generated", $time, $cache_lifetime); + } + } + else + { + // cache hit ... + Log::debug(sprintf("cache hit for %s ...", $key)); + $response = new JsonResponse(json_decode($data, true), 200, array + ( + 'content-type' => 'application/json', + ) + ); + } + + $response->headers->set('xcontent-timestamp', $time); + $response->headers->set('Cache-Control', sprintf('private, max-age=%s', $cache_lifetime)); + $response->headers->set('Expires', gmdate('D, d M Y H:i:s \G\M\T', $time + $cache_lifetime)); + + return $response; + } +} \ No newline at end of file diff --git a/app/Http/Middleware/ETagsMiddleware.php b/app/Http/Middleware/ETagsMiddleware.php index e2f14366..49be902e 100644 --- a/app/Http/Middleware/ETagsMiddleware.php +++ b/app/Http/Middleware/ETagsMiddleware.php @@ -1,44 +1,53 @@ getStatusCode() === 200) - { - $etag = md5($response->getContent()); - $requestETag = str_replace('"', '', $request->getETags()); - if ($requestETag && $requestETag[0] == $etag) - { - $response->setNotModified(); - } - $response->setEtag($etag); - } - return $response; - } + /** + * Handle an incoming request. + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, Closure $next) + { + $response = $next($request); + if ($response->getStatusCode() === 200 && $request->getMethod() === 'GET') + { + $etag = md5($response->getContent()); + $requestETag = str_replace('"', '', $request->getETags()); + $requestETag = str_replace('-gzip', '', $requestETag); + + if ($requestETag && $requestETag[0] == $etag) + { + Log::debug('ETAG 304'); + $response->setNotModified(); + } + $response->setEtag($etag); + } + + return $response; + } } \ No newline at end of file diff --git a/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php b/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php index d456b534..18d8cfbf 100644 --- a/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php +++ b/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php @@ -1,286 +1,277 @@ context = $context; - $this->headers = $this->getHeaders(); - $this->endpoint_repository = $endpoint_repository; - $this->token_service = $token_service; - } + /** + * @param IResourceServerContext $context + * @param IApiEndpointRepository $endpoint_repository + * @param IAccessTokenService $token_service + */ + public function __construct( + IResourceServerContext $context, + IApiEndpointRepository $endpoint_repository, + IAccessTokenService $token_service + ) { + $this->context = $context; + $this->headers = $this->getHeaders(); + $this->endpoint_repository = $endpoint_repository; + $this->token_service = $token_service; + } - /** - * @param \Illuminate\Http\Request $request - * @param callable $next - * @return OAuth2WWWAuthenticateErrorResponse - */ - public function handle($request, Closure $next) - { - $url = $request->getRequestUri(); - $method = $request->getMethod(); - $realm = $request->getHost(); + /** + * @param \Illuminate\Http\Request $request + * @param Closure $next + * @return OAuth2WWWAuthenticateErrorResponse + */ + public function handle($request, Closure $next) + { + $url = $request->getRequestUri(); + $method = $request->getMethod(); + $realm = $request->getHost(); - try - { - $route = RequestUtils::getCurrentRoutePath($request); - if (!$route) - { - throw new OAuth2ResourceServerException( - 400, - OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, - sprintf('API endpoint does not exits! (%s:%s)', $url, $method) - ); - } - // http://tools.ietf.org/id/draft-abarth-origin-03.html - $origin = $request->headers->has('Origin') ? $request->headers->get('Origin') : null; - if(!empty($origin)) - { - $nm = new Normalizer($origin); - $origin = $nm->normalize(); - } + try { + $route = RequestUtils::getCurrentRoutePath($request); + if (!$route) { + throw new OAuth2ResourceServerException( + 400, + OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, + sprintf('API endpoint does not exits! (%s:%s)', $url, $method) + ); + } - //check first http basic auth header - $auth_header = isset($this->headers['authorization']) ? $this->headers['authorization'] : null; - if (!is_null($auth_header) && !empty($auth_header)) - { - $access_token_value = BearerAccessTokenAuthorizationHeaderParser::getInstance()->parse($auth_header); - } - else - { - // http://tools.ietf.org/html/rfc6750#section-2- 2 - // if access token is not on authorization header check on POST/GET params - $access_token_value = Input::get(OAuth2Protocol::OAuth2Protocol_AccessToken, ''); - } + Log::debug($request->headers->__toString()); + // http://tools.ietf.org/id/draft-abarth-origin-03.html + $origin = $request->headers->has('Origin') ? $request->headers->get('Origin') : null; + if (!empty($origin)) { + $nm = new Normalizer($origin); + $origin = $nm->normalize(); + } - if (is_null($access_token_value) || empty($access_token_value)) - { - //if access token value is not set, then error - throw new OAuth2ResourceServerException( - 400, - OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, - 'missing access token' - ); - } + //check first http basic auth header + $auth_header = isset($this->headers['authorization']) ? $this->headers['authorization'] : null; + if (!is_null($auth_header) && !empty($auth_header)) { + $access_token_value = BearerAccessTokenAuthorizationHeaderParser::getInstance()->parse($auth_header); + } else { + // http://tools.ietf.org/html/rfc6750#section-2- 2 + // if access token is not on authorization header check on POST/GET params + $access_token_value = Input::get(OAuth2Protocol::OAuth2Protocol_AccessToken, ''); + } - $endpoint = $this->endpoint_repository->getApiEndpointByUrlAndMethod($route, $method); + if (is_null($access_token_value) || empty($access_token_value)) { + //if access token value is not set, then error + throw new OAuth2ResourceServerException( + 400, + OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, + 'missing access token' + ); + } - //api endpoint must be registered on db and active - if (is_null($endpoint) || !$endpoint->isActive()) - { - throw new OAuth2ResourceServerException( - 400, - OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, - sprintf('API endpoint does not exits! (%s:%s)', $route, $method) - ); - } + $endpoint = $this->endpoint_repository->getApiEndpointByUrlAndMethod($route, $method); - $token_info = $this->token_service->get($access_token_value); + //api endpoint must be registered on db and active + if (is_null($endpoint) || !$endpoint->isActive()) { + throw new OAuth2ResourceServerException( + 400, + OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, + sprintf('API endpoint does not exits! (%s:%s)', $route, $method) + ); + } - //check lifetime - if (is_null($token_info) || $token_info->getLifetime() <= 0) - { - throw new OAuth2ResourceServerException( - 401, - OAuth2Protocol::OAuth2Protocol_Error_UnauthorizedClient, - 'invalid origin' - ); - } - //check token audience - $audience = explode(' ', $token_info->getAudience()); - if ((!in_array($realm, $audience))) - { - throw new OAuth2ResourceServerException( - 401, - OAuth2Protocol::OAuth2Protocol_Error_InvalidToken, - 'the access token provided is expired, revoked, malformed, or invalid for other reasons.' - ); - } - if ($token_info->getApplicationType() === 'JS_CLIENT' && str_contains($token_info->getAllowedOrigins(), $origin) === false) - { - //check origins - throw new OAuth2ResourceServerException( - 403, - OAuth2Protocol::OAuth2Protocol_Error_UnauthorizedClient, - 'invalid origin' - ); - } - //check scopes - $endpoint_scopes = explode(' ', $endpoint->getScope()); - $token_scopes = explode(' ', $token_info->getScope()); - //check token available scopes vs. endpoint scopes - if (count(array_intersect($endpoint_scopes, $token_scopes)) == 0) - { - Log::error( - sprintf( - 'access token scopes (%s) does not allow to access to api url %s , needed scopes %s', - $token_info->getScope(), - $url, - implode(' OR ', $endpoint_scopes) - ) - ); + $token_info = $this->token_service->get($access_token_value); + if(!is_null($token_info)) + Log::debug(sprintf("token lifetime %s", $token_info->getLifetime())); + //check lifetime + if (is_null($token_info)) { + throw new InvalidGrantTypeException(OAuth2Protocol::OAuth2Protocol_Error_InvalidToken); + } + //check token audience + Log::debug('checking token audience ...'); + $audience = explode(' ', $token_info->getAudience()); + if ((!in_array($realm, $audience))) { + throw new InvalidGrantTypeException(OAuth2Protocol::OAuth2Protocol_Error_InvalidToken); + } + if ($token_info->getApplicationType() === 'JS_CLIENT' && str_contains($token_info->getAllowedOrigins(), + $origin) === false + ) { + //check origins + throw new OAuth2ResourceServerException( + 403, + OAuth2Protocol::OAuth2Protocol_Error_UnauthorizedClient, + sprintf('invalid origin %s - allowed ones (%s)',$origin, $token_info->getAllowedOrigins()) + ); + } + //check scopes + Log::debug('checking token scopes ...'); + $endpoint_scopes = explode(' ', $endpoint->getScope()); + $token_scopes = explode(' ', $token_info->getScope()); - throw new OAuth2ResourceServerException( - 403, - OAuth2Protocol::OAuth2Protocol_Error_InsufficientScope, - 'the request requires higher privileges than provided by the access token', - implode(' ', $endpoint_scopes) - ); - } - //set context for api and continue processing - $context = array( - 'access_token' => $access_token_value, - 'expires_in' => $token_info->getLifetime(), - 'client_id' => $token_info->getClientId(), - 'scope' => $token_info->getScope() - ); + //check token available scopes vs. endpoint scopes + if (count(array_intersect($endpoint_scopes, $token_scopes)) == 0) { + Log::error( + sprintf( + 'access token scopes (%s) does not allow to access to api url %s , needed scopes %s', + $token_info->getScope(), + $url, + implode(' OR ', $endpoint_scopes) + ) + ); - if (!is_null($token_info->getUserId())) - { - $context['user_id'] = $token_info->getUserId(); - } - $this->context->setAuthorizationContext($context); - } - catch (OAuth2ResourceServerException $ex1) - { - Log::error($ex1); - $response = new OAuth2WWWAuthenticateErrorResponse( - $realm, - $ex1->getError(), - $ex1->getErrorDescription(), - $ex1->getScope(), - $ex1->getHttpCode() - ); - $http_response = Response::json($response->getContent(), $response->getHttpCode()); - $http_response->header('WWW-Authenticate', $response->getWWWAuthenticateHeaderValue()); - return $http_response; - } - catch (InvalidGrantTypeException $ex2) - { - Log::error($ex2); - $response = new OAuth2WWWAuthenticateErrorResponse( - $realm, - OAuth2Protocol::OAuth2Protocol_Error_InvalidToken, - 'the access token provided is expired, revoked, malformed, or invalid for other reasons.', - null, - 401 - ); - $http_response = Response::json($response->getContent(), $response->getHttpCode()); - $http_response->header('WWW-Authenticate', $response->getWWWAuthenticateHeaderValue()); - return $http_response; - } - catch (\Exception $ex) - { - Log::error($ex); - $response = new OAuth2WWWAuthenticateErrorResponse( - $realm, - OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, - 'invalid request', - null, - 400 - ); - $http_response = Response::json($response->getContent(), $response->getHttpCode()); - $http_response->header('WWW-Authenticate', $response->getWWWAuthenticateHeaderValue()); - return $http_response; - } - $response = $next($request); - return $response; - } + throw new OAuth2ResourceServerException( + 403, + OAuth2Protocol::OAuth2Protocol_Error_InsufficientScope, + 'the request requires higher privileges than provided by the access token', + implode(' ', $endpoint_scopes) + ); + } + Log::debug('setting resource server context ...'); + //set context for api and continue processing + $context = array + ( + 'access_token' => $access_token_value, + 'expires_in' => $token_info->getLifetime(), + 'client_id' => $token_info->getClientId(), + 'scope' => $token_info->getScope(), + 'application_type' => $token_info->getApplicationType() + ); - /** - * @return array - */ - protected function getHeaders() - { - $headers = array(); - if (function_exists('getallheaders')) - { - foreach (getallheaders() as $name => $value) - { - $headers[strtolower($name)] = $value; - } - } - else - { - // @codeCoverageIgnoreEnd - foreach ($_SERVER as $name => $value) - { - if (substr($name, 0, 5) == 'HTTP_') - { - $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); - $headers[strtolower($name)] = $value; - } - } - foreach (Request::header() as $name => $value) - { - if (!array_key_exists($name, $headers)) - { - $headers[strtolower($name)] = $value[0]; - } - } - } - return $headers; - } + if (!is_null($token_info->getUserId())) + { + $context['user_id'] = $token_info->getUserId(); + $context['user_external_id'] = $token_info->getUserExternalId(); + } + + $this->context->setAuthorizationContext($context); + + } + catch (OAuth2ResourceServerException $ex1) + { + Log::error($ex1); + $response = new OAuth2WWWAuthenticateErrorResponse( + $realm, + $ex1->getError(), + $ex1->getErrorDescription(), + $ex1->getScope(), + $ex1->getHttpCode() + ); + $http_response = Response::json($response->getContent(), $response->getHttpCode()); + $http_response->header('WWW-Authenticate', $response->getWWWAuthenticateHeaderValue()); + + return $http_response; + } + catch (InvalidGrantTypeException $ex2) + { + Log::error($ex2); + $response = new OAuth2WWWAuthenticateErrorResponse( + $realm, + OAuth2Protocol::OAuth2Protocol_Error_InvalidToken, + 'the access token provided is expired, revoked, malformed, or invalid for other reasons.', + null, + 401 + ); + $http_response = Response::json($response->getContent(), $response->getHttpCode()); + $http_response->header('WWW-Authenticate', $response->getWWWAuthenticateHeaderValue()); + + return $http_response; + } catch (\Exception $ex) { + Log::error($ex); + $response = new OAuth2WWWAuthenticateErrorResponse( + $realm, + OAuth2Protocol::OAuth2Protocol_Error_InvalidRequest, + 'invalid request', + null, + 400 + ); + $http_response = Response::json($response->getContent(), $response->getHttpCode()); + $http_response->header('WWW-Authenticate', $response->getWWWAuthenticateHeaderValue()); + + return $http_response; + } + $response = $next($request); + + return $response; + } + + /** + * @return array + */ + protected function getHeaders() + { + $headers = array(); + if (function_exists('getallheaders')) { + foreach (getallheaders() as $name => $value) { + $headers[strtolower($name)] = $value; + } + } else { + // @codeCoverageIgnoreEnd + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); + $headers[strtolower($name)] = $value; + } + } + foreach (Request::header() as $name => $value) { + if (!array_key_exists($name, $headers)) { + $headers[strtolower($name)] = $value[0]; + } + } + } + + return $headers; + } } \ No newline at end of file diff --git a/app/Http/Middleware/RateLimitMiddleware.php b/app/Http/Middleware/RateLimitMiddleware.php index 81689bb6..73ccd58c 100644 --- a/app/Http/Middleware/RateLimitMiddleware.php +++ b/app/Http/Middleware/RateLimitMiddleware.php @@ -1,106 +1,101 @@ endpoint_repository = $endpoint_repository; - $this->cache_service = $cache_service; - } + /** + * @param IApiEndpointRepository $endpoint_repository + * @param ICacheService $cache_service + */ + public function __construct(IApiEndpointRepository $endpoint_repository, ICacheService $cache_service) + { + $this->endpoint_repository = $endpoint_repository; + $this->cache_service = $cache_service; + } - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @return mixed - */ - public function handle($request, Closure $next) - { - $response = $next($request); - // if response was not changed then short circuit ... - if ($response->getStatusCode() === 304) - { - return $response; - } + /** + * Handle an incoming request. + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, Closure $next) + { + $response = $next($request); + // if response was not changed then short circuit ... + if ($response->getStatusCode() === 304) { + return $response; + } - $url = $request->getRequestUri(); + $url = $request->getRequestUri(); - try - { - $route = RequestUtils::getCurrentRoutePath($request); - $method = $request->getMethod(); - $endpoint = $this->endpoint_repository->getApiEndpointByUrlAndMethod($route, $method); + try { + $route = RequestUtils::getCurrentRoutePath($request); + $method = $request->getMethod(); + $endpoint = $this->endpoint_repository->getApiEndpointByUrlAndMethod($route, $method); - if (!is_null($endpoint->rate_limit) && ($requestsPerHour = (int)$endpoint->rate_limit) > 0) - { - //do rate limit checking - $key = sprintf('rate.limit.%s_%s_%s', $url, $method, $request->getClientIp()); - // Add if doesn't exist - // Remember for 1 hour - $this->cache_service->addSingleValue($key, 0, 3600); - // Add to count - $count = $this->cache_service->incCounter($key); - if ( $count > $requestsPerHour ) - { - // Short-circuit response - we're ignoring - $response = Response::json(array( - 'message' => "You have triggered an abuse detection mechanism and have been temporarily blocked. - Please retry your request again later."), 403); - $ttl = (int) $this->cache_service->ttl($key); - $response->headers->set('X-RateLimit-Reset', $ttl, false); - } - $response->headers->set('X-Ratelimit-Limit', $requestsPerHour, false); - $remaining = $requestsPerHour-(int)$count; - if ($remaining < 0) - { - $remaining = 0; - } - $response->headers->set('X-Ratelimit-Remaining', $remaining, false); - } - } - catch (Exception $ex) - { - Log::error($ex); - } - return $response; - } + if (!is_null($endpoint->rate_limit) && ($requestsPerHour = (int)$endpoint->rate_limit) > 0) { + //do rate limit checking + $key = sprintf('rate.limit.%s_%s_%s', $url, $method, $request->getClientIp()); + // Add if doesn't exist + // Remember for 1 hour + $this->cache_service->addSingleValue($key, 0, 3600); + // Add to count + $count = $this->cache_service->incCounter($key); + if ($count > $requestsPerHour) { + // Short-circuit response - we're ignoring + $response = Response::json(array( + 'message' => "You have triggered an abuse detection mechanism and have been temporarily blocked. + Please retry your request again later." + ), 403); + $ttl = (int)$this->cache_service->ttl($key); + $response->headers->set('X-RateLimit-Reset', $ttl, false); + } + $response->headers->set('X-Ratelimit-Limit', $requestsPerHour, false); + $remaining = $requestsPerHour - (int)$count; + if ($remaining < 0) { + $remaining = 0; + } + $response->headers->set('X-Ratelimit-Remaining', $remaining, false); + } + } catch (Exception $ex) { + Log::error($ex); + } + + return $response; + } } \ No newline at end of file diff --git a/app/Http/Middleware/SecurityHTTPHeadersWriterMiddleware.php b/app/Http/Middleware/SecurityHTTPHeadersWriterMiddleware.php index 257f996f..f2446b12 100644 --- a/app/Http/Middleware/SecurityHTTPHeadersWriterMiddleware.php +++ b/app/Http/Middleware/SecurityHTTPHeadersWriterMiddleware.php @@ -44,7 +44,7 @@ class SecurityHTTPHeadersWriterMiddleware implements Middleware * applies to the domain of the issuing HSTS Host and all of its * subdomains: */ - $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + //$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); return $response; } } \ No newline at end of file diff --git a/app/Http/Utils/AbstractFilterElement.php b/app/Http/Utils/AbstractFilterElement.php new file mode 100644 index 00000000..028a3f62 --- /dev/null +++ b/app/Http/Utils/AbstractFilterElement.php @@ -0,0 +1,36 @@ +operator = $operator; + } + + /** + * @return string + */ + public function getOperator(){ + return $this->operator; + } +} \ No newline at end of file diff --git a/app/Http/Utils/Filter.php b/app/Http/Utils/Filter.php new file mode 100644 index 00000000..2738e064 --- /dev/null +++ b/app/Http/Utils/Filter.php @@ -0,0 +1,183 @@ +filters = $filters; + } + + /** + * @param string $field + * @return null|FilterElement + */ + public function getFilter($field) + { + foreach($this->filters as $f) + { + if($f->getField() === $field) + { + return $f; + } + } + return null; + } + + /** + * @param Relation $relation + * @param array $mappings + * @return $this + */ + public function apply2Relation(Relation $relation, array $mappings) + { + foreach($this->filters as $filter) + { + if($filter instanceof FilterElement) + { + if(isset($mappings[$filter->getField()])) + { + $mapping = $mappings[$filter->getField()]; + $mapping = explode(':', $mapping); + $value = $filter->getValue(); + if(count($mapping) > 1) + { + $value = $this->convertValue($value, $mapping[1]); + } + $relation->getQuery()->where($mapping[0], $filter->getOperator(), $value); + } + } + else if(is_array($filter)) + { + // OR + $relation->getQuery()->where(function ($query) use($filter, $mappings){ + foreach($filter as $e) { + if($e instanceof FilterElement && isset($mappings[$e->getField()])) + { + $mapping = $mappings[$e->getField()]; + $mapping = explode(':', $mapping); + $value = $e->getValue(); + if(count($mapping) > 1) + { + $value = $this->convertValue($value, $mapping[1]); + } + + $query->orWhere($mapping[0], $e->getOperator(),$value); + } + } + }); + } + } + return $this; + } + + /** + * @param string $value + * @param string $original_format + * @return mixed + */ + private function convertValue($value, $original_format) + { + switch($original_format) + { + case 'datetime_epoch': + $datetime = new \DateTime("@$value"); + return $datetime->format("Y-m-d H:i:s"); + break; + case 'json_int': + return intval($value); + break; + default: + return $value; + break; + } + } + + /** + * @return array + */ + public function getSQLBindings() + { + return $this->bindings; + } + /** + * @param array $mappings + * @return string + */ + public function toRawSQL(array $mappings) + { + $sql = ''; + $this->bindings = array(); + + foreach($this->filters as $filter) + { + if($filter instanceof FilterElement) + { + if(isset($mappings[$filter->getField()])) + { + $mapping = $mappings[$filter->getField()]; + $mapping = explode(':', $mapping); + $value = $filter->getValue(); + $op = $filter->getOperator(); + if(count($mapping) > 1) + { + $filter->setValue( $this->convertValue($value, $mapping[1])); + } + $cond = sprintf(' %s %s :%s', $mapping[0], $op, $filter->getField()); + $this->bindings[$filter->getField()] = $filter->getValue(); + if(!empty($sql)) $sql .= " AND "; + $sql .= $cond; + } + } + else if(is_array($filter)) + { + // OR + $sql .= " ( "; + $sql_or = ''; + foreach($filter as $e) + { + if($e instanceof FilterElement && isset($mappings[$e->getField()])) + { + $mapping = $mappings[$e->getField()]; + $mapping = explode(':', $mapping); + $value = $e->getValue(); + $op = $e->getOperator(); + if(count($mapping) > 1) + { + $e->setValue( $this->convertValue($value, $mapping[1])); + } + $cond = sprintf(' %s %s :%s', $mapping[0], $op, $e->getField()); + $this->bindings[$e->getField()] = $e->getValue(); + if(!empty($sql_or)) $sql_or .= " OR "; + $sql_or .= $cond; + } + } + $sql .= $sql_or. " ) "; + } + } + return $sql; + } +} \ No newline at end of file diff --git a/app/Http/Utils/FilterElement.php b/app/Http/Utils/FilterElement.php new file mode 100644 index 00000000..8569657a --- /dev/null +++ b/app/Http/Utils/FilterElement.php @@ -0,0 +1,106 @@ +field = $field; + $this->value = $value; + } + + /** + * @param mixed $value + * @return $this + */ + public function setValue($value) + { + $this->value = $value; + return $this; + } + + /** + * @return string + */ + public function getField() + { + return $this->field; + } + + /** + * @return string + */ + public function getValue() + { + switch($this->operator) + { + case 'like': + return "%".$this->value."%"; + break; + default: + return $this->value; + break; + } + } + + public static function makeEqual($field, $value) + { + return new self($field, $value, '='); + } + + public static function makeGreather($field, $value) + { + return new self($field, $value, '>'); + } + + public static function makeGreatherOrEqual($field, $value) + { + return new self($field, $value, '=>'); + } + + public static function makeLower($field, $value) + { + return new self($field, $value, '>'); + } + + public static function makeLowerOrEqual($field, $value) + { + return new self($field, $value, '>='); + } + + public static function makeNotEqual($field, $value) + { + return new self($field, $value, '<>'); + } + + public static function makeLike($field, $value) + { + return new self($field, $value, 'like'); + } +} \ No newline at end of file diff --git a/app/Http/Utils/FilterParser.php b/app/Http/Utils/FilterParser.php new file mode 100644 index 00000000..87b72fda --- /dev/null +++ b/app/Http/Utils/FilterParser.php @@ -0,0 +1,115 @@ + 1) + { + $f = array(); + foreach ($or_filters as $of) { + + //single filter + preg_match('/[=<>][=>@]{0,1}/', $of, $matches); + if(count($matches) === 1) + { + $op = $matches[0]; + $operands = explode($op, $of); + $field = $operands[0]; + $value = $operands[1]; + if(!isset($allowed_fields[$field])) continue; + if(!in_array($op, $allowed_fields[$field])) continue; + $f_or = self::buildFilter($field, $op, $value); + if(!is_null($f_or)) + array_push($f, $f_or); + } + } + } + else + { + //single filter + preg_match('/[=<>][=>@]{0,1}/', $filter, $matches); + if(count($matches) === 1) + { + $op = $matches[0]; + $operands = explode($op, $filter); + $field = $operands[0]; + $value = $operands[1]; + if(!isset($allowed_fields[$field])) continue; + if(!in_array($op, $allowed_fields[$field])) continue; + $f = self::buildFilter($field, $op, $value); + + } + } + if(!is_null($f)) + array_push($res, $f); + } + return new Filter($res); + } + + /** + * Factory Method + * + * @param string $field + * @param string $op + * @param string $value + * @return FilterElement|null + */ + private static function buildFilter($field, $op, $value) + { + switch($op) + { + case '==': + return FilterElement::makeEqual($field, $value); + break; + case '=@': + return FilterElement::makeLike($field, $value); + break; + case '>': + return FilterElement::makeGreather($field, $value); + break; + case '>=': + return FilterElement::makeGreatherOrEqual($field, $value); + break; + case '<': + return FilterElement::makeLower($field, $value); + break; + case '<=': + return FilterElement::makeLowerOrEqual($field, $value); + break; + case '<>': + return FilterElement::makeNotEqual($field, $value); + break; + } + return null; + } +} \ No newline at end of file diff --git a/app/Http/Utils/Order.php b/app/Http/Utils/Order.php new file mode 100644 index 00000000..d0020468 --- /dev/null +++ b/app/Http/Utils/Order.php @@ -0,0 +1,66 @@ +ordering = $ordering; + } + + public function apply2Relation(Relation $relation, array $mappings) + { + foreach ($this->ordering as $order) { + if ($order instanceof OrderElement) { + if (isset($mappings[$order->getField()])) { + $mapping = $mappings[$order->getField()]; + $relation->getQuery()->orderBy($mapping, $order->getDirection()); + } + } + } + + return $this; + } + + /** + * @param array $mappings + * @return string + */ + public function toRawSQL(array $mappings) + { + $sql = ' ORDER BY '; + foreach ($this->ordering as $order) { + if ($order instanceof OrderElement) { + if (isset($mappings[$order->getField()])) { + $mapping = $mappings[$order->getField()]; + $sql .= sprintf('%s %s, ', $mapping, $order->getDirection()); + } + } + } + return substr($sql, 0 , strlen($sql) - 2); + } +} \ No newline at end of file diff --git a/app/Http/Utils/OrderElement.php b/app/Http/Utils/OrderElement.php new file mode 100644 index 00000000..68d0dfdb --- /dev/null +++ b/app/Http/Utils/OrderElement.php @@ -0,0 +1,74 @@ +field = $field; + $this->direction = $direction; + } + + public static function buildAscFor($field) + { + return new OrderElement($field, 'ASC'); + } + + public static function buildDescFor($field) + { + return new OrderElement($field, 'DESC'); + } + + /** + * @return string + */ + public function getField() + { + return $this->field; + } + + public function isAsc() + { + return $this->direction === 'ASC'; + } + + /** + * @return string + */ + public function getDirection() + { + return $this->direction; + } +} \ No newline at end of file diff --git a/app/Http/Utils/OrderParser.php b/app/Http/Utils/OrderParser.php new file mode 100644 index 00000000..48823f73 --- /dev/null +++ b/app/Http/Utils/OrderParser.php @@ -0,0 +1,57 @@ +page = $page; + $this->per_page = $per_page; + } + + /** + * @return int + */ + public function getCurrentPage() + { + return $this->page; + } + + /** + * @return int + */ + public function getPerPage() + { + return $this->per_page; + } + + /** + * @return int + */ + public function getOffset() + { + return ($this->page - 1) * $this->per_page; + } +} \ No newline at end of file diff --git a/app/Http/Utils/PagingResponse.php b/app/Http/Utils/PagingResponse.php new file mode 100644 index 00000000..457a6657 --- /dev/null +++ b/app/Http/Utils/PagingResponse.php @@ -0,0 +1,105 @@ +total = $total; + $this->per_page = $per_page; + $this->page = $page; + $this->last_page = $last_page; + $this->items = $items; + } + + public function getTotal() + { + return $this->total; + } + + /** + * @return int + */ + public function getPerPage() + { + return $this->per_page; + } + + /** + * @return int + */ + public function getCurrentPage() + { + return $this->page; + } + + /** + * @return int + */ + public function getLastPage() + { + return $this->last_page; + } + + /** + * @return array + */ + public function getItems() + { + return $this->items; + } + + /** + * @return array + */ + public function toArray() + { + return array + ( + 'total' => $this->total, + 'per_page' => $this->per_page, + 'current_page' => $this->page, + 'last_page' => $this->last_page, + 'data' => $this->items, + ); + } +} \ No newline at end of file diff --git a/app/Http/routes.php b/app/Http/routes.php index 3e3a2528..b7a13b78 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -11,30 +11,114 @@ | */ //OAuth2 Protected API -Route::group(array('prefix' => 'api/v1', - 'before' => ['ssl', 'oauth2.enabled'], - 'after' => '', - 'middleware' => ['oauth2.protected', 'rate.limit','etags']), function () { +Route::group(array( + 'prefix' => 'api/v1', + 'before' => ['ssl', 'oauth2.enabled'], + 'after' => '', + 'middleware' => ['oauth2.protected', 'rate.limit','etags'] +), function () { - Route::group(array('prefix' => 'marketplace'), function () { + Route::group(array('prefix' => 'marketplace'), function () { - Route::group(array('prefix' => 'public-clouds'), function () { - Route::get('', 'OAuth2PublicCloudApiController@getClouds'); - Route::get('/{id}', 'OAuth2PublicCloudApiController@getCloud'); - Route::get('/{id}/data-centers', 'OAuth2PublicCloudApiController@getCloudDataCenters'); - }); + Route::group(array('prefix' => 'public-clouds'), function () { + Route::get('', 'OAuth2PublicCloudApiController@getClouds'); + Route::get('/{id}', 'OAuth2PublicCloudApiController@getCloud'); + Route::get('/{id}/data-centers', 'OAuth2PublicCloudApiController@getCloudDataCenters'); + }); - Route::group(array('prefix' => 'private-clouds'), function () { - Route::get('', 'OAuth2PrivateCloudApiController@getClouds'); - Route::get('/{id}', 'OAuth2PrivateCloudApiController@getCloud'); - Route::get('/{id}/data-centers', 'OAuth2PrivateCloudApiController@getCloudDataCenters'); - }); + Route::group(array('prefix' => 'private-clouds'), function () { + Route::get('', 'OAuth2PrivateCloudApiController@getClouds'); + Route::get('/{id}', 'OAuth2PrivateCloudApiController@getCloud'); + Route::get('/{id}/data-centers', 'OAuth2PrivateCloudApiController@getCloudDataCenters'); + }); - Route::group(array('prefix' => 'consultants'), function () { - Route::get('', 'OAuth2ConsultantsApiController@getConsultants'); - Route::get('/{id}', 'OAuth2ConsultantsApiController@getConsultant'); - Route::get('/{id}/offices', 'OAuth2ConsultantsApiController@getOffices'); - }); + Route::group(array('prefix' => 'consultants'), function () { + Route::get('', 'OAuth2ConsultantsApiController@getConsultants'); + Route::get('/{id}', 'OAuth2ConsultantsApiController@getConsultant'); + Route::get('/{id}/offices', 'OAuth2ConsultantsApiController@getOffices'); + }); - }); - }); \ No newline at end of file + }); + + // summits + Route::group(array('prefix' => 'summits'), function () { + Route::get('', 'OAuth2SummitApiController@getSummits'); + Route::group(array('prefix' => '{id}'), function () { + Route::get('', [ 'middleware' => 'cache', 'uses' => 'OAuth2SummitApiController@getSummit'])->where('id', 'current|[0-9]+'); + + Route::get('entity-events', 'OAuth2SummitApiController@getSummitEntityEvents'); + // attendees + Route::group(array('prefix' => 'attendees'), function () { + + //Route::get('', 'OAuth2SummitApiController@getAttendees'); + + Route::group(array('prefix' => '{attendee_id}'), function () { + + Route::get('', 'OAuth2SummitApiController@getAttendee')->where('attendee_id', 'me|[0-9]+'); + + Route::group(array('prefix' => 'schedule'), function () + { + Route::get('', 'OAuth2SummitApiController@getAttendeeSchedule')->where('attendee_id', 'me|[0-9]+'); + + Route::group(array('prefix' => '{event_id}'), function (){ + Route::post('', 'OAuth2SummitApiController@addEventToAttendeeSchedule')->where('attendee_id', 'me|[0-9]+'); + Route::delete('', 'OAuth2SummitApiController@removeEventFromAttendeeSchedule')->where('attendee_id', 'me|[0-9]+'); + Route::put('/check-in', 'OAuth2SummitApiController@checkingAttendeeOnEvent')->where('attendee_id', 'me|[0-9]+'); + }); + }); + }); + }); + + // speakers + Route::group(array('prefix' => 'speakers'), function () { + + Route::get('', 'OAuth2SummitApiController@getSpeakers'); + + Route::group(array('prefix' => '{speaker_id}'), function () { + Route::get('', 'OAuth2SummitApiController@getSpeaker')->where('speaker_id', 'me|[0-9]+'); + }); + }); + + // events + Route::group(array('prefix' => 'events'), function () { + + Route::get('', 'OAuth2SummitApiController@getEvents'); + Route::get('/published', 'OAuth2SummitApiController@getScheduleEvents'); + Route::post('', 'OAuth2SummitApiController@addEvent'); + Route::group(array('prefix' => '{event_id}'), function () { + + Route::get('', 'OAuth2SummitApiController@getEvent'); + Route::get('/published', 'OAuth2SummitApiController@getScheduleEvent'); + Route::put('', 'OAuth2SummitApiController@updateEvent'); + Route::delete('', 'OAuth2SummitApiController@deleteEvent'); + Route::put('/publish', 'OAuth2SummitApiController@publishEvent'); + Route::delete('/publish', 'OAuth2SummitApiController@unPublishEvent'); + Route::post('/feedback', 'OAuth2SummitApiController@addEventFeedback'); + Route::get('/feedback/{attendee_id?}', 'OAuth2SummitApiController@getEventFeedback')->where('attendee_id', 'me|[0-9]+'); + }); + }); + + // locations + Route::group(array('prefix' => 'locations'), function () { + + Route::get('', 'OAuth2SummitApiController@getLocations'); + + Route::group(array('prefix' => '{location_id}'), function () { + + Route::get('', 'OAuth2SummitApiController@getLocation'); + }); + }); + + // event types + Route::group(array('prefix' => 'event-types'), function () { + Route::get('', 'OAuth2SummitApiController@getEventTypes'); + }); + + // summit types + Route::group(array('prefix' => 'summit-types'), function () { + Route::get('', 'OAuth2SummitApiController@getSummitTypes'); + }); + + }); + }); +}); \ No newline at end of file diff --git a/app/Libs/oauth2/OAuth2Protocol.php b/app/Libs/oauth2/OAuth2Protocol.php index 0adf2f60..04dd71ce 100644 --- a/app/Libs/oauth2/OAuth2Protocol.php +++ b/app/Libs/oauth2/OAuth2Protocol.php @@ -1,92 +1,93 @@ self::OAuth2Protocol_ResponseType_Code, - self::OAuth2Protocol_ResponseType_Token => self::OAuth2Protocol_ResponseType_Token - ); - public static $protocol_definition = array( - self::OAuth2Protocol_ResponseType => self::OAuth2Protocol_ResponseType, - self::OAuth2Protocol_ClientId => self::OAuth2Protocol_ClientId, - self::OAuth2Protocol_RedirectUri => self::OAuth2Protocol_RedirectUri, - self::OAuth2Protocol_Scope => self::OAuth2Protocol_Scope, - self::OAuth2Protocol_State => self::OAuth2Protocol_State - ); + public static $valid_responses_types = array( + self::OAuth2Protocol_ResponseType_Code => self::OAuth2Protocol_ResponseType_Code, + self::OAuth2Protocol_ResponseType_Token => self::OAuth2Protocol_ResponseType_Token + ); + public static $protocol_definition = array( + self::OAuth2Protocol_ResponseType => self::OAuth2Protocol_ResponseType, + self::OAuth2Protocol_ClientId => self::OAuth2Protocol_ClientId, + self::OAuth2Protocol_RedirectUri => self::OAuth2Protocol_RedirectUri, + self::OAuth2Protocol_Scope => self::OAuth2Protocol_Scope, + self::OAuth2Protocol_State => self::OAuth2Protocol_State + ); } \ No newline at end of file diff --git a/app/Libs/oauth2/OAuth2WWWAuthenticateErrorResponse.php b/app/Libs/oauth2/OAuth2WWWAuthenticateErrorResponse.php index ea1b4a2f..8ad52d3f 100644 --- a/app/Libs/oauth2/OAuth2WWWAuthenticateErrorResponse.php +++ b/app/Libs/oauth2/OAuth2WWWAuthenticateErrorResponse.php @@ -1,71 +1,71 @@ realm = $realm; - $this->error = $error; - $this->error_description = $error_description; - $this->scope = $scope; - $this->http_error = $http_error; - } + public function __construct($realm, $error, $error_description, $scope, $http_error) + { + parent::__construct($http_error, self::DirectResponseContentType); + $this->realm = $realm; + $this->error = $error; + $this->error_description = $error_description; + $this->scope = $scope; + $this->http_error = $http_error; + } - public function getWWWAuthenticateHeaderValue() - { - $value=sprintf('Bearer realm="%s"', $this->realm); - $value=$value.sprintf(', error="%s"', $this->error); - $value=$value.sprintf(', error_description="%s"', $this->error_description); - if (!is_null($this->scope)) - { - $value=$value.sprintf(', scope="%s"', $this->scope); - } - return $value; - } + public function getWWWAuthenticateHeaderValue() + { + $value = sprintf('Bearer realm="%s"', $this->realm); + $value = $value . sprintf(', error="%s"', $this->error); + $value = $value . sprintf(', error_description="%s"', $this->error_description); + if (!is_null($this->scope)) { + $value = $value . sprintf(', scope="%s"', $this->scope); + } + + return $value; + } - public function getContent() - { - $content = array( - 'error' => $this->error, - 'error_description' => $this->error_description - ); - if (!is_null($this->scope)) - { - $content['scope'] = $this->scope; - } - return $content; - } + public function getContent() + { + $content = array( + 'error' => $this->error, + 'error_description' => $this->error_description + ); + if (!is_null($this->scope)) { + $content['scope'] = $this->scope; + } - public function getType() - { - return null; - } + return $content; + } + + public function getType() + { + return null; + } } \ No newline at end of file diff --git a/app/Libs/utils/DateTimeUtils.php b/app/Libs/utils/DateTimeUtils.php new file mode 100644 index 00000000..5c8c1cb4 --- /dev/null +++ b/app/Libs/utils/DateTimeUtils.php @@ -0,0 +1,33 @@ +getTimestamp(); + } +} \ No newline at end of file diff --git a/app/Models/Marketplace/CompanyService.php b/app/Models/Marketplace/CompanyService.php deleted file mode 100644 index 114bf2c3..00000000 --- a/app/Models/Marketplace/CompanyService.php +++ /dev/null @@ -1,38 +0,0 @@ -ID; - } -} \ No newline at end of file diff --git a/app/Models/Marketplace/Consultant.php b/app/Models/Marketplace/Consultant.php deleted file mode 100644 index ef1beaa4..00000000 --- a/app/Models/Marketplace/Consultant.php +++ /dev/null @@ -1,28 +0,0 @@ -hasMany('models\marketplace\Office', 'ConsultantID', 'ID')->get(); - } -} \ No newline at end of file diff --git a/app/Models/Marketplace/ICompanyServiceRepository.php b/app/Models/Marketplace/ICompanyServiceRepository.php deleted file mode 100644 index 2ca22192..00000000 --- a/app/Models/Marketplace/ICompanyServiceRepository.php +++ /dev/null @@ -1,45 +0,0 @@ -hasMany('models\marketplace\DataCenterRegion', 'CloudServiceID', 'ID')->get(); - } -} \ No newline at end of file diff --git a/app/Models/ResourceServer/AccessTokenService.php b/app/Models/ResourceServer/AccessTokenService.php deleted file mode 100644 index 81131357..00000000 --- a/app/Models/ResourceServer/AccessTokenService.php +++ /dev/null @@ -1,154 +0,0 @@ -cache_service = $cache_service; - } - - /** - * @param string $token_value - * @return AccessToken - * @throws \Exception - */ - public function get($token_value) - { - $token = null; - - - $token_info = $this->cache_service->getHash(md5($token_value), array( - 'access_token', - 'scope', - 'client_id', - 'audience', - 'user_id', - 'expires_in', - 'application_type', - 'allowed_return_uris', - 'allowed_origins')); - - if (count($token_info) === 0) - { - $token_info = $this->makeRemoteCall($token_value); - $this->cache_service->storeHash(md5($token_value), $token_info, (int)$token_info['expires_in']); - } - else - { - $token_info['expires_in'] = $this->cache_service->ttl(md5($token_value)); - } - - $token = AccessToken::createFromParams( - $token_info['access_token'], - $token_info['scope'], - $token_info['client_id'], - $token_info['audience'], - $token_info['user_id'], - (int)$token_info['expires_in'], - $token_info['application_type'], - isset($token_info['allowed_return_uris']) ? $token_info['allowed_return_uris'] : null, - isset($token_info['allowed_origins']) ? $token_info['allowed_origins'] : null - ); - - return $token; - } - - /** - * @param $token_value - * @return mixed - * @throws ConfigurationException - * @throws InvalidGrantTypeException - * @throws OAuth2InvalidIntrospectionResponse - */ - private function makeRemoteCall($token_value) - { - - try - { - $client = new Client([ - 'defaults' => [ - 'timeout' => Config::get('curl.timeout', 60), - 'allow_redirects' => Config::get('curl.allow_redirects', false), - 'verify' => Config::get('curl.verify_ssl_cert', true) - ] - ]); - - $client_id = Config::get('app.openstackid_client_id', ''); - $client_secret = Config::get('app.openstackid_client_secret', ''); - $auth_server_url = Config::get('app.openstackid_base_url', ''); - - if (empty($client_id)) - { - throw new ConfigurationException('app.openstackid_client_id param is missing!'); - } - - if (empty($client_secret)) - { - throw new ConfigurationException('app.openstackid_client_secret param is missing!'); - } - - if (empty($auth_server_url)) - { - throw new ConfigurationException('app.openstackid_base_url param is missing!'); - } - - $response = $client->post( - $auth_server_url . '/oauth2/token/introspection', - [ - 'query' => ['token' => $token_value], - 'headers' => ['Authorization' => " Basic " . base64_encode($client_id . ':' . $client_secret)] - ] - ); - - $token_info = $response->json(); - - return $token_info; - - } - catch (RequestException $ex) - { - $response = $ex->getResponse(); - $body = $response->json(); - $code = $response->getStatusCode(); - if ($code === 400) - { - throw new InvalidGrantTypeException($body['error']); - } - throw new OAuth2InvalidIntrospectionResponse(sprintf('http code %s', $ex->getCode())); - } - } -} \ No newline at end of file diff --git a/app/Models/ResourceServer/IAccessTokenService.php b/app/Models/ResourceServer/IAccessTokenService.php deleted file mode 100644 index 4befc6ca..00000000 --- a/app/Models/ResourceServer/IAccessTokenService.php +++ /dev/null @@ -1,30 +0,0 @@ -where($filter['name'], $filter['op'], $filter['value']); - } - return $query; - } + private $class = null; - public function __construct($attributes = array()) - { - parent::__construct($attributes); - $this->class = new ReflectionClass(get_class($this)); - if ($this->useSti()) - { - $this->setAttribute($this->stiClassField, $this->class->getName()); - } - } + protected $array_mappings = array(); - private function useSti() - { - return ($this->stiClassField && $this->stiBaseClass); - } + /** + * @param $query + * @param array $filters + * @return mixed + */ + public function scopeFilter($query, array $filters) + { + foreach ($filters as $filter) { + $query = $query->where($filter['name'], $filter['op'], $filter['value']); + } - public function newQuery($excludeDeleted = true) - { - $builder = parent::newQuery($excludeDeleted); - // If I am using STI, and I am not the base class, - // then filter on the class name. - if ($this->useSti() && get_class(new $this->stiBaseClass) !== get_class($this)) - { - $builder->where($this->stiClassField, "=", $this->class->getShortName()); - } - return $builder; - } + return $query; + } - public function newFromBuilder($attributes = array(), $connection = null) - { - if ($this->useSti() && $attributes->{$this->stiClassField}) - { - $class = $this->class->getName(); - $instance = new $class; - $instance->exists = true; - $instance->setRawAttributes((array) $attributes, true); - return $instance; - } - else - { - return parent::newFromBuilder($attributes, $connection); - } - } + public function __construct($attributes = array()) + { + parent::__construct($attributes); + $this->class = new ReflectionClass(get_class($this)); + if ($this->useSti()) { + $this->setAttribute($this->stiClassField, $this->class->getName()); + } + } + + public function toArray() + { + $values = parent::toArray(); + + if (count($this->array_mappings)) { + $new_values = array(); + foreach ($this->array_mappings as $old_key => $new_key) { + $value = isset($values[$old_key])? $values[$old_key] : + ( + isset($values['pivot'])? ( + isset($values['pivot'][$old_key]) ? $values['pivot'][$old_key] : null + ): null + ); + + $new_key = preg_split('/:/',$new_key); + if(count($new_key) > 1) + { + //we have a formatter ... + switch(strtolower($new_key[1])) + { + case 'datetime_epoch': + { + $datetime = new \DateTime($value); + $value = $datetime->getTimestamp(); + } + break; + case 'json_string': + { + $value = JsonUtils::toJsonString($value); + } + break; + case 'json_boolean': + { + $value = JsonUtils::toJsonBoolean($value); + } + break; + case 'json_int': + { + $value = JsonUtils::toJsonInt($value); + } + break; + case 'json_float': + { + $value = JsonUtils::toJsonFloat($value); + } + break; + } + } + $new_values[$new_key[0]] = $value; + } + $values = $new_values; + } + + return $values; + } + + private function useSti() + { + return ($this->stiClassField && $this->stiBaseClass); + } + + private function useMti() + { + return $this->mtiClassType; + } + + public function newQuery($excludeDeleted = true) + { + $builder = parent::newQuery($excludeDeleted); + // If I am using STI, and I am not the base class, + // then filter on the class name. + if ($this->useMti()) { + $query = $builder->getQuery(); + $class = $this->class->getName(); + $parents = $this->get_class_lineage(new $class); + $base_table_set = false; + $current_class_name = null; + if ($this->mtiClassType === 'concrete') { + $current_class_name = $this->class->getShortName(); + $query = $query->from($current_class_name); + $base_table_set = true; + } + + foreach ($parents as $parent) { + + if(!$this->isAllowedParent($parent)) + { + continue; + } + + $parent = new $parent; + if ($parent->mtiClassType === 'abstract') { + continue; + } + + $table_name = $parent->class->getShortName(); + + if ($base_table_set === true) { + $query->leftJoin($table_name, $current_class_name . '.ID', '=', $table_name . '.ID'); + } else { + $query = $query->from($table_name); + $base_table_set = true; + $current_class_name = $table_name; + } + } + + } else { + if ($this->useSti() && get_class(new $this->stiBaseClass) !== get_class($this)) { + $builder->where($this->stiClassField, "=", $this->class->getShortName()); + } + } + + return $builder; + } + + protected function isAllowedParent($parent_name) + { + $res = str_contains($parent_name, $this->class->getShortName()) || + str_contains($parent_name,'Illuminate\Database\Eloquent\Model') || + str_contains($parent_name, 'models\utils\BaseModelEloquent'); + return !$res; + } + + private function get_class_lineage($object) + { + $class_name = get_class($object); + $parents = array_values(class_parents($class_name)); + + return array_merge(array($class_name), $parents); + } + + public function newFromBuilder($attributes = array(), $connection = null) + { + if ($this->useSti() && $attributes->{$this->stiClassField}) { + $class = $this->class->getName(); + $instance = new $class; + $instance->exists = true; + $instance->setRawAttributes((array)$attributes, true); + + return $instance; + } else { + return parent::newFromBuilder($attributes, $connection); + } + } } \ No newline at end of file diff --git a/app/Models/Utils/EloquentBaseRepository.php b/app/Models/Utils/EloquentBaseRepository.php new file mode 100644 index 00000000..9527e6ca --- /dev/null +++ b/app/Models/Utils/EloquentBaseRepository.php @@ -0,0 +1,62 @@ +entity->find($id); + } + + /** + * @param IEntity $entity + * @return void + */ + public function add($entity) + { + $entity->save(); + } + + + /** + * @param IEntity $entity + * @return void + */ + public function delete($entity) + { + $entity->delete(); + } + + /** + * @return IEntity[] + */ + public function getAll() + { + return $this->entity->all()->all(); + } +} \ No newline at end of file diff --git a/app/Models/Utils/IBaseRepository.php b/app/Models/Utils/IBaseRepository.php index 9943057b..ce62d984 100644 --- a/app/Models/Utils/IBaseRepository.php +++ b/app/Models/Utils/IBaseRepository.php @@ -1,24 +1,31 @@ ClassName = $this->table; + } + + /** + * @return int + */ + public function getIdentifier() + { + return (int)$this->ID; + } +} \ No newline at end of file diff --git a/app/Models/exceptions/EntityNotFoundException.php b/app/Models/exceptions/EntityNotFoundException.php new file mode 100644 index 00000000..f486d7ed --- /dev/null +++ b/app/Models/exceptions/EntityNotFoundException.php @@ -0,0 +1,19 @@ + 'id:json_int', + 'Name' => 'name:json_string', + ); + +} \ No newline at end of file diff --git a/app/Models/main/File.php b/app/Models/main/File.php new file mode 100644 index 00000000..740af437 --- /dev/null +++ b/app/Models/main/File.php @@ -0,0 +1,48 @@ + 'id:json_int', + 'Name' => 'name:json_string', + 'Title' => 'description:json_string', + 'Filename' => 'file_name:json_string', + 'Content' => 'content:json_string', + 'ClassName' => 'class_name', + ); + + /** + * @return int + */ + public function getIdentifier() + { + return (int)$this->ID; + } +} \ No newline at end of file diff --git a/app/Models/main/Image.php b/app/Models/main/Image.php new file mode 100644 index 00000000..b710fd15 --- /dev/null +++ b/app/Models/main/Image.php @@ -0,0 +1,26 @@ + 'id:json_int', + 'FirstName' => 'first_name:json_string', + 'Surname' => 'last_name:json_string', + 'Email' => 'email:datetime_epoch', + ); + + /** + * @return Image + */ + public function photo() + { + return $this->hasOne('models\main\Image', 'ID', 'PhotoID')->first(); + } +} \ No newline at end of file diff --git a/app/Models/main/Tag.php b/app/Models/main/Tag.php new file mode 100644 index 00000000..fb1f5bef --- /dev/null +++ b/app/Models/main/Tag.php @@ -0,0 +1,33 @@ + 'id:json_int', + 'Tag' => 'tag:json_string', + ); + +} \ No newline at end of file diff --git a/app/Models/marketplace/CompanyService.php b/app/Models/marketplace/CompanyService.php new file mode 100644 index 00000000..16334009 --- /dev/null +++ b/app/Models/marketplace/CompanyService.php @@ -0,0 +1,39 @@ +ID; + } +} \ No newline at end of file diff --git a/app/Models/marketplace/Consultant.php b/app/Models/marketplace/Consultant.php new file mode 100644 index 00000000..6e304cdb --- /dev/null +++ b/app/Models/marketplace/Consultant.php @@ -0,0 +1,29 @@ +hasMany('models\marketplace\Office', 'ConsultantID', 'ID')->get(); + } +} \ No newline at end of file diff --git a/app/Models/Marketplace/DataCenterLocation.php b/app/Models/marketplace/DataCenterLocation.php similarity index 100% rename from app/Models/Marketplace/DataCenterLocation.php rename to app/Models/marketplace/DataCenterLocation.php diff --git a/app/Models/Marketplace/DataCenterRegion.php b/app/Models/marketplace/DataCenterRegion.php similarity index 100% rename from app/Models/Marketplace/DataCenterRegion.php rename to app/Models/marketplace/DataCenterRegion.php diff --git a/app/Models/Marketplace/ICloudService.php b/app/Models/marketplace/ICloudService.php similarity index 100% rename from app/Models/Marketplace/ICloudService.php rename to app/Models/marketplace/ICloudService.php diff --git a/app/Models/Marketplace/ICloudServiceRepository.php b/app/Models/marketplace/ICloudServiceRepository.php similarity index 100% rename from app/Models/Marketplace/ICloudServiceRepository.php rename to app/Models/marketplace/ICloudServiceRepository.php diff --git a/app/Models/marketplace/ICompanyServiceRepository.php b/app/Models/marketplace/ICompanyServiceRepository.php new file mode 100644 index 00000000..a3dccdc8 --- /dev/null +++ b/app/Models/marketplace/ICompanyServiceRepository.php @@ -0,0 +1,47 @@ +hasMany('models\marketplace\DataCenterRegion', 'CloudServiceID', 'ID')->get(); + } +} \ No newline at end of file diff --git a/app/Models/oauth2/AccessToken.php b/app/Models/oauth2/AccessToken.php index 434612b9..d647bc30 100644 --- a/app/Models/oauth2/AccessToken.php +++ b/app/Models/oauth2/AccessToken.php @@ -1,120 +1,143 @@ value = $value; - $instance->scope = $scope; - $instance->client_id = $client_id; - $instance->user_id = $user_id; - $instance->auth_code = null; - $instance->audience = $audience; - $instance->refresh_token = null; - $instance->lifetime = intval($lifetime); - $instance->is_hashed = false; - $instance->allowed_return_uris = $allowed_return_uris; - $instance->application_type = $application_type; - $instance->allowed_origins = $allowed_origins; - return $instance; - } + /** + * @param $value + * @param $scope + * @param $client_id + * @param $audience + * @param $user_id + * @param $user_external_id + * @param $lifetime + * @param $application_type + * @param $allowed_return_uris + * @param $allowed_origins + * @return AccessToken + */ + public static function createFromParams( + $value, + $scope, + $client_id, + $audience, + $user_id, + $user_external_id, + $lifetime, + $application_type, + $allowed_return_uris, + $allowed_origins + ) { + $instance = new self(); + $instance->value = $value; + $instance->scope = $scope; + $instance->client_id = $client_id; + $instance->user_id = $user_id; + $instance->user_external_id = $user_external_id; + $instance->auth_code = null; + $instance->audience = $audience; + $instance->refresh_token = null; + $instance->lifetime = intval($lifetime); + $instance->is_hashed = false; + $instance->allowed_return_uris = $allowed_return_uris; + $instance->application_type = $application_type; + $instance->allowed_origins = $allowed_origins; - public function getAuthCode() - { - return $this->auth_code; - } + return $instance; + } - public function getRefreshToken() - { - return $this->refresh_token; - } + public function getAuthCode() + { + return $this->auth_code; + } - public function getApplicationType() - { - return $this->application_type; - } + public function getRefreshToken() + { + return $this->refresh_token; + } - public function getAllowedOrigins() - { - return $this->allowed_origins; - } + public function getApplicationType() + { + return $this->application_type; + } - public function getAllowedReturnUris() - { - return $this->allowed_return_uris; - } + public function getAllowedOrigins() + { + return $this->allowed_origins; + } - public function toJSON() - { - return '{}'; - } + public function getAllowedReturnUris() + { + return $this->allowed_return_uris; + } - public function fromJSON($json) - { + /** + * @return int|null + */ + public function getUserExternalId() + { + return $this->user_external_id; + } - } + public function toJSON() + { + return '{}'; + } + + public function fromJSON($json) + { + + } } \ No newline at end of file diff --git a/app/Models/oauth2/IResourceServerContext.php b/app/Models/oauth2/IResourceServerContext.php index 69672dde..e3d2725b 100644 --- a/app/Models/oauth2/IResourceServerContext.php +++ b/app/Models/oauth2/IResourceServerContext.php @@ -1,58 +1,69 @@ auth_context['scope'])? explode(' ', $this->auth_context['scope']):array(); - } + /** + * @return array + */ + public function getCurrentScope() + { + return isset($this->auth_context['scope']) ? explode(' ', $this->auth_context['scope']) : array(); + } - /** - * @return null|string - */ - public function getCurrentAccessToken() - { - return isset($this->auth_context['access_token'])?$this->auth_context['access_token']:null; - } + /** + * @return null|string + */ + public function getCurrentAccessToken() + { + return isset($this->auth_context['access_token']) ? $this->auth_context['access_token'] : null; + } - /** - * @return null|string - */ - public function getCurrentAccessTokenLifetime() - { - return isset($this->auth_context['expires_in'])?$this->auth_context['expires_in']:null; - } + /** + * @return null|string + */ + public function getCurrentAccessTokenLifetime() + { + return isset($this->auth_context['expires_in']) ? $this->auth_context['expires_in'] : null; + } - /** - * @return null - */ - public function getCurrentClientId() - { - return isset($this->auth_context['client_id'])?$this->auth_context['client_id']:null; - } + /** + * @return null|string + */ + public function getCurrentClientId() + { + return isset($this->auth_context['client_id']) ? $this->auth_context['client_id'] : null; + } - /** - * @return null|int - */ - public function getCurrentUserId() - { - return isset($this->auth_context['user_id'])?intval($this->auth_context['user_id']):null; - } + /** + * @return null|int + */ + public function getCurrentUserId() + { + return isset($this->auth_context['user_id']) ? intval($this->auth_context['user_id']) : null; + } - /** - * @param array $auth_context - * @return void - */ - public function setAuthorizationContext(array $auth_context) - { - $this->auth_context = $auth_context; - } + /** + * @param array $auth_context + * @return void + */ + public function setAuthorizationContext(array $auth_context) + { + $this->auth_context = $auth_context; + } + + /** + * @return int + */ + public function getCurrentUserExternalId() + { + return isset($this->auth_context['user_external_id']) ? intval($this->auth_context['user_external_id']) : null; + } + + /** + * @return string + */ + public function getApplicationType() + { + return isset($this->auth_context['application_type']) ? $this->auth_context['application_type'] : null; + } } \ No newline at end of file diff --git a/app/Models/oauth2/Token.php b/app/Models/oauth2/Token.php index 5b233f95..252024e5 100644 --- a/app/Models/oauth2/Token.php +++ b/app/Models/oauth2/Token.php @@ -1,90 +1,93 @@ len = $len; - $this->is_hashed = false; - } + public function __construct($len = self::DefaultByteLength) + { + $this->len = $len; + $this->is_hashed = false; + } - public function getValue() - { - return $this->value; - } + public function getValue() + { + return $this->value; + } - public function getLifetime() - { - return intval($this->lifetime); - } + public function getLifetime() + { + return intval($this->lifetime); + } - public function getScope() - { - return $this->scope; - } + public function getScope() + { + return $this->scope; + } - public function getClientId() - { - return $this->client_id; - } + public function getClientId() + { + return $this->client_id; + } - public function getAudience() - { - return $this->audience; - } + public function getAudience() + { + return $this->audience; + } - public function getFromIp() - { - return $this->from_ip; - } + public function getFromIp() + { + return $this->from_ip; + } - public function getUserId() - { - return $this->user_id; - } + /** + * @return null|int + */ + public function getUserId() + { + return $this->user_id; + } - public function isHashed() - { - return $this->is_hashed; - } + public function isHashed() + { + return $this->is_hashed; + } - public abstract function toJSON(); + public abstract function toJSON(); - public abstract function fromJSON($json); + public abstract function fromJSON($json); } \ No newline at end of file diff --git a/app/Models/resource_server/AccessTokenService.php b/app/Models/resource_server/AccessTokenService.php new file mode 100644 index 00000000..ecc91f93 --- /dev/null +++ b/app/Models/resource_server/AccessTokenService.php @@ -0,0 +1,199 @@ +cache_service = $cache_service; + } + + /** + * @param string $token_value + * @return AccessToken + * @throws \Exception + */ + public function get($token_value) + { + $token = null; + $cache_lifetime = intval(Config::get('server.access_token_cache_lifetime', 300)); + + if($this->cache_service->exists(md5($token_value).'.revoked')) + { + Log::debug(sprintf('token marked as revoked on cache (%s)',md5($token_value) )); + throw new InvalidGrantTypeException(OAuth2Protocol::OAuth2Protocol_Error_InvalidToken); + } + + $token_info = $this->cache_service->getHash(md5($token_value), array + ( + 'access_token', + 'scope', + 'client_id', + 'audience', + 'user_id', + 'user_external_id', + 'expires_in', + 'application_type', + 'allowed_return_uris', + 'allowed_origins' + )); + + if (count($token_info) === 0) + { + Log::debug("getting token from remote call ..."); + $token_info = $this->makeRemoteCall($token_value); + $this->cache_service->storeHash(md5($token_value), $token_info, $cache_lifetime ); + } + else + { + $cache_remaining_lifetime = intval($this->cache_service->ttl(md5($token_value))); + $expires_in = intval($token_info['expires_in']); + $token_info['expires_in'] = $expires_in - ( $cache_lifetime - $cache_remaining_lifetime); + Log::debug + ( + sprintf + ( + "original token life time %s - current token life time %s - token cache remaining lifetime %s", + $expires_in, + $token_info['expires_in'], + $cache_remaining_lifetime + ) + ); + } + + $token = AccessToken::createFromParams + ( + $token_info['access_token'], + $token_info['scope'], + $token_info['client_id'], + $token_info['audience'], + isset($token_info['user_id'])? intval($token_info['user_id']):null, + isset($token_info['user_external_id'])? intval($token_info['user_external_id']) : null, + (int)$token_info['expires_in'], + $token_info['application_type'], + isset($token_info['allowed_return_uris']) ? $token_info['allowed_return_uris'] : null, + isset($token_info['allowed_origins']) ? $token_info['allowed_origins'] : null + ); + + $str_token_info = ""; + foreach($token_info as $k => $v){ + $str_token_info .= sprintf("-%s=%s-", $k, $v); + } + Log::debug("token info : ". $str_token_info); + if($token->getLifetime() <= 0) + { + Log::debug("token lifetime is < 0 ... retrieving from IDP"); + $this->cache_service->delete(md5($token_value)); + $token = $this->get($token_value); + } + return $token; + } + + /** + * @param $token_value + * @return mixed + * @throws ConfigurationException + * @throws InvalidGrantTypeException + * @throws OAuth2InvalidIntrospectionResponse + * @throws \Exception + */ + private function makeRemoteCall($token_value) + { + + try { + $client = new Client([ + 'defaults' => [ + 'timeout' => Config::get('curl.timeout', 60), + 'allow_redirects' => Config::get('curl.allow_redirects', false), + 'verify' => Config::get('curl.verify_ssl_cert', true) + ] + ]); + + $client_id = Config::get('app.openstackid_client_id', ''); + $client_secret = Config::get('app.openstackid_client_secret', ''); + $auth_server_url = Config::get('app.openstackid_base_url', ''); + + if (empty($client_id)) { + throw new ConfigurationException('app.openstackid_client_id param is missing!'); + } + + if (empty($client_secret)) { + throw new ConfigurationException('app.openstackid_client_secret param is missing!'); + } + + if (empty($auth_server_url)) { + throw new ConfigurationException('app.openstackid_base_url param is missing!'); + } + + $response = $client->post( + $auth_server_url . '/oauth2/token/introspection', + [ + 'query' => ['token' => $token_value], + 'headers' => ['Authorization' => " Basic " . base64_encode($client_id . ':' . $client_secret)] + ] + ); + + $content_type = $response->getHeader('content-type'); + if(!str_contains($content_type, 'application/json')) + { + // invalid content type + throw new \Exception($response->getBody()); + } + $token_info = $response->json(); + + return $token_info; + + } catch (RequestException $ex) + { + Log::error($ex->getMessage()); + $response = $ex->getResponse(); + $content_type = $response->getHeader('content-type'); + $is_json = str_contains($content_type, 'application/json'); + $body = ($is_json) ? $response->json(): $response->getBody(); + + $code = $response->getStatusCode(); + if ($code === 400 && $is_json && isset($body['error']) && $body['error'] === OAuth2Protocol::OAuth2Protocol_Error_InvalidToken) + { + $this->cache_service->setSingleValue(md5($token_value).'.revoked', md5($token_value)); + throw new InvalidGrantTypeException($body['error']); + } + throw new OAuth2InvalidIntrospectionResponse(sprintf('http code %s', $ex->getCode())); + } + } +} \ No newline at end of file diff --git a/app/Models/ResourceServer/Api.php b/app/Models/resource_server/Api.php similarity index 100% rename from app/Models/ResourceServer/Api.php rename to app/Models/resource_server/Api.php diff --git a/app/Models/ResourceServer/ApiEndpoint.php b/app/Models/resource_server/ApiEndpoint.php similarity index 96% rename from app/Models/ResourceServer/ApiEndpoint.php rename to app/Models/resource_server/ApiEndpoint.php index 9706f9a3..cf504d7c 100644 --- a/app/Models/ResourceServer/ApiEndpoint.php +++ b/app/Models/resource_server/ApiEndpoint.php @@ -13,6 +13,7 @@ **/ use models\utils\BaseModelEloquent; + /** * Class ApiEndpoint * @package models\resource_server @@ -131,4 +132,12 @@ class ApiEndpoint extends BaseModelEloquent implements IApiEndpoint { return (bool)$this->allow_credentials; } + + /** + * @return int + */ + public function getIdentifier() + { + return (int)$this->id; + } } \ No newline at end of file diff --git a/app/Models/ResourceServer/ApiScope.php b/app/Models/resource_server/ApiScope.php similarity index 100% rename from app/Models/ResourceServer/ApiScope.php rename to app/Models/resource_server/ApiScope.php diff --git a/app/Models/resource_server/IAccessTokenService.php b/app/Models/resource_server/IAccessTokenService.php new file mode 100644 index 00000000..9bd2e583 --- /dev/null +++ b/app/Models/resource_server/IAccessTokenService.php @@ -0,0 +1,31 @@ + 'id:json_int', + 'Title' => 'title:json_string', + 'Description' => 'description:json_string', + 'StartDate' => 'start_date:datetime_epoch', + 'EndDate' => 'end_date:datetime_epoch', + 'LocationID' => 'location_id:json_int', + 'TypeID' => 'type_id:json_int', + 'ClassName' => 'class_name', + 'CategoryID' => 'track_id:json_int', + 'ModeratorID' => 'moderator_speaker_id:json_int', + 'Level' => 'level', + 'AllowFeedBack' => 'allow_feedback:json_boolean', + ); + + /** + * @return PresentationSpeaker[] + */ + public function speakers() + { + return $this->belongsToMany('models\summit\PresentationSpeaker','Presentation_Speakers','PresentationID','PresentationSpeakerID')->get(); + } + + + public function getSpeakerIds() + { + $ids = array(); + foreach($this->speakers() as $speaker) + { + array_push($ids, intval($speaker->ID)); + } + return $ids; + } + + public function setFromSpeaker() + { + $this->from_speaker = true; + } + + /** + * @return array + */ + public function toArray() + { + $values = parent::toArray(); + if(!$this->from_speaker) + $values['speakers'] = $this->getSpeakerIds(); + + $slides = array(); + foreach($this->slides() as $s) + { + array_push($slides, $s->toArray()); + } + $values['slides'] = $slides; + + $videos = array(); + foreach($this->videos() as $v) + { + array_push($videos, $v->toArray()); + } + $values['videos'] = $videos; + + return $values; + } + /** + * @return PresentationVideo[] + */ + public function videos() + { + $bindings = array('presentation_id' => $this->ID); + $rows = DB::connection('ss')->select("select * from `PresentationVideo` left join `PresentationMaterial` on `PresentationVideo`.`ID` = `PresentationMaterial`.`ID` +where `PresentationMaterial`.`PresentationID` = :presentation_id and `PresentationMaterial`.`PresentationID` is not null", $bindings); + + $videos = array(); + foreach($rows as $row) + { + $instance = new PresentationVideo; + $instance->setRawAttributes((array)$row, true); + array_push($videos, $instance); + } + return $videos; + } + + /** + * @return PresentationSlide[] + */ + public function slides() + { + $bindings = array('presentation_id' => $this->ID); + $rows = DB::connection('ss')->select("select * from `PresentationSlide` left join `PresentationMaterial` on `PresentationSlide`.`ID` = `PresentationMaterial`.`ID` +where `PresentationMaterial`.`PresentationID` = :presentation_id and `PresentationMaterial`.`PresentationID` is not null", $bindings); + + $slides = array(); + foreach($rows as $row) + { + $instance = new PresentationSlide; + $instance->setRawAttributes((array)$row, true); + array_push($slides, $instance); + } + return $slides; + } +} diff --git a/app/Models/summit/PresentationCategory.php b/app/Models/summit/PresentationCategory.php new file mode 100644 index 00000000..2643eadf --- /dev/null +++ b/app/Models/summit/PresentationCategory.php @@ -0,0 +1,57 @@ + 'id:json_int', + 'Title' => 'name:json_string', + ); + + + /** + * @return PresentationCategoryGroup[] + */ + public function groups() + { + return $this->belongsToMany('models\summit\PresentationCategoryGroup','PresentationCategoryGroup_Categories','PresentationCategoryID', 'PresentationCategoryGroupID')->get(); + } + + /** + * @return array + */ + public function toArray() + { + $values = parent::toArray(); + $groups = array(); + foreach($this->groups() as $g) + { + array_push($groups, intval($g->ID)); + } + $values['track_groups'] = $groups; + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/PresentationCategoryGroup.php b/app/Models/summit/PresentationCategoryGroup.php new file mode 100644 index 00000000..25e94ee1 --- /dev/null +++ b/app/Models/summit/PresentationCategoryGroup.php @@ -0,0 +1,67 @@ + 'id:json_int', + 'Name' => 'name:json_string', + 'Color' => 'color:json_string', + 'Description' => 'description:json_string', + ); + + + /** + * @return PresentationCategory[] + */ + public function categories() + { + return $this->belongsToMany('models\summit\PresentationCategory','PresentationCategoryGroup_Categories','PresentationCategoryGroupID','PresentationCategoryID')->get(); + } + + /** + * @return array + */ + public function toArray() + { + $values = parent::toArray(); + + $color = isset($values['color']) ? $values['color']:''; + if(empty($color)) + $color = 'f0f0ee'; + if (strpos($color,'#') === false) { + $color = '#'.$color; + } + $values['color'] = $color; + $categories = array(); + foreach($this->categories() as $c) + { + array_push($categories, intval($c->ID)); + } + $values['tracks'] = $categories; + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/PresentationMaterial.php b/app/Models/summit/PresentationMaterial.php new file mode 100644 index 00000000..ad6db3ed --- /dev/null +++ b/app/Models/summit/PresentationMaterial.php @@ -0,0 +1,41 @@ + 'id:json_int', + 'Name' => 'name:json_text', + 'Description' => 'description:json_text', + 'DisplayOnSite' => 'display_on_site:json_boolean', + 'Featured' => 'featured:json_boolean', + 'PresentationID' => 'presentation_id:json_int', + ); + +} \ No newline at end of file diff --git a/app/Models/summit/PresentationSlide.php b/app/Models/summit/PresentationSlide.php new file mode 100644 index 00000000..11614f46 --- /dev/null +++ b/app/Models/summit/PresentationSlide.php @@ -0,0 +1,59 @@ + 'id:json_int', + 'Name' => 'name:json_text', + 'Description' => 'description:json_text', + 'DisplayOnSite' => 'display_on_site:json_boolean', + 'Featured' => 'featured:json_boolean', + 'PresentationID' => 'presentation_id:json_int', + 'Link' => 'link:json_text', + ); + + /** + * @return Image + */ + public function slide() + { + return $this->hasOne('models\main\Image', 'ID', 'SlideID')->first(); + } + + public function toArray() + { + $values = parent::toArray(); + $slide = $this->slide(); + if(!is_null($slide)) + { + $values['link'] = Config::get("server.assets_base_url", 'https://www.openstack.org/'). $slide->Filename; + } + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/PresentationSpeaker.php b/app/Models/summit/PresentationSpeaker.php new file mode 100644 index 00000000..c58469c5 --- /dev/null +++ b/app/Models/summit/PresentationSpeaker.php @@ -0,0 +1,99 @@ + 'id:json_int', + 'FirstName' => 'first_name:json_string', + 'LastName' => 'last_name:json_string', + 'Title' => 'title:json_string', + 'Bio' => 'bio:json_string', + 'IRCHandle' => 'irc', + 'TwitterHandle' => 'twitter', + 'MemberID' => 'member_id:json_int', + ); + + /** + * @return Presentation[] + */ + public function presentations() + { + return $this->belongsToMany('models\summit\Presentation','Presentation_Speakers','PresentationSpeakerID','PresentationID')->get(); + } + + public function getPresentationIds() + { + $ids = array(); + foreach($this->presentations() as $p) + { + array_push($ids, intval($p->ID)); + } + return $ids; + } + + /** + * @return Image + */ + public function photo() + { + return $this->hasOne('models\main\Image', 'ID', 'PhotoID')->first(); + } + + /** + * @return Member + */ + public function member() + { + return $this->hasOne('models\main\Member', 'ID', 'MemberID')->first(); + } + + public function toArray() + { + $values = parent::toArray(); + $values['presentations'] = $this->getPresentationIds(); + $member = $this->member(); + $values['pic'] = Config::get("server.assets_base_url", 'https://www.openstack.org/'). 'profile_images/speakers/'. $this->ID; + if(!is_null($member)) + { + $values['gender'] = $member->Gender; + } + return $values; + } + + + /** + * @param int $presentation_id + * @return Presentation + */ + public function getPresentation($presentation_id) + { + return $this->belongsToMany('models\summit\Presentation','Presentation_Speakers','PresentationSpeakerID', 'PresentationID') + ->where('PresentationID','=',$presentation_id) + ->first(); + } +} \ No newline at end of file diff --git a/app/Models/summit/PresentationVideo.php b/app/Models/summit/PresentationVideo.php new file mode 100644 index 00000000..b74d468b --- /dev/null +++ b/app/Models/summit/PresentationVideo.php @@ -0,0 +1,38 @@ + 'id:json_int', + 'Name' => 'name:json_text', + 'Description' => 'description:json_text', + 'DisplayOnSite' => 'display_on_site:json_boolean', + 'Featured' => 'featured:json_boolean', + 'PresentationID' => 'presentation_id:json_int', + 'YouTubeID' => 'youtube_id:json_text', + ); + +} \ No newline at end of file diff --git a/app/Models/summit/Summit.php b/app/Models/summit/Summit.php new file mode 100644 index 00000000..b5fbc95a --- /dev/null +++ b/app/Models/summit/Summit.php @@ -0,0 +1,490 @@ + 'id:json_int', + 'Name' => 'name:json_string', + 'SummitBeginDate' => 'start_date:datetime_epoch', + 'SummitEndDate' => 'end_date:datetime_epoch', + 'StartShowingVenuesDate' => 'start_showing_venues_date:datetime_epoch', + 'Active' => 'active:json_boolean', + ); + + protected $hidden = array + ( + + ); + + /** + * @return SummitAbstractLocation[] + */ + public function locations() + { + $res = $this->hasMany('models\summit\SummitAbstractLocation', 'SummitID', 'ID')->get(); + $locations = array(); + foreach($res as $l) + { + + $class = 'models\\summit\\'.$l->ClassName; + $entity = $class::find($l->ID); + array_push($locations, $entity); + } + return $locations; + } + + /** + * @return Image + */ + public function logo() + { + return $this->hasOne('models\main\Image', 'ID', 'LogoID')->first(); + } + + /** + * @param int $location_id + * @return SummitAbstractLocation + */ + public function getLocation($location_id) + { + $location = $this->hasMany('models\summit\SummitAbstractLocation', 'SummitID', 'ID')->where('SummitAbstractLocation.ID', '=', $location_id)->get()->first(); + if(!is_null($location)) + { + $class = 'models\\summit\\'.$location->ClassName; + $location = $class::find($location->ID); + } + return $location; + } + + /** + * @return SummitEventType[] + */ + public function event_types() + { + return $this->hasMany('models\summit\SummitEventType', 'SummitID', 'ID')->get(); + } + + /** + * @param int $event_type_id + * @return SummitEventType + */ + public function getEventType($event_type_id) + { + return $this->hasMany('models\summit\SummitEventType', 'SummitID', 'ID')->where('ID','=', intval($event_type_id))->first(); + } + + /** + * @return SummitType[] + */ + public function summit_types() + { + return $this->hasMany('models\summit\SummitType', 'SummitID', 'ID')->get(); + } + + /** + * @param int $summit_type_id + * @return SummitType + */ + public function getSummitType($summit_type_id) + { + return $this->hasMany('models\summit\SummitType', 'SummitID', 'ID')->where('ID','=', intval($summit_type_id))->first(); + } + + /** + * @return SummitTicketType[] + */ + public function ticket_types() + { + return $this->hasMany('models\summit\SummitTicketType', 'SummitID', 'ID')->get(); + } + + /** + * @param int $page + * @param int $per_page + * @param Filter|null $filter + * @param Order|null $order + * @return array + */ + public function attendees($page = 1, $per_page = 100, Filter $filter = null, Order $order = null) + { + $rel = $this->hasMany('models\summit\SummitAttendee', 'SummitID', 'ID')->join('Member', 'Member.ID', '=', 'SummitAttendee.MemberID'); + + if(!is_null($filter)) + { + $filter->apply2Relation($rel, array + ( + 'first_name' => 'Member.FirstName', + 'last_name' => 'Member.Surname', + 'email' => 'Member.Email', + )); + } + + if(!is_null($order)) + { + $order->apply2Relation($rel, array + ( + 'first_name' => 'Member.FirstName', + 'last_name' => 'Member.Surname', + )); + } + + $pagination_result = $rel->paginate($per_page); + $total = $pagination_result->total(); + $items = $pagination_result->items(); + $per_page = $pagination_result->perPage(); + $current_page = $pagination_result->currentPage(); + $last_page = $pagination_result->lastPage(); + + return array ($total,$per_page, $current_page, $last_page, $items); + } + /** + * @param int $page + * @param int $per_page + * @param Filter|null $filter + * @return array + */ + public function schedule($page = 1, $per_page = 100, Filter $filter = null) + { + $rel = $this->hasMany('models\summit\SummitEvent', 'SummitID', 'ID') + ->where('Published','=','1'); + + if(!is_null($filter)) + { + $filter->apply2Relation($rel, array + ( + 'title' => 'SummitEvent.Title', + 'start_date' => 'SummitEvent.StartDate:datetime_epoch', + 'end_date' => 'SummitEvent.EndDate:datetime_epoch', + )); + } + $tags = !is_null($filter) ? $filter->getFilter('tags'): null; + if(!is_null($tags)) { + $op = $tags->getOperator(); + $val = $tags->getValue(); + $rel->getBaseQuery()->whereRaw(" EXISTS ( SELECT T.ID FROM Tag T INNER JOIN SummitEvent_Tags ST ON ST.TagID = T.ID WHERE ST.SummitEventID = SummitEvent.ID AND T.Tag {$op} '{$val}' ) "); + } + $rel = $rel->orderBy('StartDate','asc')->orderBy('EndDate','asc'); + + $pagination_result = $rel->paginate($per_page); + $total = $pagination_result->total(); + $items = $pagination_result->items(); + $per_page = $pagination_result->perPage(); + $current_page = $pagination_result->currentPage(); + $last_page = $pagination_result->lastPage(); + $events = array(); + foreach($items as $e) + { + $class = 'models\\summit\\'.$e->ClassName; + $entity = $class::find($e->ID); + array_push($events, $entity); + } + return array($total,$per_page, $current_page, $last_page, $events); + } + + + /** + * @param int $page + * @param int $per_page + * @param Filter|null $filter + * @return array + */ + public function events($page = 1, $per_page = 100, Filter $filter = null) + { + $rel = $this->hasMany('models\summit\SummitEvent', 'SummitID', 'ID'); + + if(!is_null($filter)) + { + $filter->apply2Relation($rel, array + ( + 'title' => 'SummitEvent.Title', + 'start_date' => 'SummitEvent.StartDate:datetime_epoch', + 'end_date' => 'SummitEvent.EndDate:datetime_epoch', + )); + } + $tags = !is_null($filter) ? $filter->getFilter('tags'): null; + if(!is_null($tags)) { + $op = $tags->getOperator(); + $val = $tags->getValue(); + $rel->getBaseQuery()->whereRaw(" EXISTS ( SELECT T.ID FROM Tag T INNER JOIN SummitEvent_Tags ST ON ST.TagID = T.ID WHERE ST.SummitEventID = SummitEvent.ID AND T.Tag {$op} '{$val}' ) "); + } + $rel = $rel->orderBy('StartDate','asc')->orderBy('EndDate','asc'); + + $pagination_result = $rel->paginate($per_page); + $total = $pagination_result->total(); + $items = $pagination_result->items(); + $per_page = $pagination_result->perPage(); + $current_page = $pagination_result->currentPage(); + $last_page = $pagination_result->lastPage(); + $events = array(); + foreach($items as $e) + { + $class = 'models\\summit\\'.$e->ClassName; + $entity = $class::find($e->ID); + array_push($events, $entity); + } + return array($total,$per_page, $current_page, $last_page, $events); + } + + + /** + * @param int $member_id + * @return SummitAttendee + */ + public function getAttendeeByMemberId($member_id) + { + return $this->hasMany('models\summit\SummitAttendee', 'SummitID', 'ID')->where('MemberID','=',$member_id)->first(); + } + + /** + * @param int $attendee_id + * @return SummitAttendee + */ + public function getAttendeeById($attendee_id) + { + return $this->hasMany('models\summit\SummitAttendee', 'SummitID', 'ID')->where('SummitAttendee.ID','=',$attendee_id)->first(); + } + + /** + * @param int $event_id + * @return null|SummitEvent + */ + public function getScheduleEvent($event_id) + { + $e = $this->hasMany('models\summit\SummitEvent', 'SummitID', 'ID') + ->where('SummitEvent.ID','=', intval($event_id)) + ->where('Published','=','1') + ->first(); + if(is_null($e)) return null; + $class = 'models\\summit\\'.$e->ClassName; + return $class::find($e->ID); + } + + /** + * @param int $event_id + * @return null|SummitEvent + */ + public function getEvent($event_id) + { + $e = $this->hasMany('models\summit\SummitEvent', 'SummitID', 'ID') + ->where('SummitEvent.ID','=', intval($event_id)) + ->first(); + if(is_null($e)) return null; + $class = 'models\\summit\\'.$e->ClassName; + return $class::find($e->ID); + } + + /** + * @return PresentationCategory[] + */ + public function presentation_categories() + { + return $this->hasMany('models\summit\PresentationCategory', 'SummitID', 'ID')->get(); + } + + /** + * @return PresentationCategoryGroup[] + */ + public function category_groups() + { + return $this->hasMany('models\summit\PresentationCategoryGroup', 'SummitID', 'ID')->get(); + } + + + /** + * @param int $group_id + * @return null|PresentationCategoryGroup + */ + public function getCategoryGroup($group_id) + { + return $this->hasMany('models\summit\PresentationCategoryGroup', 'SummitID', 'ID') + ->where('PresentationCategoryGroup.ID','=', intval($group_id)) + ->first(); + } + + public function sponsors() + { + $summit_id = $this->ID; + $rows = DB::connection('ss')->select("SELECT DISTINCT C.* FROM SummitEvent_Sponsors S +INNER JOIN SummitEvent E ON E.ID = S.SummitEventID AND E.SummitID = {$summit_id} +INNER JOIN Company C ON C.ID = S.CompanyID"); + + $sponsors = array(); + foreach($rows as $row) + { + $instance = new Company; + $instance->setRawAttributes((array)$row, true); + array_push($sponsors, $instance); + } + return $sponsors; + } + + /** + * @param int $speaker_id + * @return null|PresentationSpeaker + */ + public function getSpeakerById($speaker_id) + { + return $this->hasMany('models\summit\PresentationSpeaker', 'SummitID', 'ID')->where('PresentationSpeaker.ID','=', intval($speaker_id))->first(); + } + + /** + * @param int $member_id + * @return null|PresentationSpeaker + */ + public function getSpeakerByMemberId($member_id) + { + return $this->hasMany('models\summit\PresentationSpeaker', 'SummitID', 'ID')->where('PresentationSpeaker.MemberID','=', intval($member_id))->first(); + } + + /** + * @param int|null $from_id + * @param \DateTime|null $from_date + * @return SummitEntityEvent[] + */ + public function getEntityEvents($from_id = null, \DateTime $from_date = null) + { + $relation = $this->hasMany('models\summit\SummitEntityEvent', 'SummitID', 'ID'); + if(!is_null($from_id)) + { + $relation = $relation->where('SummitEntityEvent.ID','>', intval($from_id)); + } + if(!is_null($from_date)) + { + $relation = $relation->where('SummitEntityEvent.Created','>=', $from_date); + } + return $relation + ->orderBy('Created','asc') + ->get(); + } + + public function toArray() + { + $values = parent::toArray(); + $time_zone_list = timezone_identifiers_list(); + $time_zone_id = $this->TimeZone; + $values['time_zone'] = null; + if(!empty($time_zone_id) && isset($time_zone_list[$time_zone_id])) + { + + $time_zone_name = $time_zone_list[$time_zone_id]; + $time_zone = new \DateTimeZone($time_zone_name); + $time_zone_info = $time_zone->getLocation(); + $time_zone_info['name'] = $time_zone->getName(); + $now = new \DateTime("now", $time_zone); + $time_zone_info['offset'] = $time_zone->getOffset($now); + $values['time_zone'] = $time_zone_info; + } + $values['logo'] = ($this->logo() !== null) ? Config::get("server.assets_base_url", 'https://www.openstack.org/'). $this->logo()->photo()->Filename : null; + if(empty($values['name'])) + { + $values['name'] = $this->Title; + } + return $values; + } + + + /** + * @param $value + * @return null|string + */ + public function convertDateFromTimeZone2UTC($value) + { + $time_zone_id = $this->TimeZone; + if(empty($time_zone_id)) return $value; + $time_zone_list = timezone_identifiers_list(); + + if(isset($time_zone_list[$time_zone_id]) && !empty($value)) + { + $utc_timezone = new \DateTimeZone("UTC"); + $time_zone_name = $time_zone_list[$time_zone_id]; + $time_zone = new \DateTimeZone($time_zone_name); + $date = new \DateTime($value, $time_zone); + $date->setTimezone($utc_timezone); + return $date->format("Y-m-d H:i:s"); + } + return null; + } + + /** + * @param $value + * @return null|string + */ + public function convertDateFromUTC2TimeZone($value) + { + $time_zone_id = $this->TimeZone; + if(empty($time_zone_id)) return $value; + $time_zone_list = timezone_identifiers_list(); + + if(isset($time_zone_list[$time_zone_id]) && !empty($value)) + { + $utc_timezone = new \DateTimeZone("UTC"); + $time_zone_name = $time_zone_list[$time_zone_id]; + $time_zone = new \DateTimeZone($time_zone_name); + $date = new \DateTime($value, $utc_timezone); + + $date->setTimezone($time_zone); + return $date->format("Y-m-d H:i:s"); + } + return null; + } + + /** + * @param SummitEvent $summit_event + * @return bool + */ + public function isEventInsideSummitDuration(SummitEvent $summit_event) + { + $event_start_date = $summit_event->StartDate; + $event_end_date = $summit_event->EndDate; + $summit_start_date = new \DateTime($this->convertDateFromUTC2TimeZone($this->SummitBeginDate)); + $summit_end_date = new \DateTime($this->convertDateFromUTC2TimeZone($this->SummitEndDate)); + + return $event_start_date >= $summit_start_date && $event_start_date <= $summit_end_date && + $event_end_date <= $summit_end_date && $event_end_date >= $event_start_date; + } + + /** + * @return \DateTime + */ + public function getLocalBeginDate() + { + return new \DateTime($this->convertDateFromUTC2TimeZone($this->SummitBeginDate)); + } + + /** + * @return \DateTime + */ + public function getLocalEndDate() + { + return new \DateTime($this->convertDateFromUTC2TimeZone($this->SummitEndDate)); + } + +} \ No newline at end of file diff --git a/app/Models/summit/SummitAbstractLocation.php b/app/Models/summit/SummitAbstractLocation.php new file mode 100644 index 00000000..2188f859 --- /dev/null +++ b/app/Models/summit/SummitAbstractLocation.php @@ -0,0 +1,49 @@ + 'id:json_int', + 'Name' => 'name:json_string', + 'Description' => 'description:json_string', + 'ClassName' => 'class_name', + 'LocationType' => 'location_type', + ); + + /** + * @return int + */ + public function getIdentifier() + { + return (int)$this->ID; + } + +} \ No newline at end of file diff --git a/app/Models/summit/SummitAirport.php b/app/Models/summit/SummitAirport.php new file mode 100644 index 00000000..8107a8ef --- /dev/null +++ b/app/Models/summit/SummitAirport.php @@ -0,0 +1,21 @@ + 'id:json_int', + 'SummitHallCheckedIn' => 'summit_hall_checked_in:json_boolean', + 'SummitHallCheckedInDate' => 'summit_hall_checked_in_date:datetime_epoch', + 'SharedContactInfo' => 'shared_contact_info:json_boolean', + 'MemberID' => 'member_id:json_int', + ); + + /** + * @return SummitEvent[] + */ + public function schedule() + { + $res = $this->belongsToMany + ( + 'models\summit\SummitEvent', + 'SummitAttendee_Schedule', + 'SummitAttendeeID', + 'SummitEventID' + )->withPivot('IsCheckedIn')->get(); + + $events = array(); + foreach($res as $e) + { + $class = 'models\\summit\\'.$e->ClassName; + $entity = $class::find($e->ID); + $entity->attributes['IsCheckedIn'] = $e->pivot->IsCheckedIn; + array_push($events, $entity); + } + return $events; + } + + /** + * @return SummitEventFeedback[] + */ + public function emitted_feedback(){ + return SummitEventFeedback::where('OwnerID', '=', $this->MemberID)->orderBy('ID','asc')->get(); + } + + /** + * @return int[] + */ + public function getScheduleIds() + { + $res = $this->belongsToMany + ( + 'models\summit\SummitEvent', + 'SummitAttendee_Schedule', + 'SummitAttendeeID', + 'SummitEventID' + )->withPivot('IsCheckedIn')->get(); + + $ids = array(); + foreach($res as $e) + { + array_push($ids, intval($e->ID)); + } + return $ids; + } + + public function add2Schedule(SummitEvent $event) + { + if($this->isOnSchedule($event)) throw new ValidationException(sprintf('Event %s already belongs to attendee %s schedule.', $event->ID, $this->ID)); + $this->belongsToMany + ( + 'models\summit\SummitEvent', + 'SummitAttendee_Schedule', + 'SummitAttendeeID', + 'SummitEventID' + )->attach($event->ID,['IsCheckedIn' => false] ); + return true; + } + + public function removeFromSchedule(SummitEvent $event) + { + if(!$this->isOnSchedule($event)) throw new ValidationException(sprintf('Event %s does not belongs to attendee %s schedule.', $event->ID, $this->ID)); + $this->belongsToMany + ( + 'models\summit\SummitEvent', + 'SummitAttendee_Schedule', + 'SummitAttendeeID', + 'SummitEventID' + )->detach($event->ID); + return true; + } + + public function isOnSchedule(SummitEvent $event) + { + return $this->belongsToMany + ( + 'models\summit\SummitEvent', + 'SummitAttendee_Schedule', + 'SummitAttendeeID', + 'SummitEventID' + )->where('SummitEventID', '=', $event->ID)->count() > 0; + } + + public function checkIn(SummitEvent $event) + { + if(!$this->isOnSchedule($event)) throw new ValidationException(sprintf('Event %s does not belongs to attendee %s schedule.', $event->ID, $this->ID)); + $this->belongsToMany + ( + 'models\summit\SummitEvent', + 'SummitAttendee_Schedule', + 'SummitAttendeeID', + 'SummitEventID' + )->withPivot('IsCheckedIn')->updateExistingPivot($event->ID, ['IsCheckedIn' => true]); + return true; + } + + /** + * @return Member + */ + public function member() + { + return $this->hasOne('models\main\Member', 'ID', 'MemberID')->first(); + } + + /** + * @return SummitAttendeeTicket[] + */ + public function tickets() + { + return $this->hasMany('models\summit\SummitAttendeeTicket', 'OwnerID', 'ID')->get(); + } + + public function toArray() + { + $values = parent::toArray(); + $member = $this->member(); + $values['schedule'] = $this->getScheduleIds(); + $tickets = array(); + foreach($this->tickets() as $t) + { + array_push($tickets, intval($t->ticket_type()->ID)); + } + $values['tickets'] = $tickets; + if(!is_null($member)) + { + $values['first_name'] = JsonUtils::toJsonString($member->FirstName); + $values['last_name'] = JsonUtils::toJsonString($member->Surname); + $values['gender'] = $member->Gender; + $values['bio'] = JsonUtils::toJsonString($member->Bio); + $values['pic'] = Config::get("server.assets_base_url", 'https://www.openstack.org/'). 'profile_images/members/'. $member->ID; + $values['linked_in'] = $member->LinkedInProfile; + $values['irc'] = $member->IRCHandle; + $values['twitter'] = $member->TwitterName; + } + return $values; + } + + /** + * @return Summit + */ + public function getSummit() + { + return $this->hasOne('models\summit\Summit', 'ID', 'SummitID')->first(); + } + +} \ No newline at end of file diff --git a/app/Models/summit/SummitAttendeeTicket.php b/app/Models/summit/SummitAttendeeTicket.php new file mode 100644 index 00000000..656db363 --- /dev/null +++ b/app/Models/summit/SummitAttendeeTicket.php @@ -0,0 +1,61 @@ + 'id:json_int', + 'ExternalOrderId' => 'external_order_id:json_int', + 'ExternalAttendeeId' => 'external_attendee_id:json_int', + 'TicketBoughtDate' => 'bought_date:datetime_epoch', + ); + + + /** + * @return SummitTicketType + */ + public function ticket_type() + { + return $this->hasOne('models\summit\SummitTicketType', 'ID', 'TicketTypeID')->first(); + } + + /** + * @return SummitAttendee + */ + public function owner() + { + return $this->hasOne('models\summit\SummitAttendee', 'ID', 'SummitAttendeeID')->first(); + } + + /** + * @return array + */ + public function toArray() + { + $values = parent::toArray(); + $values['ticket_type_id'] = intval($this->ticket_type()->ID); + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitEntityEvent.php b/app/Models/summit/SummitEntityEvent.php new file mode 100644 index 00000000..c5d21863 --- /dev/null +++ b/app/Models/summit/SummitEntityEvent.php @@ -0,0 +1,36 @@ + 'id:json_int', + 'EntityID' => 'entity_id:json_int', + 'EntityClassName' => 'entity_class:json_string', + 'Created' => 'created:datetime_epoch', + 'Type' => 'type', + ); + +} \ No newline at end of file diff --git a/app/Models/summit/SummitEvent.php b/app/Models/summit/SummitEvent.php new file mode 100644 index 00000000..57461b19 --- /dev/null +++ b/app/Models/summit/SummitEvent.php @@ -0,0 +1,455 @@ + 'id:json_int', + 'Title' => 'title:json_string', + 'Description' => 'description:json_string', + 'StartDate' => 'start_date:datetime_epoch', + 'EndDate' => 'end_date:datetime_epoch', + 'LocationID' => 'location_id:json_int', + 'TypeID' => 'type_id:json_int', + 'ClassName' => 'class_name', + 'AllowFeedBack' => 'allow_feedback:json_boolean', + 'AvgFeedbackRate' => 'avg_feedback_rate:json_float', + 'Published' => 'is_published:json_boolean', + ); + + /** + * @param string $title + * @return $this + */ + public function setTitle($title) + { + $this->Title = $title; + return $this; + } + + /** + * @param string $description + * @return $this + */ + public function setDescription($description) + { + $this->Description = $description; + return $this; + } + + /** + * @param \DateTime $value + * @return $this + */ + public function setStartDateAttribute(\DateTime $value) + { + $summit = $this->getSummit(); + if(!is_null($summit)) + { + $value = new \DateTime($summit->convertDateFromTimeZone2UTC($value->format('Y-m-d H:i:s'))); + } + $this->attributes['StartDate'] = $value->format('Y-m-d H:i:s'); + return $this; + } + + /** + * @return \DateTime|null + */ + public function getStartDateAttribute($value) + { + if(!empty($value)) { + $res = new \DateTime($value); + $summit = $this->getSummit(); + if(!is_null($summit)) + { + $res = new \DateTime($summit->convertDateFromUTC2TimeZone($value)); + } + return $res; + } + return null; + } + + /** + * @return \DateTime|null + */ + public function getStartDateUTCAttribute($value) + { + $value = $this->attributes['StartDate']; + if(!empty($value)) { + return new \DateTime($value); + } + return null; + } + + /** + * @param \DateTime $value + * @return $this + */ + public function setEndDateAttribute(\DateTime $value) + { + $summit = $this->getSummit(); + if(!is_null($summit)) + { + $value = new \DateTime($summit->convertDateFromTimeZone2UTC($value->format('Y-m-d H:i:s'))); + } + $this->attributes['EndDate'] = $value->format('Y-m-d H:i:s'); + return $this; + } + + /** + * @return \DateTime|null + */ + public function getEndDateAttribute($value) + { + if(!empty($value)) { + $res = new \DateTime($value); + $summit = $this->getSummit(); + if(!is_null($summit)) + { + $res = new \DateTime($summit->convertDateFromUTC2TimeZone($value)); + } + return $res; + } + return null; + } + + /** + * @return \DateTime|null + */ + public function getEndDateUTCAttribute($value) + { + $value = $this->attributes['EndDate']; + if(!empty($value)) { + return new \DateTime($value); + } + return null; + } + + /** + * @param bool $allow_feeback + * @return $this + */ + public function setAllowFeedBack($allow_feeback) + { + $this->AllowFeedBack = $allow_feeback; + return $this; + } + + /** + * @param SummitEventType $type + * @return $this + */ + public function setType(SummitEventType $type) + { + $this->TypeID = $type->ID; + return $this; + } + + /** + * @param SummitAbstractLocation $location + * @return $this + */ + public function setLocation(SummitAbstractLocation $location) + { + $this->LocationID = $location->ID; + return $this; + } + + /** + * @return SummitAbstractLocation + */ + public function getLocation() + { + return $this->hasOne('models\summit\SummitAbstractLocation', 'ID', 'LocationID')->first(); + } + + /** + * @param Summit $summit + * @return $this + */ + public function setSummit(Summit $summit) + { + $this->SummitID = $summit->ID; + return $this; + } + + /** + * @return array + */ + public function getSummitTypesIds() + { + $ids = array(); + foreach($this->summit_types() as $type) + { + array_push($ids, intval($type->ID)); + } + return $ids; + } + + /** + * @return array + */ + public function getSponsorsIds() + { + $ids = array(); + foreach($this->sponsors() as $company) + { + array_push($ids, intval($company->ID)); + } + return $ids; + } + + /** + * @return SummitType[] + */ + public function summit_types() + { + return $this->belongsToMany('models\summit\SummitType','SummitEvent_AllowedSummitTypes', 'SummitEventID','SummitTypeID')->get(); + } + + /** + * @param SummitType $summit_type + */ + public function addSummitType(SummitType $summit_type) + { + $this->belongsToMany('models\summit\SummitType','SummitEvent_AllowedSummitTypes', 'SummitEventID','SummitTypeID')->attach($summit_type->ID); + } + + public function clearSummitTypes() + { + $this->belongsToMany('models\summit\SummitType','SummitEvent_AllowedSummitTypes', 'SummitEventID','SummitTypeID')->detach(); + } + + /** + * @return Company[] + */ + public function sponsors() + { + return $this->belongsToMany('models\main\Company','SummitEvent_Sponsors','SummitEventID', 'CompanyID')->get(); + } + + /** + * @return SummitEventType + */ + public function getType() + { + return $this->hasOne('models\summit\SummitEventType', 'ID', 'TypeID')->first(); + } + + /** + * @return Summit + */ + public function getSummit() + { + return $this->hasOne('models\summit\Summit', 'ID', 'SummitID')->first(); + } + + /** + * @return SummitAttendee[] + */ + public function attendees() + { + return $this->belongsToMany('models\summit\SummitAttendee','SummitAttendee_Schedule','SummitEventID', 'SummitAttendeeID') + ->where('IsCheckedIn','=',1) + ->get(); + } + + public function toArray() + { + $values = parent::toArray(); + $values['summit_types'] = $this->getSummitTypesIds(); + $values['sponsors'] = $this->getSponsorsIds(); + $tags = array(); + foreach($this->tags() as $t) + { + array_push($tags, $t->toArray()); + } + $values['tags'] = $tags; + return $values; + } + + public function setFromAttendee() + { + $this->from_attendee = true; + $this->array_mappings['IsCheckedIn'] = 'is_checked_in:json_boolean'; + } + + /** + * @param int $page + * @param int $per_page + * @param Filter|null $filter + * @param Order|null $order + * @return array + */ + public function feedback($page = 1, $per_page = 100, Filter $filter = null, Order $order = null) + { + $rel = $this->hasMany('models\summit\SummitEventFeedback', 'EventID', 'ID')->where('ClassName','=','SummitEventFeedback'); + + if(!is_null($filter)) + { + $filter->apply2Relation($rel, array + ( + 'owner_id' => 'SummitEventFeedback.OwnerID', + )); + } + + if(!is_null($order)) + { + $order->apply2Relation($rel, array + ( + 'created_date' => 'SummitEventFeedback.Created', + 'owner_id' => 'SummitEventFeedback.OwnerID', + 'rate' => 'SummitEventFeedback.Rate', + 'id' => 'SummitEventFeedback.ID', + )); + } + else + { + //default order + $rel = $rel->orderBy('SummitEventFeedback.Created', 'DESC'); + } + + $pagination_result = $rel->paginate($per_page); + $total = $pagination_result->total(); + $items = $pagination_result->items(); + $per_page = $pagination_result->perPage(); + $current_page = $pagination_result->currentPage(); + $last_page = $pagination_result->lastPage(); + + $feedback = array(); + foreach($items as $e) + { + $class = 'models\\summit\\'.$e->ClassName; + $entity = $class::find($e->ID); + array_push($feedback, $entity); + } + return array($total,$per_page, $current_page, $last_page, $feedback); + } + + public function addFeedBack(SummitEventFeedback $feedback) + { + $this->hasMany('models\summit\SummitEventFeedback', 'EventID', 'ID')->where('ClassName','=','SummitEventFeedback')->save($feedback); + } + + /** + * @return Tag[] + */ + public function tags() + { + return $this->belongsToMany('models\main\Tag','SummitEvent_Tags','SummitEventID','TagID')->get(); + } + + /** + * @param string $tag + */ + public function addTag($tag) + { + $t = Tag::where('Tag','=', trim($tag))->first(); + if(is_null($t)) + { + $t = new Tag; + $t->Tag = trim($tag); + $t->save(); + } + + $this->belongsToMany('models\main\Tag','SummitEvent_Tags','SummitEventID','TagID')->attach($t->ID); + } + + public function clearTags() + { + $this->belongsToMany('models\main\Tag','SummitEvent_Tags','SummitEventID','TagID')->detach(); + } + + public function publish() + { + if($this->Published) + throw new ValidationException('Already published Summit Event'); + + if(count($this->summit_types()) === 0) + throw new EntityValidationException('To publish this event you must associate a valid summit type!'); + + $start_date = $this->StartDate; + $end_date = $this->EndDate; + + if((is_null($start_date) || is_null($end_date))) + throw new ValidationException('To publish this event you must define a start/end datetime!'); + + $summit = $this->getSummit(); + + if(is_null($summit)) + throw new ValidationException('To publish you must assign a summit'); + + $timezone = $summit->TimeZone; + if(empty($timezone)){ + throw new ValidationException('Invalid Summit TimeZone!'); + } + if($end_date < $start_date) + throw new ValidationException('start datetime must be greather or equal than end datetime!'); + + if(!$summit->isEventInsideSummitDuration($this)) + throw new ValidationException + ( + sprintf + ( + 'start/end datetime must be between summit start/end datetime! (%s - %s)', + $summit->getLocalBeginDate(), + $summit->getLocalEndDate() + ) + ); + + $this->Published = true; + $this->PublishedDate = DateTimeUtils::nowRfc2822(); + } + + /** + * @return bool + */ + public function isPublished() + { + return $this->Published; + } + + /** + * @return void + */ + public function unPublish() + { + $this->Published = false; + $this->PublishedDate = null; + } + +} \ No newline at end of file diff --git a/app/Models/summit/SummitEventFactory.php b/app/Models/summit/SummitEventFactory.php new file mode 100644 index 00000000..7e451745 --- /dev/null +++ b/app/Models/summit/SummitEventFactory.php @@ -0,0 +1,32 @@ +Type === 'Presentation' ? new Presentation: new SummitEvent; + return $event; + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitEventFeedback.php b/app/Models/summit/SummitEventFeedback.php new file mode 100644 index 00000000..470878ea --- /dev/null +++ b/app/Models/summit/SummitEventFeedback.php @@ -0,0 +1,92 @@ + 'id:json_int', + 'Rate' => 'rate:json_int', + 'Note' => 'note:json_string', + 'OwnerID' => 'owner_id:json_int', + 'EventID' => 'event_id:json_int', + 'Created' => 'created_date:datetime_epoch', + ); + + /** + * @return Member + */ + public function owner() + { + return $this->hasOne('models\main\Member', 'ID', 'OwnerID')->first(); + } + + /** + * @return SummitEvent + */ + public function event() + { + return $this->hasOne('models\summit\SummitEvent', 'ID', 'EventID')->first(); + } + + /** + * @param bool|false $show_attendee_info + * @return array + */ + public function toArray($show_attendee_info = false) + { + $data = parent::toArray(); + $member_id = $data['owner_id']; + unset($data['owner_id']); + $attendee = SummitAttendee::where('MemberID', '=', $member_id)->first(); + + if (!is_null($attendee)) + { + + if ($show_attendee_info) + { + + $member = $attendee->member(); + $data['owner'] = array + ( + 'id' => intval($attendee->ID), + 'first_name' => JsonUtils::toJsonString($member->FirstName), + 'last_name' => JsonUtils::toJsonString($member->Surname) + ); + } + else + { + $data['owner_id'] = intval($attendee->ID); + } + } + else + { + $data['member_id'] = intval($member_id); + } + return $data; + } +} diff --git a/app/Models/summit/SummitEventType.php b/app/Models/summit/SummitEventType.php new file mode 100644 index 00000000..4a870750 --- /dev/null +++ b/app/Models/summit/SummitEventType.php @@ -0,0 +1,47 @@ + 'id:json_int', + 'Type' => 'name:json_string', + 'Color' => 'color:json_string', + 'BlackoutTimes' => 'black_out_times:json_boolean', + ); + + public function toArray() + { + $values = parent::toArray(); + $color = isset($values['color']) ? $values['color']:''; + if(empty($color)) + $color = 'f0f0ee'; + if (strpos($color,'#') === false) { + $color = '#'.$color; + } + $values['color'] = $color; + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitExternalLocation.php b/app/Models/summit/SummitExternalLocation.php new file mode 100644 index 00000000..226f5673 --- /dev/null +++ b/app/Models/summit/SummitExternalLocation.php @@ -0,0 +1,23 @@ + 'id:json_int', + 'Name' => 'name:json_string', + 'Description' => 'description:json_string', + 'ClassName' => 'class_name', + 'LocationType' => 'location_type', + 'Address1' => 'address_1:json_string', + 'Address2' => 'address_2:json_string', + 'ZipCode' => 'zip_code', + 'City' => 'city:json_string', + 'State' => 'state:json_string', + 'Country' => 'country:json_string', + 'Lng' => 'lng', + 'Lat' => 'lat', + ); + + /** + * @return SummitLocationMap[] + */ + public function maps() + { + return $this->hasMany('models\summit\SummitLocationMap', 'LocationID', 'ID')->orderBy('Order','ASC')->get(); + } + + /** + * @return array + */ + public function toArray() + { + $values = parent::toArray(); + + $maps = array(); + foreach($this->maps() as $m) + { + array_push($maps, $m->toArray()); + } + $values['maps'] = $maps; + + return $values; + } + +} \ No newline at end of file diff --git a/app/Models/summit/SummitHotel.php b/app/Models/summit/SummitHotel.php new file mode 100644 index 00000000..d9b736cc --- /dev/null +++ b/app/Models/summit/SummitHotel.php @@ -0,0 +1,24 @@ + 'id:json_int', + 'LocationID' => 'location_id:json_int', + 'Name' => 'name:json_text', + 'Description' => 'description:json_text', + ); + + /** + * @return Image + */ + public function map() + { + return $this->hasOne('models\main\Image', 'ID', 'MapID')->first(); + } + + public function toArray() + { + $values = parent::toArray(); + $map = $this->map(); + if(!is_null($map)) + { + $values['image_url'] = Config::get("server.assets_base_url", 'https://www.openstack.org/'). $map->Filename; + } + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitTicketType.php b/app/Models/summit/SummitTicketType.php new file mode 100644 index 00000000..5f6c9e8d --- /dev/null +++ b/app/Models/summit/SummitTicketType.php @@ -0,0 +1,62 @@ + 'id:json_int', + 'Name' => 'name:json_string', + 'Description' => 'description:json_string', + ); + + public function allowed_summit_types() + { + return $this->belongsToMany + ( + 'models\summit\SummitType', + 'SummitTicketType_AllowedSummitTypes', + 'SummitTicketTypeID', + 'SummitTypeID' + )->get(); + } + + + private function getAllowedSummitTypeIds() + { + $ids = array(); + foreach($this->allowed_summit_types() as $type) + { + array_push($ids, intval($type->ID)); + } + return $ids; + } + + public function toArray() + { + $values = parent::toArray(); + $values['allowed_summit_types'] = $this->getAllowedSummitTypeIds(); + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitType.php b/app/Models/summit/SummitType.php new file mode 100644 index 00000000..ebf6751e --- /dev/null +++ b/app/Models/summit/SummitType.php @@ -0,0 +1,47 @@ + 'id:json_int', + 'Title' => 'name:json_string', + 'Color' => 'color:json_string', + 'Type' => 'type:json_string', + ); + + public function toArray() + { + $values = parent::toArray(); + $color = isset($values['color']) ? $values['color']:''; + if(empty($color)) + $color = 'f0f0ee'; + if (strpos($color,'#') === false) { + $color = '#'.$color; + } + $values['color'] = $color; + return $values; + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitVenue.php b/app/Models/summit/SummitVenue.php new file mode 100644 index 00000000..4837fa9a --- /dev/null +++ b/app/Models/summit/SummitVenue.php @@ -0,0 +1,56 @@ +rooms, $room); + } + + public function toArray() + { + $values = parent::toArray(); + + $rooms = array(); + + foreach($this->rooms as $r) + { + array_push($rooms, $r->toArray()); + } + + if(count($rooms) > 0) + $values['rooms'] = $rooms; + + return $values; + } + + /** + * @return SummitVenueRoom[] + */ + public function rooms() + { + return $this->hasMany('models\summit\SummitVenueRoom', 'VenueID', 'ID')->get(); + } +} \ No newline at end of file diff --git a/app/Models/summit/SummitVenueRoom.php b/app/Models/summit/SummitVenueRoom.php new file mode 100644 index 00000000..0a8784d5 --- /dev/null +++ b/app/Models/summit/SummitVenueRoom.php @@ -0,0 +1,34 @@ + 'id:json_int', + 'VenueID' => 'venue_id:json_int', + 'ClassName' => 'class_name', + 'Name' => 'name:json_string', + 'Description' => 'description:json_string', + 'Capacity' => 'Capacity:json_int', + ); +} \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 1c786225..92731fba 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -1,47 +1,96 @@ pushHandler($handler); - } + if (!empty($to) && !empty($from)) { + $subject = 'openstackid-resource-server error'; + $mono_log = Log::getMonolog(); + $handler = new NativeMailerHandler($to, $subject, $from, $level = Logger::WARNING); + $mono_log->pushHandler($handler); + } - } + if(Config::get("server.db_log_enabled", false)) { + Event::listen('illuminate.query', function ($query, $bindings, $time, $name) { + $data = compact('bindings', 'time', 'name'); - /** - * Register any application services. - * - * @return void - */ - public function register() - { - App::singleton('models\\oauth2\\IResourceServerContext', 'models\\oauth2\\ResourceServerContext'); - App::singleton('models\resource_server\\IAccessTokenService', 'models\resource_server\\AccessTokenService'); - App::singleton('models\\resource_server\\IApi', 'models\\resource_server\\Api'); - App::singleton('models\\resource_server\\IApiEndpoint', 'models\\resource_server\\ApiEndpoint'); - App::singleton('models\\resource_server\\IApiScope', 'models\\resource_server\\ApiScope'); - } + // Format binding data for sql insertion + foreach ($bindings as $i => $binding) { + if ($binding instanceof \DateTime) { + $bindings[$i] = $binding->format('\'Y-m-d H:i:s\''); + } else { + if (is_string($binding)) { + $bindings[$i] = "'$binding'"; + } + } + } + + // Insert bindings into query + $query = str_replace(array('%', '?'), array('%%', '%s'), $query); + $query = vsprintf($query, $bindings); + + Log::info($query, $data); + }); + } + + Validator::extend('int_array', function($attribute, $value, $parameters, $validator) + { + $validator->addReplacer('int_array', function($message, $attribute, $rule, $parameters) use ($validator) { + return sprintf("%s should be an array of integers", $attribute); + }); + if(!is_array($value)) return false; + foreach($value as $element) + { + if(!is_int($element)) return false; + } + return true; + }); + + Validator::extend('string_array', function($attribute, $value, $parameters, $validator) + { + $validator->addReplacer('string_array', function($message, $attribute, $rule, $parameters) use ($validator) { + return sprintf("%s should be an array of integers", $attribute); + }); + if(!is_array($value)) return false; + foreach($value as $element) + { + if(!is_string($element)) return false; + } + return true; + }); + } + + /** + * Register any application services. + * @return void + */ + public function register() + { + App::singleton('models\\oauth2\\IResourceServerContext', 'models\\oauth2\\ResourceServerContext'); + App::singleton('models\resource_server\\IAccessTokenService', 'models\resource_server\\AccessTokenService'); + App::singleton('models\\resource_server\\IApi', 'models\\resource_server\\Api'); + App::singleton('models\\resource_server\\IApiEndpoint', 'models\\resource_server\\ApiEndpoint'); + App::singleton('models\\resource_server\\IApiScope', 'models\\resource_server\\ApiScope'); + } } \ No newline at end of file diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 78951b7b..ea54f595 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -1,32 +1,118 @@ [ - 'EventListener', - ], - ]; +class EventServiceProvider extends ServiceProvider +{ + /** + * The event handler mappings for the application. + * @var array + */ + protected $listen = [ + ]; - /** - * Register any other events for your application. - * - * @param \Illuminate\Contracts\Events\Dispatcher $events - * @return void - */ - public function boot(DispatcherContract $events) - { - parent::boot($events); + /** + * Register any other events for your application. + * @param \Illuminate\Contracts\Events\Dispatcher $events + * @return void + */ + public function boot(DispatcherContract $events) + { + parent::boot($events); - // - } + Event::listen('App\Events\MyScheduleAdd', function($event) + { + if(!$event instanceof MyScheduleAdd) return; + + $entity_event = new SummitEntityEvent; + $entity_event->EntityClassName = 'MySchedule'; + $entity_event->EntityID = $event->getEventId(); + $entity_event->Type = 'INSERT'; + $entity_event->OwnerID = $event->getAttendee()->member()->ID; + $entity_event->SummitID = $event->getAttendee()->getSummit()->ID; + $entity_event->Metadata = ''; + $entity_event->save(); + }); + + Event::listen('App\Events\MyScheduleRemove', function($event) + { + if(!$event instanceof MyScheduleRemove) return; + + $entity_event = new SummitEntityEvent; + $entity_event->EntityClassName = 'MySchedule'; + $entity_event->EntityID = $event->getEventId(); + $entity_event->Type = 'DELETE'; + $entity_event->OwnerID = $event->getAttendee()->member()->ID; + $entity_event->SummitID = $event->getAttendee()->getSummit()->ID; + $entity_event->Metadata = ''; + $entity_event->save(); + }); + + SummitEvent::deleted(function($summit_event){ + + if(!$summit_event instanceof SummitEvent) return; + $resource_server_context = App::make('models\\oauth2\\IResourceServerContext'); + $owner_id = $resource_server_context->getCurrentUserExternalId(); + if(is_null($owner_id)) $owner_id = 0; + + $entity_event = new SummitEntityEvent; + $entity_event->EntityClassName = $summit_event->ClassName; + $entity_event->EntityID = $summit_event->ID; + $entity_event->Type = 'DELETE'; + $entity_event->OwnerID = $owner_id; + $entity_event->SummitID = $summit_event->getSummit()->ID; + $entity_event->Metadata = ''; + $entity_event->save(); + }); + + SummitEvent::updated(function($summit_event){ + + if(!$summit_event instanceof SummitEvent) return; + + $resource_server_context = App::make('models\\oauth2\\IResourceServerContext'); + $owner_id = $resource_server_context->getCurrentUserExternalId(); + if(is_null($owner_id)) $owner_id = 0; + + $original = $summit_event->getOriginal(); + $entity_event = new SummitEntityEvent; + $entity_event->EntityClassName = $summit_event->ClassName; + $entity_event->EntityID = $summit_event->ID; + $entity_event->Type = 'UPDATE'; + $entity_event->OwnerID = $owner_id; + $entity_event->SummitID = $summit_event->getSummit()->ID; + if(intval($original['Published']) !== intval($summit_event->Published)){ + $entity_event->Metadata = json_encode( array ( 'pub_old'=> intval($original['Published']), 'pub_new' => intval($summit_event->Published))); + } + else + $entity_event->Metadata = json_encode( array ( 'pub_new' => intval($summit_event->Published))); + $entity_event->save(); + }); + + SummitEvent::created(function($summit_event){ + + if(!$summit_event instanceof SummitEvent) return; + + $resource_server_context = App::make('models\\oauth2\\IResourceServerContext'); + $owner_id = $resource_server_context->getCurrentUserExternalId(); + if(is_null($owner_id)) $owner_id = 0; + + $entity_event = new SummitEntityEvent; + $entity_event->EntityClassName = $summit_event->ClassName; + $entity_event->EntityID = $summit_event->ID; + $entity_event->Type = 'INSERT'; + $entity_event->OwnerID = $owner_id; + $entity_event->SummitID = $summit_event->getSummit()->ID; + $entity_event->Metadata = json_encode( array ( 'pub_new' => intval($summit_event->Published))); + $entity_event->save(); + }); + } } \ No newline at end of file diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 40477cbe..3a211e44 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -32,14 +32,14 @@ class RouteServiceProvider extends ServiceProvider { // Route::filter('filter.name',function($route, $request){ .... }); Route::filter("ssl", function () { - if (!Request::secure() && Config::get("SSL.Enable", false)) + if (!Request::secure() && Config::get("server.ssl_enabled", false)) { return Redirect::secure(Request::getRequestUri()); } }); Route::filter("oauth2.enabled", function () { - if (!Config::get("OAuth2.Enable", true)) + if (!Config::get("server.oauth2_enabled", true)) { return View::make('errors.404'); } diff --git a/app/Repositories/RepositoriesProvider.php b/app/Repositories/RepositoriesProvider.php index f73594b8..6b7f7b3c 100644 --- a/app/Repositories/RepositoriesProvider.php +++ b/app/Repositories/RepositoriesProvider.php @@ -1,49 +1,65 @@ 'Active', + 'op' => '=', + 'value' => true + ) + ); + break; + case ICompanyServiceRepository::Status_non_active: + array_push( + $filters, + array( + 'name' => 'Active', + 'op' => '=', + 'value' => false + ) + ); + break; + } - /** - * @param int $id - * @return IEntity - */ - public function getById($id) - { - return $this->entity->find($id); - } + $query = $this->entity->Filter($filters); - /** - * @param int $page - * @param int $per_page - * @param string $status - * @param string $order_by - * @param string $order_dir - * @return IEntity[] - */ - public function getAll( - $page = 1, - $per_page = 1000, - $status = ICompanyServiceRepository::Status_All, - $order_by = ICompanyServiceRepository::Order_date, - $order_dir = 'asc' - ) { - $fields = array('*'); - $filters = array(); - switch($status) - { - case ICompanyServiceRepository::Status_active: - array_push( - $filters, - array( - 'name'=>'Active', - 'op' => '=', - 'value'=> true - ) - ); - break; - case ICompanyServiceRepository::Status_non_active: - array_push( - $filters, - array( - 'name'=>'Active', - 'op' => '=', - 'value'=> false - ) - ); - break; - } + switch ($order_by) { + case ICompanyServiceRepository::Order_date: + $query = $query->orderBy('Created', $order_dir); + break; + case ICompanyServiceRepository::Order_name: + $query = $query->orderBy('Name', $order_dir); + break; + } - $query = $this->entity->Filter($filters); - - switch($order_by) - { - case ICompanyServiceRepository::Order_date: - $query = $query->orderBy('Created', $order_dir); - break; - case ICompanyServiceRepository::Order_name: - $query = $query->orderBy('Name', $order_dir); - break; - } - - return $query->paginate($per_page, $fields)->toArray(); - } + return $query->paginate($per_page, $fields)->toArray(); + } } \ No newline at end of file diff --git a/app/Repositories/marketplace/EloquentConsultantRepository.php b/app/Repositories/marketplace/EloquentConsultantRepository.php index 8f3c188c..aca8e209 100644 --- a/app/Repositories/marketplace/EloquentConsultantRepository.php +++ b/app/Repositories/marketplace/EloquentConsultantRepository.php @@ -1,32 +1,33 @@ entity = $consultant; - } + /** + * @param Consultant $consultant + */ + public function __construct(Consultant $consultant) + { + $this->entity = $consultant; + } } \ No newline at end of file diff --git a/app/Repositories/marketplace/EloquentPrivateCloudServiceRepository.php b/app/Repositories/marketplace/EloquentPrivateCloudServiceRepository.php index 3d4b2937..5480bb5b 100644 --- a/app/Repositories/marketplace/EloquentPrivateCloudServiceRepository.php +++ b/app/Repositories/marketplace/EloquentPrivateCloudServiceRepository.php @@ -1,35 +1,36 @@ entity = $private_cloud; - } + /** + * @param PrivateCloudService $private_cloud + */ + public function __construct(PrivateCloudService $private_cloud) + { + $this->entity = $private_cloud; + } } \ No newline at end of file diff --git a/app/Repositories/marketplace/EloquentPublicCloudServiceRepository.php b/app/Repositories/marketplace/EloquentPublicCloudServiceRepository.php index 9620d7eb..605026b5 100644 --- a/app/Repositories/marketplace/EloquentPublicCloudServiceRepository.php +++ b/app/Repositories/marketplace/EloquentPublicCloudServiceRepository.php @@ -1,34 +1,35 @@ entity = $public_cloud; - } + /** + * @param PublicCloudService $public_cloud + */ + public function __construct(PublicCloudService $public_cloud) + { + $this->entity = $public_cloud; + } } \ No newline at end of file diff --git a/app/Repositories/resource_server/EloquentApiEndpointRepository.php b/app/Repositories/resource_server/EloquentApiEndpointRepository.php index 9cff7151..58cec3b3 100644 --- a/app/Repositories/resource_server/EloquentApiEndpointRepository.php +++ b/app/Repositories/resource_server/EloquentApiEndpointRepository.php @@ -1,67 +1,57 @@ entity = $endpoint; + } + /** + * @param string $url + * @param string $http_method + * @return IApiEndpoint + */ + public function getApiEndpointByUrlAndMethod($url, $http_method) + { + return $this->entity->Filter(array( + array( + 'name' => 'route', + 'op' => '=', + 'value' => $url + ), + array( + 'name' => 'http_method', + 'op' => '=', + 'value' => $http_method + ) + ))->firstOrFail(); + } - /** - * @param IApiEndpoint $endpoint - */ - public function __construct(IApiEndpoint $endpoint) - { - $this->entity = $endpoint; - } - /** - * @param string $url - * @param string $http_method - * @return IApiEndpoint - */ - public function getApiEndpointByUrlAndMethod($url, $http_method) - { - return $this->entity->Filter(array( array( - 'name'=>'route', - 'op' => '=', - 'value'=> $url - ), array( - 'name'=>'http_method', - 'op' => '=', - 'value'=> $http_method - )))->firstOrFail(); - } - - /** - * @param int $id - * @return IEntity - */ - public function getById($id) - { - return $this->entity->find($id); - } } \ No newline at end of file diff --git a/app/Repositories/summit/EloquentSpeakerRepository.php b/app/Repositories/summit/EloquentSpeakerRepository.php new file mode 100644 index 00000000..d7713977 --- /dev/null +++ b/app/Repositories/summit/EloquentSpeakerRepository.php @@ -0,0 +1,120 @@ +entity = $speaker; + } + + /** + * @param Summit $summit + * @param PagingInfo $paging_info + * @param Filter|null $filter + * @param Order|null $order + * @return PagingResponse + */ + public function getSpeakersBySummit(Summit $summit, PagingInfo $paging_info, Filter $filter = null, Order $order = null) + { + + $extra_filters = ''; + $extra_orders = ''; + + $bindings = array + ( + 'summit_id' => $summit->getIdentifier(), + ); + + if(!is_null($filter)) + { + $extra_filters = ' AND '.$filter->toRawSQL(array + ( + 'first_name' => 'M.FirstName', + 'last_name' => 'M.Surname', + 'email' => 'M.Email', + )); + $bindings = array_merge($bindings, $filter->getSQLBindings()); + } + + if(!is_null($order)) + { + $extra_orders = $order->toRawSQL(array + ( + 'first_name' => 'M.FirstName', + 'last_name' => 'M.Surname', + )); + } + + $total = DB::connection('ss')->select(" +SELECT COUNT(S.ID) AS QTY From PresentationSpeaker S +LEFT JOIN Member M ON M.ID = S.MemberID +WHERE EXISTS +( + SELECT E.ID FROM SummitEvent E + INNER JOIN Presentation P ON E.ID = P.ID + INNER JOIN Presentation_Speakers PS ON PS.PresentationID = P.ID + WHERE E.SummitID = :summit_id AND E.Published = 1 AND PS.PresentationSpeakerID = S.ID +) {$extra_filters};", $bindings); + $total = intval($total[0]->QTY); + + $bindings = array_merge( $bindings, array + ( + 'per_page' => $paging_info->getPerPage(), + 'offset' => $paging_info->getOffset(), + )); + $rows = DB::connection('ss')->select(" +SELECT S.* From PresentationSpeaker S +LEFT JOIN Member M ON M.ID = S.MemberID +WHERE EXISTS +( + SELECT E.ID FROM SummitEvent E + INNER JOIN Presentation P ON E.ID = P.ID + INNER JOIN Presentation_Speakers PS ON PS.PresentationID = P.ID + WHERE E.SummitID = :summit_id AND E.Published = 1 AND PS.PresentationSpeakerID = S.ID +) {$extra_filters} {$extra_orders} limit :per_page offset :offset;", $bindings); + + $items = array(); + foreach($rows as $row) + { + $instance = new PresentationSpeaker(); + $instance->setRawAttributes((array)$row, true); + array_push($items, $instance); + } + + $last_page = (int) ceil($total / $paging_info->getPerPage()); + + return new PagingResponse($total, $paging_info->getPerPage(), $paging_info->getCurrentPage(), $last_page, $items); + } +} \ No newline at end of file diff --git a/app/Repositories/summit/EloquentSummitEventRepository.php b/app/Repositories/summit/EloquentSummitEventRepository.php new file mode 100644 index 00000000..36686623 --- /dev/null +++ b/app/Repositories/summit/EloquentSummitEventRepository.php @@ -0,0 +1,52 @@ +entity = $event; + } + + /** + * @param SummitEvent $event + * @return SummitEvent[] + */ + public function getPublishedOnSameTimeFrame(SummitEvent $event) + { + $summit = $event->getSummit(); + $end_date = $event->EndDateUTC; + $start_date = $event->StartDateUTC; + return $this->entity + ->where('SummitID', '=', $summit->getIdentifier()) + ->where('Published', '=', 1) + ->where('StartDate', '<=', $end_date->format('Y-m-d H:i:s')) + ->where('EndDate', '>=', $start_date->format('Y-m-d H:i:s')) + ->get(); + } +} \ No newline at end of file diff --git a/app/Repositories/summit/EloquentSummitRepository.php b/app/Repositories/summit/EloquentSummitRepository.php new file mode 100644 index 00000000..71618583 --- /dev/null +++ b/app/Repositories/summit/EloquentSummitRepository.php @@ -0,0 +1,42 @@ +entity = $summit; + } + + /** + * @return Summit + */ + public function getCurrent() + { + //$now = new \DateTime('now', new DateTimeZone('UTC')); + return $this->entity + ->where('Active','=',1) + ->first(); + } +} \ No newline at end of file diff --git a/app/Services/ServicesProvider.php b/app/Services/ServicesProvider.php index 0e2da689..fff75162 100644 --- a/app/Services/ServicesProvider.php +++ b/app/Services/ServicesProvider.php @@ -1,34 +1,37 @@ event_repository = $event_repository; + $this->tx_service = $tx_service; + } + + /** + * @param Summit $summit + * @param SummitAttendee $attendee + * @param int $event_id + * @return bool + * @throws EntityNotFoundException + */ + public function addEventToAttendeeSchedule(Summit $summit, SummitAttendee $attendee, $event_id) + { + $res = $this->tx_service->transaction(function() use($summit, $attendee, $event_id) { + $event = $summit->getScheduleEvent($event_id); + if (is_null($event)) { + throw new EntityNotFoundException('event not found on summit!'); + } + + return $attendee->add2Schedule($event); + }); + Event::fire(new MyScheduleAdd($attendee, $event_id)); + return $res; + } + + /** + * @param Summit $summit + * @param SummitAttendee $attendee + * @param $event_id + * @return bool + * @throws EntityNotFoundException + */ + public function checkInAttendeeOnEvent(Summit $summit, SummitAttendee $attendee, $event_id) + { + return $this->tx_service->transaction(function() use($summit, $attendee, $event_id) { + $event = $summit->getScheduleEvent($event_id); + if(is_null($event)) throw new EntityNotFoundException('event not found on summit!'); + return $attendee->checkIn($event); + }); + } + + /** + * @param Summit $summit + * @param SummitAttendee $attendee + * @param int $event_id + * @return bool + * @throws \Exception + */ + public function removeEventFromAttendeeSchedule(Summit $summit, SummitAttendee $attendee, $event_id) + { + $res = $this->tx_service->transaction(function() use($summit, $attendee, $event_id) { + $event = $summit->getScheduleEvent($event_id); + if(is_null($event)) throw new EntityNotFoundException('event not found on summit!'); + return $attendee->removeFromSchedule($event); + }); + Event::fire(new MyScheduleRemove($attendee, $event_id)); + return $res; + } + + /** + * @param Summit $summit + * @param SummitEvent $event + * @param array $feedback + * @return SummitEventFeedback + */ + public function addEventFeedback(Summit $summit, SummitEvent $event, array $feedback) + { + + return $this->tx_service->transaction(function() use($summit, $event, $feedback) { + + if(!$event->AllowFeedBack) + throw new ValidationException(sprintf("event id %s dont allow feedback", $event->ID)); + + $attendee_id = intval($feedback['attendee_id']); + $attendee = SummitAttendee::find($attendee_id); + if(is_null($attendee)) throw new EntityNotFoundException(); + + $newFeedback = new SummitEventFeedback(); + $newFeedback->Rate = $feedback['rate']; + $newFeedback->Note = $feedback['note']; + $newFeedback->OwnerID = $attendee->MemberID; + $newFeedback->EventID = $event->ID; + + $event->addFeedBack($newFeedback); + + return $newFeedback; + }); + } + + + /** + * @param Summit $summit + * @param null|int $member_id + * @param null|\DateTime $from_date + * @param null|int $from_id + * @return array + */ + public function getSummitEntityEvents(Summit $summit, $member_id = null, \DateTime $from_date = null, $from_id = null) + { + $events = $summit->getEntityEvents($from_id, $from_date); + $list = array(); + $ops_dictionary = array(); + + $ops_dictionary['UPDATE'] = array(); + $ops_dictionary['DELETE'] = array(); + $ops_dictionary['INSERT'] = array(); + $last_event_id = 0; + $last_event_date = 0; + + foreach($events as $e) + { + $last_event_id = intval($e->ID); + $last_event_date = $e->Created; + + $metadata = $e->Metadata; + switch($e->EntityClassName) + { + case 'Presentation': + case 'SummitEvent': + { + $entity = $summit->getScheduleEvent($e->EntityID); + + if($e->Type === 'UPDATE') + { + $metadata = !empty($metadata) ? json_decode($metadata, true): array(); + $published_old = isset($metadata['pub_old']) ? (bool)intval($metadata['pub_old']) : false; + $published_current = isset($metadata['pub_new']) ? (bool)intval($metadata['pub_new']) : false; + + // the event was not published at the moment of UPDATE .. then skip it! + if(!isset($metadata['pub_old']) && isset($metadata['pub_new']) && !$published_current) continue; + + if(!is_null($entity)) // if event exists its bc its published + { + $type = $published_current && !$published_old && isset($metadata['pub_old']) ? 'INSERT' : 'UPDATE'; + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$type])) continue; + array_push($ops_dictionary[$type],$e->EntityClassName.$e->EntityID); + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $type, $entity)); + } + else // if does not exists on schedule delete it + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary['DELETE'])) continue; + array_push($ops_dictionary['DELETE'],$e->EntityClassName.$e->EntityID); + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, 'DELETE')); + } + } + else if($e->Type === 'DELETE') + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'MySchedule': + { + if(!is_null($member_id) && intval($member_id) === intval($e->OwnerID)) + { + if($e->Type === 'INSERT') + { + $entity = $summit->getScheduleEvent($e->EntityID); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + } + break; + case 'SummitType': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitType::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitEventType': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitEventType::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'PresentationSpeaker': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = PresentationSpeaker::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitTicketType': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitTicketType::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitVenueRoom': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitVenueRoom::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitVenue': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitVenue::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitLocationMap': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitLocationMap::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitHotel': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitHotel::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SummitAirport': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = SummitAirport::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'PresentationCategory': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = PresentationCategory::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'PresentationCategoryGroup': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = PresentationCategoryGroup::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'TrackFromTrackGroup': + { + $metadata = !empty($metadata) ? json_decode($metadata, true): array(); + if(count($metadata) === 0) continue; + $group_id = isset($metadata['group_id']) ? intval($metadata['group_id']) : null; + if(is_null($group_id)) continue; + $entity = $summit->getCategoryGroup($group_id); + if(is_null($entity)) continue; + if(in_array('PresentationCategoryGroup'.$group_id, $ops_dictionary['UPDATE'])) continue; + array_push($ops_dictionary['UPDATE'],'PresentationCategoryGroup'.$group_id); + array_push($list, $this->serializeSummitEntityEvent($e, 'PresentationCategoryGroup', 'UPDATE', $entity)); + } + break; + case 'PresentationSlide': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = PresentationSlide::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'PresentationVideo': + { + if(in_array($e->EntityClassName.$e->EntityID, $ops_dictionary[$e->Type])) continue; + array_push($ops_dictionary[$e->Type],$e->EntityClassName.$e->EntityID); + + if($e->Type === 'UPDATE' || $e->Type === "INSERT") + { + $entity = PresentationVideo::find(intval($e->EntityID)); + if(is_null($entity)) continue; + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type, $entity)); + } + else if($e->Type === 'DELETE') + { + array_push($list, $this->serializeSummitEntityEvent($e, $e->EntityClassName, $e->Type)); + } + } + break; + case 'SpeakerFromPresentation': + { + $metadata = !empty($metadata) ? json_decode($metadata, true): array(); + if(count($metadata) === 0) continue; + $presentation_id = isset($metadata['presentation_id']) ? intval($metadata['presentation_id']) : null; + if(is_null($presentation_id)) continue; + $entity = $summit->getScheduleEvent($presentation_id); + if(is_null($entity)) continue; + if(in_array('Presentation'.$presentation_id, $ops_dictionary['UPDATE'])) continue; + array_push($ops_dictionary['UPDATE'],'Presentation'.$presentation_id); + array_push($list, $this->serializeSummitEntityEvent($e, 'Presentation', 'UPDATE', $entity)); + } + break; + case 'SummitTypeFromEvent': + { + $metadata = !empty($metadata) ? json_decode($metadata, true): array(); + if(count($metadata) === 0) continue; + $event_id = isset($metadata['event_id']) ? intval($metadata['event_id']) : null; + if(is_null($event_id)) continue; + $entity = $summit->getScheduleEvent($event_id); + if(is_null($entity)) continue; + if(in_array('SummitEvent'.$event_id, $ops_dictionary['UPDATE'])) continue; + array_push($ops_dictionary['UPDATE'],'SummitEvent'.$event_id); + array_push($list, $this->serializeSummitEntityEvent($e, 'SummitEvent', 'UPDATE', $entity)); + } + break; + case 'SponsorFromEvent': + { + $metadata = !empty($metadata) ? json_decode($metadata, true): array(); + if(count($metadata) === 0) continue; + $event_id = isset($metadata['event_id']) ? intval($metadata['event_id']) : null; + if(is_null($event_id)) continue; + $entity = $summit->getScheduleEvent($event_id); + if(is_null($entity)) continue; + if(in_array('SummitEvent'.$event_id, $ops_dictionary['UPDATE'])) continue; + array_push($ops_dictionary['UPDATE'],'SummitEvent'.$event_id); + array_push($list, $this->serializeSummitEntityEvent($e, 'SummitEvent', 'UPDATE', $entity)); + } + break; + case 'WipeData': + { + // if event is for a particular user + if(intval($e->EntityID) > 0 ) + { + // if we are not the recipient or its already processed then continue + if( intval($member_id) !== intval($e->EntityID)) + continue; + } + array_push($list, $this->serializeSummitEntityEvent($e, 'TRUNCATE', 'TRUNCATE')); + } + break; + } + } + return array($last_event_id, $last_event_date, $list); + } + + /** + * @param SummitEntityEvent $e + * @param $class_name + * @param $type + * @param null $entity + * @return array + */ + private function serializeSummitEntityEvent(SummitEntityEvent $e, $class_name, $type, $entity = null) + { + $row = array + ( + 'id' => intval($e->ID), + 'created' => JsonUtils::toEpoch($e->Created), + 'class_name' => $class_name, + 'entity_id' => intval($e->EntityID), + 'type' => $type, + ); + + if(!is_null($entity)) + { + $data = $entity->toArray(); + if(isset($data['speakers'])) + { + unset($data['speakers']); + $speakers = array(); + foreach($entity->speakers() as $speaker) + { + array_push($speakers, $speaker->toArray()); + } + $data['speakers'] = $speakers; + } + + if(isset($data['sponsors'])) + { + unset($data['sponsors']); + $sponsors = array(); + foreach($entity->sponsors() as $sponsor) + { + array_push($sponsors, $sponsor->toArray()); + } + $data['sponsors'] = $sponsors; + } + $row['entity'] = $data; + } + + return $row; + } + + /** + * @param Summit $summit + * @param array $data + * @return SummitEvent + */ + public function addEvent(Summit $summit, array $data) + { + return $this->saveOrUpdateEvent($summit, $data); + } + + /** + * @param Summit $summit + * @param int $event_id + * @param array $data + * @return SummitEvent + */ + public function updateEvent(Summit $summit, $event_id, array $data) + { + return $this->saveOrUpdateEvent($summit, $data, $event_id); + } + + private function saveOrUpdateEvent(Summit $summit, array $data, $event_id = null) + { + $event_repository = $this->event_repository; + + return $this->tx_service->transaction(function() use($summit, $data, $event_id, $event_repository) { + + $start_datetime = null; + $end_datetime = null; + + if(isset($data['start_date']) && isset($data['end_date'])) + { + $start_datetime = intval($data['start_date']); + $start_datetime = new \DateTime("@$start_datetime"); + $end_datetime = intval($data['end_date']); + $end_datetime = new \DateTime("@$end_datetime"); + $interval = $end_datetime->diff($start_datetime); + if($interval->i < self::MIN_EVENT_MINUTES ) + throw new ValidationException + ( + sprintf + ( + "event should last at lest %s minutes - current duration %s", + self::MIN_EVENT_MINUTES, + $interval->i + ) + ); + } + + // check start/end datetime with summit + $event_type = null; + if(isset($data['type_id'])) { + $event_type = $summit->getEventType(intval($data['type_id'])); + if (is_null($event_type)) { + throw new EntityNotFoundException(sprintf("event type id %s does not exists!", $data['type_id'])); + } + } + + $location = null; + if(isset($data['location_id'])) { + $location = $summit->getLocation(intval($data['location_id'])); + if (is_null($location)) { + throw new EntityNotFoundException(sprintf("location id %s does not exists!", $data['location_id'])); + } + } + + $summit_types = array(); + if(isset($data['summit_types_id'])) { + foreach ($data['summit_types_id'] as $summit_type_id) { + $summit_type = $summit->getSummitType($summit_type_id); + if (is_null($summit_type)) { + throw new ValidationException(sprintf("summit type id %s does not exists!", $summit_type_id)); + } + array_push($summit_types, $summit_type); + } + } + + if(is_null($event_id)){ + $event = SummitEventFactory::build($event_type); + } + else + { + $event = $event_repository->getById($event_id); + if(is_null($event)) + throw new ValidationException(sprintf("event id %s does not exists!", $event_id)); + } + + if(isset($data['title'])) + $event->setTitle($data['title']); + + if(isset($data['description'])) + $event->setDescription($data['description']); + + if(isset($data['allow_feedback'])) + $event->setAllowFeedBack($data['allow_feedback']); + if(!is_null($event_type)) + $event->setType($event_type); + + $event->setSummit($summit); + + if(!is_null($location)) + $event->setLocation($location); + + if(!is_null($start_datetime) && !is_null($end_datetime)) { + $event->StartDate = $start_datetime; + $event->EndDate = $end_datetime; + + if(!$summit->isEventInsideSummitDuration($event)) + throw new ValidationException + ( + sprintf + ( + "event start/end (%s - %s) does not match with summit start/end (%s - %s)", + $start_datetime->format('Y-m-d H:i:s'), + $end_datetime->format('Y-m-d H:i:s'), + $summit->getLocalBeginDate()>format('Y-m-d H:i:s'), + $summit->getLocalEndDate()>format('Y-m-d H:i:s') + ) + ); + } + + + + $event_repository->add($event); + + if(count($summit_types) > 0) { + $event->clearSummitTypes(); + foreach ($summit_types as $summit_type) { + $event->addSummitType($summit_type); + } + } + + if(isset($data['tags']) && count($data['tags']) > 0) { + $event->clearTags(); + foreach ($data['tags'] as $tag) { + $event->addTag($tag); + } + } + + return $event; + }); + } + + /** + * @param Summit $summit + * @param int $event_id + * @param array $data + * @return SummitEvent + */ + public function publishEvent(Summit $summit, $event_id, array $data) + { + $event_repository = $this->event_repository; + + return $this->tx_service->transaction(function () use ($summit, $data, $event_id, $event_repository) { + + $event = $event_repository->getById($event_id); + + if(is_null($event)) + throw new EntityNotFoundException(sprintf("event id %s does not exists!", $event_id)); + + if(is_null($event->getType())) + throw new EntityNotFoundException(sprintf("event type its not assigned to event id %s!", $event_id)); + + if(is_null($event->getSummit())) + throw new EntityNotFoundException(sprintf("summit its not assigned to event id %s!", $event_id)); + + if($event->getSummit()->getIdentifier() !== $summit->getIdentifier()) + throw new ValidationException(sprintf("event %s does not belongs to summit id %s", $event_id, $summit->getIdentifier())); + + $start_datetime = $event->StartDate; + $end_datetime = $event->EndDate; + + if(isset($data['start_date']) && isset($data['end_date'])) { + $start_datetime = intval($data['start_date']); + $start_datetime = new \DateTime("@$start_datetime"); + $end_datetime = intval($data['end_date']); + $end_datetime = new \DateTime("@$end_datetime"); + } + + if(is_null($start_datetime)) + throw new ValidationException(sprintf("start_date its not assigned to event id %s!", $event_id)); + + if(is_null($end_datetime)) + throw new ValidationException(sprintf("end_date its not assigned to event id %s!", $event_id)); + + if(isset($data['location_id'])) + { + $location = $summit->getLocation(intval($data['location_id'])); + if(is_null($location)) + throw new EntityNotFoundException(sprintf("location id %s does not exists!", $data['location_id'])); + + $event->setLocation($location); + } + + $current_event_location = $event->getLocation(); + + // validate blackout times + $conflict_events = $event_repository->getPublishedOnSameTimeFrame($event); + if(!is_null($conflict_events)) { + foreach ($conflict_events as $c_event) { + // if the published event is BlackoutTime or if there is a BlackoutTime event in this timeframe + if (($event->getType()->BlackoutTimes || $c_event->getType()->BlackoutTimes) && $event->ID != $c_event->ID) { + throw new ValidationException(sprintf("You can't publish on this time frame, it conflicts with event id %s", + $c_event->ID)); + } + // if trying to publish an event on a slot occupied by another event + if ($current_event_location->getIdentifier() == $c_event->getLocation()->getIdentifier() && $event->ID != $c_event->ID) { + throw new ValidationException(sprintf("You can't publish on this time frame, it conflicts with event id %s", + $c_event->ID)); + } + + // check speakers collisions + if ($event instanceof Presentation && $c_event instanceof Presentation && $event->ID != $c_event->ID) { + foreach ($event->speakers() as $current_speaker) { + foreach ($c_event->speakers() as $c_speaker) { + if (intval($c_speaker->ID) === intval($current_speaker->ID)) { + throw new ValidationException + ( + sprintf + ( + 'speaker id % belongs already to another event ( %s) on that time frame', + $c_speaker->ID, + $c_event->ID + ) + ); + } + } + } + } + + } + } + + $event->unPublish(); + $event->publish(); + $event_repository->add($event); + return $event; + }); + } + /** + * @param Summit $summit + * @param int $event_id + * @return mixed + */ + public function unPublishEvent(Summit $summit, $event_id) + { + $event_repository = $this->event_repository; + + return $this->tx_service->transaction(function () use ($summit, $event_id, $event_repository) { + + $event = $event_repository->getById($event_id); + + if(is_null($event)) + throw new EntityNotFoundException(sprintf("event id %s does not exists!", $event_id)); + + if($event->getSummit()->getIdentifier() !== $summit->getIdentifier()) + throw new ValidationException(sprintf("event %s does not belongs to summit id %s", $event_id, $summit->getIdentifier())); + + $event->unPublish(); + $event_repository->add($event); + return $event; + }); + } + + /** + * @param Summit $summit + * @param int $event_id + * @return mixed + */ + public function deleteEvent(Summit $summit, $event_id) + { + $event_repository = $this->event_repository; + + return $this->tx_service->transaction(function () use ($summit, $event_id, $event_repository) { + + $event = $event_repository->getById($event_id); + + if(is_null($event)) + throw new EntityNotFoundException(sprintf("event id %s does not exists!", $event_id)); + + if($event->getSummit()->getIdentifier() !== $summit->getIdentifier()) + throw new ValidationException(sprintf("event %s does not belongs to summit id %s", $event_id, $summit->getIdentifier())); + + $event_repository->delete($event); + + return true; + }); + } +} \ No newline at end of file diff --git a/app/Services/utils/EloquentTransactionService.php b/app/Services/utils/EloquentTransactionService.php new file mode 100644 index 00000000..6b509a65 --- /dev/null +++ b/app/Services/utils/EloquentTransactionService.php @@ -0,0 +1,39 @@ + env('APP_OAUTH_2_0_CLIENT_ID'), 'openstackid_client_secret' => env('APP_OAUTH_2_0_CLIENT_SECRET'), - 'openstackid_base_url' => env('APP_OAUTH_2_0_AUTH_SERVER_BASE_URL'), + 'openstackid_base_url' => env('APP_OAUTH_2_0_AUTH_SERVER_BASE_URL'), /* |-------------------------------------------------------------------------- | Application Debug Mode diff --git a/config/server.php b/config/server.php new file mode 100644 index 00000000..6c8812f8 --- /dev/null +++ b/config/server.php @@ -0,0 +1,23 @@ + env('SSL_ENABLED', false), + 'oauth2_enabled' => env('OAUTH2_ENABLED', true), + 'db_log_enabled' => env('DB_LOG_ENABLED', false), + 'access_token_cache_lifetime' => env('ACCESS_TOKEN_CACHE_LIFETIME', 300), + 'assets_base_url' => env('ASSETS_BASE_URL', null), + 'response_cache_lifetime' => env('API_RESPONSE_CACHE_LIFETIME', 300), +); \ No newline at end of file diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index aef51ed4..e7cbd1ee 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -1,185 +1,550 @@ delete(); + DB::table('api_endpoints')->delete(); + $this->seedPublicCloudsEndpoints(); + $this->seedPrivateCloudsEndpoints(); + $this->seedConsultantsEndpoints(); + $this->seedSummitEndpoints(); + } - DB::table('endpoint_api_scopes')->delete(); - DB::table('api_endpoints')->delete(); + private function seedPublicCloudsEndpoints() + { - $this->seedPublicCloudsEndpoints(); - $this->seedPrivateCloudsEndpoints(); - $this->seedConsultantsEndpoints(); - } + $public_clouds = Api::where('name', '=', 'public-clouds')->first(); + $current_realm = Config::get('app.url'); + // endpoints scopes - private function seedPublicCloudsEndpoints() - { + ApiEndpoint::create( + array( + 'name' => 'get-public-clouds', + 'active' => true, + 'api_id' => $public_clouds->id, + 'route' => '/api/v1/marketplace/public-clouds', + 'http_method' => 'GET' + ) + ); - $public_clouds = Api::where('name', '=', 'public-clouds')->first(); - $current_realm = Config::get('app.url'); - // endpoints scopes + ApiEndpoint::create( + array( + 'name' => 'get-public-cloud', + 'active' => true, + 'api_id' => $public_clouds->id, + 'route' => '/api/v1/marketplace/public-clouds/{id}', + 'http_method' => 'GET' + ) + ); - ApiEndpoint::create( - array( - 'name' => 'get-public-clouds', - 'active' => true, - 'api_id' => $public_clouds->id, - 'route' => '/api/v1/marketplace/public-clouds', - 'http_method' => 'GET' - ) - ); + ApiEndpoint::create( + array( + 'name' => 'get-public-cloud-datacenters', + 'active' => true, + 'api_id' => $public_clouds->id, + 'route' => '/api/v1/marketplace/public-clouds/{id}/data-centers', + 'http_method' => 'GET' + ) + ); - ApiEndpoint::create( - array( - 'name' => 'get-public-cloud', - 'active' => true, - 'api_id' => $public_clouds->id, - 'route' => '/api/v1/marketplace/public-clouds/{id}', - 'http_method' => 'GET' - ) - ); + $public_cloud_read_scope = ApiScope::where('name', '=', + sprintf('%s/public-clouds/read', $current_realm))->first(); - ApiEndpoint::create( - array( - 'name' => 'get-public-cloud-datacenters', - 'active' => true, - 'api_id' => $public_clouds->id, - 'route' => '/api/v1/marketplace/public-clouds/{id}/data-centers', - 'http_method' => 'GET' - ) - ); + $endpoint_get_public_clouds = ApiEndpoint::where('name', '=', 'get-public-clouds')->first(); + $endpoint_get_public_clouds->scopes()->attach($public_cloud_read_scope->id); - $public_cloud_read_scope = ApiScope::where('name', '=', sprintf('%s/public-clouds/read', $current_realm))->first(); + $endpoint_get_public_cloud = ApiEndpoint::where('name', '=', 'get-public-cloud')->first(); + $endpoint_get_public_cloud->scopes()->attach($public_cloud_read_scope->id); - $endpoint_get_public_clouds = ApiEndpoint::where('name', '=', 'get-public-clouds')->first(); - $endpoint_get_public_clouds->scopes()->attach($public_cloud_read_scope->id); + $endpoint_get_public_cloud_datacenters = ApiEndpoint::where('name', '=', + 'get-public-cloud-datacenters')->first(); + $endpoint_get_public_cloud_datacenters->scopes()->attach($public_cloud_read_scope->id); + } - $endpoint_get_public_cloud = ApiEndpoint::where('name', '=', 'get-public-cloud')->first(); - $endpoint_get_public_cloud->scopes()->attach($public_cloud_read_scope->id); + private function seedPrivateCloudsEndpoints() + { + $private_clouds = Api::where('name', '=', 'private-clouds')->first(); + $current_realm = Config::get('app.url'); + // endpoints scopes - $endpoint_get_public_cloud_datacenters = ApiEndpoint::where('name', '=', 'get-public-cloud-datacenters')->first(); - $endpoint_get_public_cloud_datacenters->scopes()->attach($public_cloud_read_scope->id); - } + ApiEndpoint::create( + array( + 'name' => 'get-private-clouds', + 'active' => true, + 'api_id' => $private_clouds->id, + 'route' => '/api/v1/marketplace/private-clouds', + 'http_method' => 'GET' + ) + ); - private function seedPrivateCloudsEndpoints() - { - $private_clouds = Api::where('name', '=', 'private-clouds')->first(); - $current_realm = Config::get('app.url'); - // endpoints scopes + ApiEndpoint::create( + array( + 'name' => 'get-private-cloud', + 'active' => true, + 'api_id' => $private_clouds->id, + 'route' => '/api/v1/marketplace/private-clouds/{id}', + 'http_method' => 'GET' + ) + ); - ApiEndpoint::create( - array( - 'name' => 'get-private-clouds', - 'active' => true, - 'api_id' => $private_clouds->id, - 'route' => '/api/v1/marketplace/private-clouds', - 'http_method' => 'GET' - ) - ); + ApiEndpoint::create( + array( + 'name' => 'get-private-cloud-datacenters', + 'active' => true, + 'api_id' => $private_clouds->id, + 'route' => '/api/v1/marketplace/private-clouds/{id}/data-centers', + 'http_method' => 'GET' + ) + ); - ApiEndpoint::create( - array( - 'name' => 'get-private-cloud', - 'active' => true, - 'api_id' => $private_clouds->id, - 'route' => '/api/v1/marketplace/private-clouds/{id}', - 'http_method' => 'GET' - ) - ); + $private_cloud_read_scope = ApiScope::where('name', '=', + sprintf('%s/private-clouds/read', $current_realm))->first(); - ApiEndpoint::create( - array( - 'name' => 'get-private-cloud-datacenters', - 'active' => true, - 'api_id' => $private_clouds->id, - 'route' => '/api/v1/marketplace/private-clouds/{id}/data-centers', - 'http_method' => 'GET' - ) - ); + $endpoint_get_private_clouds = ApiEndpoint::where('name', '=', 'get-private-clouds')->first(); + $endpoint_get_private_clouds->scopes()->attach($private_cloud_read_scope->id); - $private_cloud_read_scope = ApiScope::where('name', '=', sprintf('%s/private-clouds/read', $current_realm))->first(); + $endpoint_get_private_cloud = ApiEndpoint::where('name', '=', 'get-private-cloud')->first(); + $endpoint_get_private_cloud->scopes()->attach($private_cloud_read_scope->id); - $endpoint_get_private_clouds = ApiEndpoint::where('name', '=', 'get-private-clouds')->first(); - $endpoint_get_private_clouds->scopes()->attach($private_cloud_read_scope->id); + $endpoint_get_private_cloud_datacenters = ApiEndpoint::where('name', '=', + 'get-private-cloud-datacenters')->first(); + $endpoint_get_private_cloud_datacenters->scopes()->attach($private_cloud_read_scope->id); - $endpoint_get_private_cloud = ApiEndpoint::where('name', '=', 'get-private-cloud')->first(); - $endpoint_get_private_cloud->scopes()->attach($private_cloud_read_scope->id); + } - $endpoint_get_private_cloud_datacenters = ApiEndpoint::where('name', '=', 'get-private-cloud-datacenters')->first(); - $endpoint_get_private_cloud_datacenters->scopes()->attach($private_cloud_read_scope->id); + private function seedConsultantsEndpoints() + { - } + $consultants = Api::where('name', '=', 'consultants')->first(); + $current_realm = Config::get('app.url'); + // endpoints scopes - private function seedConsultantsEndpoints() - { + ApiEndpoint::create( + array( + 'name' => 'get-consultants', + 'active' => true, + 'api_id' => $consultants->id, + 'route' => '/api/v1/marketplace/consultants', + 'http_method' => 'GET' + ) + ); - $consultants = Api::where('name', '=', 'consultants')->first(); - $current_realm = Config::get('app.url'); - // endpoints scopes + ApiEndpoint::create( + array( + 'name' => 'get-consultant', + 'active' => true, + 'api_id' => $consultants->id, + 'route' => '/api/v1/marketplace/consultants/{id}', + 'http_method' => 'GET' + ) + ); - ApiEndpoint::create( - array( - 'name' => 'get-consultants', - 'active' => true, - 'api_id' => $consultants->id, - 'route' => '/api/v1/marketplace/consultants', - 'http_method' => 'GET' - ) - ); + ApiEndpoint::create( + array( + 'name' => 'get-consultant-offices', + 'active' => true, + 'api_id' => $consultants->id, + 'route' => '/api/v1/marketplace/consultants/{id}/offices', + 'http_method' => 'GET' + ) + ); - ApiEndpoint::create( - array( - 'name' => 'get-consultant', - 'active' => true, - 'api_id' => $consultants->id, - 'route' => '/api/v1/marketplace/consultants/{id}', - 'http_method' => 'GET' - ) - ); + $consultant_read_scope = ApiScope::where('name', '=', sprintf('%s/consultants/read', $current_realm))->first(); - ApiEndpoint::create( - array( - 'name' => 'get-consultant-offices', - 'active' => true, - 'api_id' => $consultants->id, - 'route' => '/api/v1/marketplace/consultants/{id}/offices', - 'http_method' => 'GET' - ) - ); + $endpoint = ApiEndpoint::where('name', '=', 'get-consultants')->first(); + $endpoint->scopes()->attach($consultant_read_scope->id); - $consultant_read_scope = ApiScope::where('name', '=', sprintf('%s/consultants/read', $current_realm))->first(); + $endpoint = ApiEndpoint::where('name', '=', 'get-consultant')->first(); + $endpoint->scopes()->attach($consultant_read_scope->id); - $endpoint = ApiEndpoint::where('name', '=', 'get-consultants')->first(); - $endpoint->scopes()->attach($consultant_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-consultant-offices')->first(); + $endpoint->scopes()->attach($consultant_read_scope->id); + } - $endpoint = ApiEndpoint::where('name', '=', 'get-consultant')->first(); - $endpoint->scopes()->attach($consultant_read_scope->id); + private function seedSummitEndpoints() + { + $summit = Api::where('name', '=', 'summits')->first(); + $current_realm = Config::get('app.url'); + // endpoints scopes - $endpoint = ApiEndpoint::where('name', '=', 'get-consultant-offices')->first(); - $endpoint->scopes()->attach($consultant_read_scope->id); - } + + ApiEndpoint::create( + array( + 'name' => 'get-summits', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-summit', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-summit-entity-events', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/entity-events', + 'http_method' => 'GET' + ) + ); + + // attendees + + ApiEndpoint::create + ( + array( + 'name' => 'get-attendees', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/attendees', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-attendee', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-attendee-schedule', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/schedule', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'add-event-attendee-schedule', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/schedule/{event_id}', + 'http_method' => 'POST' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'delete-event-attendee-schedule', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/schedule/{event_id}', + 'http_method' => 'DELETE' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'checking-event-attendee-schedule', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/schedule/{event_id}/check-in', + 'http_method' => 'PUT' + ) + ); + + // speakers + + ApiEndpoint::create( + array( + 'name' => 'get-speakers', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/speakers', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-speaker', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/speakers/{speaker_id}', + 'http_method' => 'GET' + ) + ); + + + ApiEndpoint::create( + array( + 'name' => 'add-speaker-feedback', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/speakers/{speaker_id}/presentations/{presentation_id}/feedback', + 'http_method' => 'POST' + ) + ); + + // events + + ApiEndpoint::create( + array( + 'name' => 'get-events', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-published-events', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/published', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-published-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}/published', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'add-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events', + 'http_method' => 'POST' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'update-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}', + 'http_method' => 'PUT' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'publish-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}/publish', + 'http_method' => 'PUT' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'unpublish-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}/publish', + 'http_method' => 'DELETE' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'delete-event', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}', + 'http_method' => 'DELETE' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'add-event-feedback', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}/feedback', + 'http_method' => 'POST' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-event-feedback', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/events/{event_id}/feedback/{attendee_id?}', + 'http_method' => 'GET' + ) + ); + + // locations + + ApiEndpoint::create( + array( + 'name' => 'get-locations', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/locations', + 'http_method' => 'GET' + ) + ); + + ApiEndpoint::create( + array( + 'name' => 'get-location', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/locations/{location_id}', + 'http_method' => 'GET' + ) + ); + + // event types + + ApiEndpoint::create( + array( + 'name' => 'get-event-types', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/event-types', + 'http_method' => 'GET' + ) + ); + + //summit types + + ApiEndpoint::create( + array( + 'name' => 'get-summit-types', + 'active' => true, + 'api_id' => $summit->id, + 'route' => '/api/v1/summits/{id}/summit-types', + 'http_method' => 'GET' + ) + ); + + $summit_read_scope = ApiScope::where('name', '=', sprintf('%s/summits/read', $current_realm))->first(); + $summit_write_scope = ApiScope::where('name', '=', sprintf('%s/summits/write', $current_realm))->first(); + $summit_write_event_scope = ApiScope::where('name', '=', sprintf('%s/summits/write-event', $current_realm))->first(); + $summit_publish_event_scope = ApiScope::where('name', '=', sprintf('%s/summits/publish-event', $current_realm))->first(); + $summit_delete_event_scope = ApiScope::where('name', '=', sprintf('%s/summits/delete-event', $current_realm))->first(); + + // read + $endpoint = ApiEndpoint::where('name', '=', 'get-summits')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-summit')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-summit-entity-events')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-attendees')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-attendee')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-attendee-schedule')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'add-event-attendee-schedule')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-speakers')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-speaker')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-events')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-published-events')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-event')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-published-event')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-event-feedback')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-locations')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-location')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-event-types')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'get-summit-types')->first(); + $endpoint->scopes()->attach($summit_read_scope->id); + + // write + $endpoint->scopes()->attach($summit_write_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'delete-event-attendee-schedule')->first(); + $endpoint->scopes()->attach($summit_write_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'checking-event-attendee-schedule')->first(); + $endpoint->scopes()->attach($summit_write_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'add-speaker-feedback')->first(); + $endpoint->scopes()->attach($summit_write_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'add-event-feedback')->first(); + $endpoint->scopes()->attach($summit_write_scope->id); + // write events + $endpoint = ApiEndpoint::where('name', '=', 'add-event')->first(); + $endpoint->scopes()->attach($summit_write_event_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'update-event')->first(); + $endpoint->scopes()->attach($summit_write_event_scope->id); + + + $endpoint = ApiEndpoint::where('name', '=', 'publish-event')->first(); + $endpoint->scopes()->attach($summit_publish_event_scope->id); + $endpoint = ApiEndpoint::where('name', '=', 'unpublish-event')->first(); + $endpoint->scopes()->attach($summit_publish_event_scope->id); + + $endpoint = ApiEndpoint::where('name', '=', 'delete-event')->first(); + $endpoint->scopes()->attach($summit_delete_event_scope->id); + + } } \ No newline at end of file diff --git a/database/seeds/ApiScopesSeeder.php b/database/seeds/ApiScopesSeeder.php index 652fc5ef..5b6ea77f 100644 --- a/database/seeds/ApiScopesSeeder.php +++ b/database/seeds/ApiScopesSeeder.php @@ -1,88 +1,145 @@ delete(); - DB::table('api_scopes')->delete(); + public function run() + { + DB::table('endpoint_api_scopes')->delete(); + DB::table('api_scopes')->delete(); - $this->seedPublicCloudScopes(); - $this->seedPrivateCloudScopes(); - $this->seedConsultantScopes(); - } + $this->seedPublicCloudScopes(); + $this->seedPrivateCloudScopes(); + $this->seedConsultantScopes(); + $this->seedSummitScopes(); + } - private function seedPublicCloudScopes() - { + private function seedPublicCloudScopes() + { - $current_realm = Config::get('app.url'); - $public_clouds = Api::where('name', '=', 'public-clouds')->first(); + $current_realm = Config::get('app.url'); + $public_clouds = Api::where('name', '=', 'public-clouds')->first(); - ApiScope::create( - array( - 'name' => sprintf('%s/public-clouds/read', $current_realm), - 'short_description' => 'Get Public Clouds', - 'description' => 'Grants read only access for Public Clouds', - 'api_id' => $public_clouds->id, - 'system' => false - ) - ); - } + ApiScope::create( + array( + 'name' => sprintf('%s/public-clouds/read', $current_realm), + 'short_description' => 'Get Public Clouds', + 'description' => 'Grants read only access for Public Clouds', + 'api_id' => $public_clouds->id, + 'system' => false + ) + ); + } - private function seedPrivateCloudScopes() - { + private function seedPrivateCloudScopes() + { - $current_realm = Config::get('app.url'); - $private_clouds = Api::where('name', '=', 'private-clouds')->first(); + $current_realm = Config::get('app.url'); + $private_clouds = Api::where('name', '=', 'private-clouds')->first(); - ApiScope::create( - array( - 'name' => sprintf('%s/private-clouds/read', $current_realm), - 'short_description' => 'Get Private Clouds', - 'description' => 'Grants read only access for Private Clouds', - 'api_id' => $private_clouds->id, - 'system' => false - ) - ); - } + ApiScope::create( + array( + 'name' => sprintf('%s/private-clouds/read', $current_realm), + 'short_description' => 'Get Private Clouds', + 'description' => 'Grants read only access for Private Clouds', + 'api_id' => $private_clouds->id, + 'system' => false + ) + ); + } - private function seedConsultantScopes() - { + private function seedConsultantScopes() + { - $current_realm = Config::get('app.url'); - $consultants = Api::where('name', '=', 'consultants')->first(); + $current_realm = Config::get('app.url'); + $consultants = Api::where('name', '=', 'consultants')->first(); - ApiScope::create( - array( - 'name' => sprintf('%s/consultants/read', $current_realm), - 'short_description' => 'Get Consultants', - 'description' => 'Grants read only access for Consultants', - 'api_id' => $consultants->id, - 'system' => false - ) - ); - } + ApiScope::create( + array( + 'name' => sprintf('%s/consultants/read', $current_realm), + 'short_description' => 'Get Consultants', + 'description' => 'Grants read only access for Consultants', + 'api_id' => $consultants->id, + 'system' => false + ) + ); + } + + private function seedSummitScopes() + { + + $current_realm = Config::get('app.url'); + $summits = Api::where('name', '=', 'summits')->first(); + + ApiScope::create( + array( + 'name' => sprintf('%s/summits/read', $current_realm), + 'short_description' => 'Get Summit Data', + 'description' => 'Grants read only access for Summits Data', + 'api_id' => $summits->id, + 'system' => false + ) + ); + + ApiScope::create( + array( + 'name' => sprintf('%s/summits/write', $current_realm), + 'short_description' => 'Write Summit Data', + 'description' => 'Grants write access for Summits Data', + 'api_id' => $summits->id, + 'system' => false + ) + ); + + ApiScope::create( + array( + 'name' => sprintf('%s/summits/write-event', $current_realm), + 'short_description' => 'Write Summit Events', + 'description' => 'Grants write access for Summits Events', + 'api_id' => $summits->id, + 'system' => false + ) + ); + + ApiScope::create( + array( + 'name' => sprintf('%s/summits/delete-event', $current_realm), + 'short_description' => 'Delete Summit Events', + 'description' => 'Grants delete access for Summits Events', + 'api_id' => $summits->id, + 'system' => false + ) + ); + + ApiScope::create( + array( + 'name' => sprintf('%s/summits/publish-event', $current_realm), + 'short_description' => 'Publish/UnPublish Summit Events', + 'description' => 'Grants Publish/UnPublish access for Summits Events', + 'api_id' => $summits->id, + 'system' => false + ) + ); + } } \ No newline at end of file diff --git a/database/seeds/ApiSeeder.php b/database/seeds/ApiSeeder.php index f6b6d7e5..c08e3770 100644 --- a/database/seeds/ApiSeeder.php +++ b/database/seeds/ApiSeeder.php @@ -1,54 +1,63 @@ delete(); - DB::table('api_scopes')->delete(); - DB::table('api_endpoints')->delete(); - DB::table('apis')->delete(); - // public clouds - Api::create( - array( - 'name' => 'public-clouds', - 'active' => true, - 'Description' => 'Marketplace Public Clouds' - ) - ); - // private clouds - Api::create( - array( - 'name' => 'private-clouds', - 'active' => true, - 'Description' => 'Marketplace Private Clouds' - ) - ); - // consultants - Api::create( - array( - 'name' => 'consultants', - 'active' => true, - 'Description' => 'Marketplace Consultants' - ) - ); - } + DB::table('endpoint_api_scopes')->delete(); + DB::table('api_scopes')->delete(); + DB::table('api_endpoints')->delete(); + DB::table('apis')->delete(); + // public clouds + Api::create( + array( + 'name' => 'public-clouds', + 'active' => true, + 'Description' => 'Marketplace Public Clouds' + ) + ); + // private clouds + Api::create( + array( + 'name' => 'private-clouds', + 'active' => true, + 'Description' => 'Marketplace Private Clouds' + ) + ); + // consultants + Api::create( + array( + 'name' => 'consultants', + 'active' => true, + 'Description' => 'Marketplace Consultants' + ) + ); + // summit + Api::create( + array( + 'name' => 'summits', + 'active' => true, + 'Description' => 'Summits' + ) + ); + } } \ No newline at end of file diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index a4a72eda..b3d8fc03 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -1,22 +1,20 @@ call('ApiSeeder'); - $this->call('ApiScopesSeeder'); - $this->call('ApiEndpointsSeeder'); - } - -} + /** + * Run the database seeds. + * @return void + */ + public function run() + { + Model::unguard(); + $this->call('ApiSeeder'); + $this->call('ApiScopesSeeder'); + $this->call('ApiEndpointsSeeder'); + } +} \ No newline at end of file diff --git a/database/seeds/TestSeeder.php b/database/seeds/TestSeeder.php index 60596f82..3c39a1af 100644 --- a/database/seeds/TestSeeder.php +++ b/database/seeds/TestSeeder.php @@ -1,32 +1,30 @@ call('ApiSeeder'); - $this->call('ApiScopesSeeder'); - $this->call('ApiEndpointsSeeder'); - } - + public function run() + { + Model::unguard(); + $this->call('ApiSeeder'); + $this->call('ApiScopesSeeder'); + $this->call('ApiEndpointsSeeder'); + } } \ No newline at end of file diff --git a/tests/FilterParserTest.php b/tests/FilterParserTest.php new file mode 100644 index 00000000..0e2c868b --- /dev/null +++ b/tests/FilterParserTest.php @@ -0,0 +1,27 @@ +1' + ); + $res = FilterParser::parse($filters_input, array('COUNTRY_CODE', 'PRODUCT_CODE')); + } +} \ No newline at end of file diff --git a/tests/OAuth2PublicCloudApiTest.php b/tests/OAuth2PublicCloudApiTest.php index 3f5a6fca..df241933 100644 --- a/tests/OAuth2PublicCloudApiTest.php +++ b/tests/OAuth2PublicCloudApiTest.php @@ -1,121 +1,121 @@ 1 , - 'per_page' => 10, - 'status' => ICompanyServiceRepository::Status_active, - ); + $params = array( + 'page' => 1, + 'per_page' => 10, + 'status' => ICompanyServiceRepository::Status_active, + ); - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); - $response = $this->action( - "GET", - "OAuth2PublicCloudApiController@getClouds", - $params, - array(), - array(), - array(), - $headers - ); + $response = $this->action( + "GET", + "OAuth2PublicCloudApiController@getClouds", + $params, + array(), + array(), + array(), + $headers + ); - $content = $response->getContent(); - $clouds = json_decode($content); + $content = $response->getContent(); + $clouds = json_decode($content); - $this->assertResponseStatus(200); - } + $this->assertResponseStatus(200); + } - public function testGetPublicCloudNotFound() - { + public function testGetPublicCloudNotFound() + { - $params = array( - 'id' => 0 - ); + $params = array( + 'id' => 0 + ); - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2PublicCloudApiController@getCloud", - $params, - array(), - array(), - array(), - $headers - ); + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "GET", + "OAuth2PublicCloudApiController@getCloud", + $params, + array(), + array(), + array(), + $headers + ); - $content = $response->getContent(); - $res = json_decode($content); + $content = $response->getContent(); + $res = json_decode($content); - $this->assertResponseStatus(404); - } + $this->assertResponseStatus(404); + } - public function testGetPublicCloudFound() - { + public function testGetPublicCloudFound() + { - $params = array( - 'id' => 17 - ); + $params = array( + 'id' => 17 + ); - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2PublicCloudApiController@getCloud", - $params, - array(), - array(), - array(), - $headers - ); + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "GET", + "OAuth2PublicCloudApiController@getCloud", + $params, + array(), + array(), + array(), + $headers + ); - $content = $response->getContent(); - $res = json_decode($content); + $content = $response->getContent(); + $res = json_decode($content); - $this->assertResponseStatus(200); - } + $this->assertResponseStatus(200); + } - public function testGetDataCenterRegions() - { + public function testGetDataCenterRegions() + { - $params = array( - 'id' => 53 - ); + $params = array( + 'id' => 53 + ); - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2PublicCloudApiController@getCloudDataCenters", - $params, - array(), - array(), - array(), - $headers - ); + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "GET", + "OAuth2PublicCloudApiController@getCloudDataCenters", + $params, + array(), + array(), + array(), + $headers + ); - $content = $response->getContent(); - $res = json_decode($content); - $this->assertResponseStatus(200); + $content = $response->getContent(); + $res = json_decode($content); + $this->assertResponseStatus(200); - } + } } \ No newline at end of file diff --git a/tests/OAuth2SummitApiTest.php b/tests/OAuth2SummitApiTest.php new file mode 100644 index 00000000..4e772c14 --- /dev/null +++ b/tests/OAuth2SummitApiTest.php @@ -0,0 +1,849 @@ + " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getSummits", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $summits = json_decode($content); + $this->assertTrue(!is_null($summits)); + $this->assertResponseStatus(200); + + } + + public function testGetSummit() + { + + $params = array + ( + 'expand' => 'schedule' , + 'id' => 5 + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getSummit", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $summit = json_decode($content); + $this->assertTrue(!is_null($summit)); + $this->assertResponseStatus(200); + + $response = $this->action( + "GET", + "OAuth2SummitApiController@getSummit", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $summit = json_decode($content); + $this->assertTrue(!is_null($summit)); + $this->assertResponseStatus(200); + } + + public function testGetCurrentSummit() + { + + $params = array + ( + 'expand' => 'attendees,schedule' , + 'id' => 'current' + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getSummit", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $summit = json_decode($content); + $this->assertTrue(!is_null($summit)); + } + + /* + public function testGetCurrentSummitAttendees() + { + $params = array + ( + 'id' => 'current', + 'page' => 1, + 'per_page' => 15, + 'filter' => array + ( + 'first_name==sebastian,email=@smarcet', + ) + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getAttendees", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $attendees = json_decode($content); + $this->assertTrue(!is_null($attendees)); + } + */ + public function testGetCurrentSummitSpeakers() + { + $params = array + ( + 'id' => 'current', + 'page' => 1, + 'per_page' => 15, + 'filter' => 'first_name=@slack,last_name=@slack', + 'order' => '+first_name,-last_name' + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getSpeakers", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $speakers = json_decode($content); + $this->assertTrue(!is_null($speakers)); + } + + public function testCurrentSummitMyAttendeeFail404() + { + App::singleton('models\resource_server\IAccessTokenService', 'AccessTokenServiceStub2'); + + $params = array + ( + 'expand' => 'schedule' , + 'id' => 'current', + 'attendee_id' => 'me', + 'access_token' => $this->access_token + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getAttendee", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(404); + } + + public function testCurrentSummitMyAttendeeOK() + { + $params = array + ( + 'expand' => 'schedule,ticket_type,speaker,feedback' , + 'id' => '6', + 'attendee_id' => '561' + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getAttendee", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $attendee = json_decode($content); + $this->assertTrue(!is_null($attendee)); + } + + public function testCurrentSummitMyAttendeeAddToSchedule($event_id = 5476, $summit_id = 5) + { + $params = array + ( + 'id' => $summit_id, + 'attendee_id' => 'me', + 'event_id' => $event_id + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "POST", + "OAuth2SummitApiController@addEventToAttendeeSchedule", + $params, + array(), + array(), + array(), + $headers + ); + $content = $response->getContent(); + $this->assertResponseStatus(201); + } + + public function testCurrentSummitMyAttendeeScheduleCheckIn() + { + $params = array + ( + 'id' => 'current', + 'attendee_id' => 'me', + 'event_id' => '3872' + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "PUT", + "OAuth2SummitApiController@checkingAttendeeOnEvent", + $params, + array(), + array(), + array(), + $headers + ); + $content = $response->getContent(); + $this->assertResponseStatus(204); + } + + public function testCurrentSummitMyAttendeeScheduleUnset() + { + $event_id = 8860; + $summit_id = 6; + $this->testCurrentSummitMyAttendeeAddToSchedule($event_id, $summit_id); + $params = array + ( + 'id' => $summit_id, + 'attendee_id' => 'me', + 'event_id' => $event_id + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "DELETE", + "OAuth2SummitApiController@removeEventFromAttendeeSchedule", + $params, + array(), + array(), + array(), + $headers + ); + $content = $response->getContent(); + $this->assertResponseStatus(204); + } + + public function testGetMySpeakerFromCurrentSummit(){ + + $params = array + ( + 'expand' => 'presentations' , + 'id' => 'current', + 'speaker_id' => 'me' + ); + + $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); + $response = $this->action( + "GET", + "OAuth2SummitApiController@getSpeaker", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $speaker = json_decode($content); + $this->assertTrue(!is_null($speaker)); + } + + public function testAddFeedback2Speaker() + { + $params = array + ( + 'id' => 'current', + 'speaker_id' => 476, + 'presentation_id' => 3872 + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $feedback_data = array + ( + 'rate' => 10, + 'note' => 'you are the best, wow!', + 'owner_id' => 11624 + ); + + + $response = $this->action + ( + "POST", + "OAuth2SummitApiController@addSpeakerFeedback", + $params, + array(), + array(), + array(), + $headers, + json_encode($feedback_data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + + } + + public function testCurrentSummitEvents() + { + $params = array + ( + 'id' => 'current', + 'expand' => 'feedback' , + 'filter' => array + ( + 'tags=@design', + 'start_date>1445895000' + ) + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getEvents", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $events = json_decode($content); + $this->assertTrue(!is_null($events)); + } + + public function testGetEvent(){ + $params = array + ( + 'id' => 'current', + 'event_id' => 3874, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getEvent", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $events = json_decode($content); + $this->assertTrue(!is_null($events)); + } + + public function testPostEvent($start_date = 1461613958, $end_date = 1461613990 ) + { + $params = array + ( + 'id' => 6, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $data = array + ( + 'title' => 'test event', + 'description' => 'test event', + //'location_id' => 25, + //'allow_feedback' => true, + //'start_date' => $start_date, + //'end_date' => $end_date, + 'type_id' => 2, + 'summit_types_id' => [2], + //'tags' => ['tag#1','tag#2' ] + ); + + $response = $this->action + ( + "POST", + "OAuth2SummitApiController@addEvent", + $params, + array(), + array(), + array(), + $headers, + json_encode($data) + ); + + $this->assertResponseStatus(201); + $content = $response->getContent(); + $event = json_decode($content); + $this->assertTrue($event->id > 0); + return $event; + } + + public function testUpdateEvent() + { + $event = $this->testPostEvent(); + unset($event->summit_types); + unset($event->tags); + $params = array + ( + 'id' => 6, + 'event_id' => $event->id, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $event->title .= ' update'; + + + $response = $this->action + ( + "PUT", + "OAuth2SummitApiController@updateEvent", + $params, + array(), + array(), + array(), + $headers, + json_encode($event) + ); + + $this->assertResponseStatus(200); + $content = $response->getContent(); + $event = json_decode($content); + $this->assertTrue($event->id > 0); + return $event; + + } + + public function testPublishEvent($start_date = 1461685500, $end_date = 1461685800) + { + $event = $this->testPostEvent($start_date,$end_date ); + unset($event->summit_types); + unset($event->tags); + + $params = array + ( + 'id' => 6, + 'event_id' => $event->id, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "PUT", + "OAuth2SummitApiController@publishEvent", + $params, + array(), + array(), + array(), + $headers + ); + + $this->assertResponseStatus(204); + + return $event; + } + + public function testUnPublishEvent() + { + $event = $this->testPublishEvent(1461682800, 1461683700); + + $params = array + ( + 'id' => 6, + 'event_id' => $event->id, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "DELETE", + "OAuth2SummitApiController@unPublishEvent", + $params, + array(), + array(), + array(), + $headers + ); + + $this->assertResponseStatus(204); + + return $event; + } + + public function testDeleteEvent() + { + $event = $this->testPostEvent(); + + $params = array + ( + 'id' => 6, + 'event_id' => $event->id, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "DELETE", + "OAuth2SummitApiController@deleteEvent", + $params, + array(), + array(), + array(), + $headers + ); + + $this->assertResponseStatus(204); + + return $event; + } + + public function testAddFeedback2Event() + { + $params = array + ( + 'id' => 5, + 'event_id' => 4189, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $feedback_data = array + ( + 'rate' => 10, + 'note' => 'nice presentation, wow!', + 'attendee_id' => 'me' + ); + + + $response = $this->action + ( + "POST", + "OAuth2SummitApiController@addEventFeedback", + $params, + array(), + array(), + array(), + $headers, + json_encode($feedback_data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + + } + + public function testGetEntityEventsFromCurrentSummit() + { + $params = array + ( + 'id' => 'current', + 'from_date' => '1449152383' + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getSummitEntityEvents", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $events = json_decode($content); + $this->assertTrue(!is_null($events)); + } + + public function testGetEntityEventsFromCurrentSummitGreatherThanGivenID() + { + $params = array + ( + 'id' => 6, + 'last_event_id' => 0 + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getSummitEntityEvents", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $events = json_decode($content); + $this->assertTrue(!is_null($events)); + } + + public function testGetEventFeedback() + { + $this->testAddFeedback2Event(); + + $params = array + ( + 'id' => 'current', + 'event_id' => 3591, + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getEventFeedback", + $params, + array('expand' => 'owner'), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $feedback = json_decode($content); + $this->assertTrue(!is_null($feedback)); + } + + public function testGetMeEventFeedback() + { + $this->testAddFeedback2Event(); + + $params = array + ( + 'id' => 'current', + 'event_id' => 3591, + 'attendee_id' => 'me', + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getEventFeedback", + $params, + array( 'expand' => 'owner'), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $feedback = json_decode($content); + $this->assertTrue(!is_null($feedback)); + } + + public function testGetCurrentSummitLocations() + { + $params = array + ( + 'id' => 'current', + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getLocations", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $locations = json_decode($content); + $this->assertTrue(!is_null($locations)); + } + + public function testGetCurrentSummitLocation() + { + $params = array + ( + 'id' => 'current', + 'location_id' => 18 + ); + + $headers = array + ( + "HTTP_Authorization" => " Bearer " .$this->access_token, + "CONTENT_TYPE" => "application/json" + ); + + $response = $this->action + ( + "GET", + "OAuth2SummitApiController@getLocation", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $locations = json_decode($content); + $this->assertTrue(!is_null($locations)); + } + +} \ No newline at end of file diff --git a/tests/ProtectedApiTest.php b/tests/ProtectedApiTest.php index 36340120..e1ba9b31 100644 --- a/tests/ProtectedApiTest.php +++ b/tests/ProtectedApiTest.php @@ -1,74 +1,109 @@ access_token = '123456789'; - parent::setUp(); - } + return $app; + } - public function tearDown() - { - Mockery::close(); - parent::tearDown(); - } + public function setUp() + { + $this->access_token = '123456789'; + parent::setUp(); + } + + public function tearDown() + { + Mockery::close(); + parent::tearDown(); + } } \ No newline at end of file