diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php index fc58f47c..6e9459ea 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php @@ -835,10 +835,21 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController if (!Request::isJson()) return $this->error400(); $data = Input::json(); + $current_member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($current_member_id)) + return $this->error403(); + + $member = $this->member_repository->getById($current_member_id); + if (is_null($member)) + return $this->error403(); $speaker = $this->speaker_repository->getById($speaker_id); if (is_null($speaker)) return $this->error404(); + if(!$speaker->canBeEditedBy($member)){ + return $this->error403(); + } + $rules = [ 'title' => 'sometimes|string|max:100', 'first_name' => 'sometimes|string|max:100', @@ -1148,4 +1159,104 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController } } + /** + * @param $speaker_id + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function requestSpeakerEditPermission($speaker_id){ + try { + $current_member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($current_member_id)) + return $this->error403(); + + $request = $this->service->requestSpeakerEditPermission($current_member_id, $speaker_id); + + return $this->created( + SerializerRegistry::getInstance()->getSerializer($request) + ); + + } catch (ValidationException $ex1) { + Log::warning($ex1); + return $this->error412(array($ex1->getMessage())); + } catch (EntityNotFoundException $ex2) { + Log::warning($ex2); + return $this->error404(array('message' => $ex2->getMessage())); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $speaker_id + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function getSpeakerEditPermission($speaker_id){ + try { + $current_member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($current_member_id)) + return $this->error403(); + + $request = $this->service->getSpeakerEditPermission($current_member_id, $speaker_id); + + return $this->ok( + SerializerRegistry::getInstance()->getSerializer($request)->serialize() + ); + + } catch (ValidationException $ex1) { + Log::warning($ex1); + return $this->error412(array($ex1->getMessage())); + } catch (EntityNotFoundException $ex2) { + Log::warning($ex2); + return $this->error404(array('message' => $ex2->getMessage())); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + + /** + * @param $speaker_id + * @param $hash + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function approveSpeakerEditPermission($speaker_id, $hash){ + try { + $request = $this->service->approveSpeakerEditPermission($hash, $speaker_id); + return response()->view('speakers.edit_permissions.approved', [], 200); + } catch (ValidationException $ex1) { + Log::warning($ex1); + return response()->view('speakers.edit_permissions.approved_validation_error', [], 412); + } catch (EntityNotFoundException $ex2) { + Log::warning($ex2); + return response()->view('speakers.edit_permissions.approved_error', [], 404); + } catch (Exception $ex) { + Log::error($ex); + return response()->view('speakers.edit_permissions.approved_error', [], 500); + } + } + + /** + * @param $speaker_id + * @param $hash + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function declineSpeakerEditPermission($speaker_id, $hash){ + try { + + $request = $this->service->rejectSpeakerEditPermission($hash, $speaker_id); + return response()->view('speakers.edit_permissions.rejected', [], 200); + } catch (ValidationException $ex1) { + Log::warning($ex1); + return response()->view('speakers.edit_permissions.rejected_validation_error', [], 412); + } catch (EntityNotFoundException $ex2) { + Log::warning($ex2); + return response()->view('speakers.edit_permissions.rejected_error', [], 404); + } catch (Exception $ex) { + Log::error($ex); + return response()->view('speakers.edit_permissions.rejected_error', [], 500); + } + } + } \ No newline at end of file diff --git a/app/Http/Routes/public.php b/app/Http/Routes/public.php index ac3a9739..b2f8a2f4 100644 --- a/app/Http/Routes/public.php +++ b/app/Http/Routes/public.php @@ -30,6 +30,18 @@ Route::group([ Route::get('', 'OAuth2MembersApiController@getAll'); }); + // speakers + Route::group(['prefix'=>'speakers'], function() { + Route::group(['prefix'=>'{speaker_id}'], function(){ + Route::group(['prefix'=>'edit-permission'], function(){ + Route::group(['prefix'=>'{token}'], function(){ + Route::get('approve', 'OAuth2SummitSpeakersApiController@approveSpeakerEditPermission'); + Route::get('decline', 'OAuth2SummitSpeakersApiController@declineSpeakerEditPermission'); + }); + }); + }); + }); + // summits Route::group(['prefix'=>'summits'], function() { Route::get('', [ 'middleware' => 'cache:'.Config::get('cache_api_response.get_summit_response_lifetime', 600), 'uses' => 'OAuth2SummitApiController@getSummits']); diff --git a/app/Http/routes.php b/app/Http/routes.php index ba5f5e05..3163ed63 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -598,7 +598,7 @@ Route::group([ Route::group(['prefix' => 'speakers'], function () { Route::get('', 'OAuth2SummitSpeakersApiController@getAll'); - Route::post('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitSpeakersApiController@addSpeaker']); + Route::post('', 'OAuth2SummitSpeakersApiController@addSpeaker'); Route::put('merge/{speaker_from_id}/{speaker_to_id}', 'OAuth2SummitSpeakersApiController@merge'); Route::group(['prefix' => 'active-involvements'], function(){ @@ -647,7 +647,9 @@ Route::group([ }); Route::group(['prefix' => '{speaker_id}'], function () { - Route::put('',[ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitSpeakersApiController@updateSpeaker'])->where('speaker_id', 'me|[0-9]+'); + Route::put('/edit-permission', 'OAuth2SummitSpeakersApiController@requestSpeakerEditPermission')->where('speaker_id', '[0-9]+'); + Route::get('/edit-permission', 'OAuth2SummitSpeakersApiController@getSpeakerEditPermission')->where('speaker_id', '[0-9]+'); + Route::put('','OAuth2SummitSpeakersApiController@updateSpeaker')->where('speaker_id', 'me|[0-9]+'); Route::delete('',[ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitSpeakersApiController@deleteSpeaker'])->where('speaker_id', 'me|[0-9]+'); Route::get('', 'OAuth2SummitSpeakersApiController@getSpeaker'); Route::post('/photo', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitSpeakersApiController@addSpeakerPhoto']); diff --git a/app/Mail/SpeakerEditPermissionApprovedEmail.php b/app/Mail/SpeakerEditPermissionApprovedEmail.php new file mode 100644 index 00000000..dc56e3d2 --- /dev/null +++ b/app/Mail/SpeakerEditPermissionApprovedEmail.php @@ -0,0 +1,53 @@ +request = $request; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this + ->from('noreply@openstack.org') + ->subject("OpenStack - Speaker Profile Edit Permission Approved") + ->view('emails.speakers.permissioneditapproved'); + } +} diff --git a/app/Mail/SpeakerEditPermissionRejectedEmail.php b/app/Mail/SpeakerEditPermissionRejectedEmail.php new file mode 100644 index 00000000..0d813f3c --- /dev/null +++ b/app/Mail/SpeakerEditPermissionRejectedEmail.php @@ -0,0 +1,53 @@ +request = $request; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this + ->from('noreply@openstack.org') + ->subject("OpenStack - Speaker Profile Edit Permission Rejected") + ->view('emails.speakers.permissioneditrejected'); + } +} diff --git a/app/Mail/SpeakerEditPermissionRequestedEmail.php b/app/Mail/SpeakerEditPermissionRequestedEmail.php new file mode 100644 index 00000000..3d1982fc --- /dev/null +++ b/app/Mail/SpeakerEditPermissionRequestedEmail.php @@ -0,0 +1,60 @@ +request = $request; + $this->token = $token; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this + ->from('noreply@openstack.org') + ->subject("OpenStack - Speaker Profile Edit Permission Requested") + ->view('emails.speakers.permissioneditrequested'); + } +} diff --git a/app/ModelSerializers/SerializerRegistry.php b/app/ModelSerializers/SerializerRegistry.php index 935d5d81..2ab288c4 100644 --- a/app/ModelSerializers/SerializerRegistry.php +++ b/app/ModelSerializers/SerializerRegistry.php @@ -149,6 +149,8 @@ final class SerializerRegistry self::SerializerType_Private => AdminPresentationSpeakerSerializer::class ]; + $this->registry['SpeakerEditPermissionRequest'] = SpeakerEditPermissionRequestSerializer::class; + // RSVP $this->registry['RSVP'] = RSVPSerializer::class; $this->registry['RSVPTemplate'] = RSVPTemplateSerializer::class; @@ -197,6 +199,7 @@ final class SerializerRegistry $this->registry['SummitLocationImage'] = SummitLocationImageSerializer::class; $this->registry['SummitLocationBanner'] = SummitLocationBannerSerializer::class; $this->registry['ScheduledSummitLocationBanner'] = ScheduledSummitLocationBannerSerializer::class; + // track tag groups $this->registry['TrackTagGroup'] = TrackTagGroupSerializer::class; $this->registry['TrackTagGroupAllowedTag'] = TrackTagGroupAllowedTagSerializer::class; diff --git a/app/ModelSerializers/Summit/Speakers/SpeakerEditPermissionRequestSerializer.php b/app/ModelSerializers/Summit/Speakers/SpeakerEditPermissionRequestSerializer.php new file mode 100644 index 00000000..a2da54c9 --- /dev/null +++ b/app/ModelSerializers/Summit/Speakers/SpeakerEditPermissionRequestSerializer.php @@ -0,0 +1,27 @@ + 'approved:json_boolean', + 'ApprovedDate' => 'approved_date:datetime_epoch', + 'SpeakerId' => 'speaker_id:json_int', + 'RequestedById' => 'requested_by_id:json_int', + ]; +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/EmailCreationRequests/EmailCreationRequest.php b/app/Models/Foundation/Main/EmailCreationRequests/EmailCreationRequest.php index 6fa8d9a3..bf65e32b 100644 --- a/app/Models/Foundation/Main/EmailCreationRequests/EmailCreationRequest.php +++ b/app/Models/Foundation/Main/EmailCreationRequests/EmailCreationRequest.php @@ -23,7 +23,10 @@ use DateTime; * "SpeakerCreationEmailCreationRequest" = "SpeakerCreationEmailCreationRequest", * "MemberPromoCodeEmailCreationRequest"= "MemberPromoCodeEmailCreationRequest", * "CalendarSyncErrorEmailRequest" = "CalendarSyncErrorEmailRequest", - * "SpeakerSelectionAnnouncementEmailCreationRequest" = "SpeakerSelectionAnnouncementEmailCreationRequest"}) + * "SpeakerSelectionAnnouncementEmailCreationRequest" = "SpeakerSelectionAnnouncementEmailCreationRequest", + * "PresentationCreatorNotificationEmailRequest" = "PresentationCreatorNotificationEmailRequest", + * "PresentationSpeakerNotificationEmailRequest" = "PresentationSpeakerNotificationEmailRequest" + * }) * Class EmailCreationRequest * @package models\main */ diff --git a/app/Models/Foundation/Main/EmailCreationRequests/PresentationCreatorNotificationEmailRequest.php b/app/Models/Foundation/Main/EmailCreationRequests/PresentationCreatorNotificationEmailRequest.php new file mode 100644 index 00000000..5ba6366c --- /dev/null +++ b/app/Models/Foundation/Main/EmailCreationRequests/PresentationCreatorNotificationEmailRequest.php @@ -0,0 +1,52 @@ +template_name = "presentation-creator-notification"; + parent::__construct(); + } + + /** + * @return Presentation + */ + public function getPresentation(): Presentation + { + return $this->presentation; + } + + /** + * @param Presentation $presentation + */ + public function setPresentation(Presentation $presentation): void + { + $this->presentation = $presentation; + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/EmailCreationRequests/PresentationSpeakerNotificationEmailRequest.php b/app/Models/Foundation/Main/EmailCreationRequests/PresentationSpeakerNotificationEmailRequest.php new file mode 100644 index 00000000..8dd340ee --- /dev/null +++ b/app/Models/Foundation/Main/EmailCreationRequests/PresentationSpeakerNotificationEmailRequest.php @@ -0,0 +1,77 @@ +template_name = "presentation-speaker-notification"; + parent::__construct(); + } + + /** + * @return PresentationSpeaker + */ + public function getSpeaker() + { + return $this->speaker; + } + + /** + * @param PresentationSpeaker $speaker + */ + public function setSpeaker($speaker) + { + $this->speaker = $speaker; + } + + /** + * @return Presentation + */ + public function getPresentation(): Presentation + { + return $this->presentation; + } + + /** + * @param Presentation $presentation + */ + public function setPresentation(Presentation $presentation): void + { + $this->presentation = $presentation; + } + +} \ No newline at end of file diff --git a/app/Models/Foundation/Marketplace/InteropProgramVersion.php b/app/Models/Foundation/Marketplace/InteropProgramVersion.php index 2eb0ba07..b4e0b0f5 100644 --- a/app/Models/Foundation/Marketplace/InteropProgramVersion.php +++ b/app/Models/Foundation/Marketplace/InteropProgramVersion.php @@ -30,7 +30,7 @@ class InteropProgramVersion extends SilverstripeBaseModel /** * @ORM\ManyToMany(targetEntity="InteropCapability", cascade={"persist"}) - * @ORM\JoinTable(name="nteropProgramVersion_Capabilities", + * @ORM\JoinTable(name="InteropProgramVersion_Capabilities", * joinColumns={@ORM\JoinColumn(name="InteropProgramVersionID", referencedColumnName="ID")}, * inverseJoinColumns={@ORM\JoinColumn(name="InteropCapabilityID", referencedColumnName="ID")} * ) diff --git a/app/Models/Foundation/Summit/Factories/SpeakerEditPermissionRequestFactory.php b/app/Models/Foundation/Summit/Factories/SpeakerEditPermissionRequestFactory.php new file mode 100644 index 00000000..29f86b44 --- /dev/null +++ b/app/Models/Foundation/Summit/Factories/SpeakerEditPermissionRequestFactory.php @@ -0,0 +1,34 @@ +setSpeaker($speaker); + $request->setRequestedBy($requestor); + return $request; + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Repositories/ISpeakerEditPermissionRequestRepository.php b/app/Models/Foundation/Summit/Repositories/ISpeakerEditPermissionRequestRepository.php new file mode 100644 index 00000000..792faf32 --- /dev/null +++ b/app/Models/Foundation/Summit/Repositories/ISpeakerEditPermissionRequestRepository.php @@ -0,0 +1,36 @@ +organizational_roles = new ArrayCollection; $this->active_involvements = new ArrayCollection; $this->announcement_summit_emails = new ArrayCollection; + $this->granted_edit_permissions = new ArrayCollection; } /** @@ -1620,4 +1627,17 @@ SQL; } return $photoUrl; } + + /** + * @param Member $member + * @return bool + */ + public function canBeEditedBy(Member $member):bool{ + if($member->isAdmin()) return true; + $criteria = Criteria::create(); + $criteria + ->where(Criteria::expr()->eq('requested_by', $member)) + ->andWhere(Criteria::expr()->eq('approved', true)); + return $this->granted_edit_permissions->matching($criteria)->count() > 0 ; + } } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Speakers/SpeakerEditPermissionRequest.php b/app/Models/Foundation/Summit/Speakers/SpeakerEditPermissionRequest.php new file mode 100644 index 00000000..d338ee86 --- /dev/null +++ b/app/Models/Foundation/Summit/Speakers/SpeakerEditPermissionRequest.php @@ -0,0 +1,207 @@ +approved = false; + } + + /** + * @return PresentationSpeaker + */ + public function getSpeaker(): PresentationSpeaker + { + return $this->speaker; + } + + /** + * @param PresentationSpeaker $speaker + */ + public function setSpeaker(PresentationSpeaker $speaker): void + { + $this->speaker = $speaker; + } + + /** + * @return Member + */ + public function getRequestedBy(): Member + { + return $this->requested_by; + } + + /** + * @param Member $requested_by + */ + public function setRequestedBy(Member $requested_by): void + { + $this->requested_by = $requested_by; + } + + /** + * @return bool + */ + public function isApproved():bool + { + return $this->approved; + } + + /** + * @param mixed $approved + */ + public function setApproved($approved): void + { + $this->approved = $approved; + } + + /** + * @return DateTime + */ + public function getApprovedDate():DateTime + { + return $this->approved_date; + } + + /** + * @param DateTime $approved_date + */ + public function setApprovedDate($approved_date): void + { + $this->approved_date = $approved_date; + } + + /** + * @return string + */ + public function getHash():string + { + return $this->hash; + } + + /** + * @return string + */ + public function generateConfirmationToken() { + $generator = new RandomGenerator(); + $token = sprintf("%s.%s.%s",$generator->randomToken(), $this->speaker->getId() , $this->requested_by->getId()); + $this->hash = self::HashConfirmationToken($token); + return $token; + } + + /** + * @param string $token + * @return string + */ + public static function HashConfirmationToken(string $token){ + return md5($token); + } + + + public function approve():void{ + $this->approved = true; + $this->approved_date = new \DateTime('now', new \DateTimeZone('UTC')); + } + + public function reject():void{ + $this->approved = false; + $this->approved_date = new \DateTime('now', new \DateTimeZone('UTC')); + } + + /** + * @return bool + */ + public function isActionTaken():bool + { + return !is_null( $this->approved_date ); + } + + /** + * @param int $speaker_id + * @param string $token + * @return string + */ + public function getConfirmationLink(int $speaker_id, string $token): string{ + return sprintf("%s/api/public/v1/speakers/%s/edit-permission/%s/approve", Config::get("app.url", '#'), $speaker_id, $token); + } + + /** + * @return int + */ + public function getSpeakerId():int { + try { + return !is_null($this->speaker) ? $this->speaker->getId() : 0; + } + catch(\Exception $ex){ + return 0; + } + } + + /** + * @return int + */ + public function getRequestedById():int { + try { + return !is_null($this->requested_by) ? $this->requested_by->getId() : 0; + } + catch(\Exception $ex){ + return 0; + } + } +} \ No newline at end of file diff --git a/app/Models/ResourceServer/ResourceServerEntity.php b/app/Models/ResourceServer/ResourceServerEntity.php index e0ddbab3..7c9f0633 100644 --- a/app/Models/ResourceServer/ResourceServerEntity.php +++ b/app/Models/ResourceServer/ResourceServerEntity.php @@ -1,5 +1,4 @@ EntityRepository. + * + * @param EntityManager $em The EntityManager to use. + * @param ClassMetadata $class The class descriptor. + */ + public function __construct($em, ClassMetadata $class) + { + $em = Registry::getManager(ResourceServerEntity::EntityManager); + parent::__construct($em, $class); + } +} \ No newline at end of file diff --git a/app/Repositories/DoctrineRepository.php b/app/Repositories/DoctrineRepository.php index 21acbc9d..1afd514e 100644 --- a/app/Repositories/DoctrineRepository.php +++ b/app/Repositories/DoctrineRepository.php @@ -11,37 +11,25 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\QueryBuilder; -use LaravelDoctrine\ORM\Facades\Registry;use models\utils\IBaseRepository; +use LaravelDoctrine\ORM\Facades\Registry; +use models\utils\IBaseRepository; use models\utils\IEntity; +use models\utils\SilverstripeBaseModel; use utils\Filter; use utils\Order; use utils\PagingInfo; use utils\PagingResponse; use Doctrine\ORM\Tools\Pagination\Paginator; - /** * Class DoctrineRepository * @package App\Repositories */ abstract class DoctrineRepository extends EntityRepository implements IBaseRepository { - protected static $em_name = 'default'; - /** - * Initializes a new EntityRepository. - * - * @param EntityManager $em The EntityManager to use. - * @param ClassMetadata $class The class descriptor. - */ - public function __construct($em, ClassMetadata $class) - { - $em = Registry::getManager(static::$em_name); - parent::__construct($em, $class); - } public function getById($id) { diff --git a/app/Repositories/RepositoriesProvider.php b/app/Repositories/RepositoriesProvider.php index 99e6903b..6f35fb26 100644 --- a/app/Repositories/RepositoriesProvider.php +++ b/app/Repositories/RepositoriesProvider.php @@ -25,6 +25,7 @@ use App\Models\Foundation\Summit\Repositories\IPresentationSpeakerSummitAssistan use App\Models\Foundation\Summit\Repositories\IRSVPTemplateRepository; use App\Models\Foundation\Summit\Repositories\ISelectionPlanRepository; use App\Models\Foundation\Summit\Repositories\ISpeakerActiveInvolvementRepository; +use App\Models\Foundation\Summit\Repositories\ISpeakerEditPermissionRequestRepository; use App\Models\Foundation\Summit\Repositories\ISpeakerOrganizationalRoleRepository; use App\Models\Foundation\Summit\Repositories\ISummitEventTypeRepository; use App\Models\Foundation\Summit\Repositories\ISummitLocationBannerRepository; @@ -33,6 +34,7 @@ use App\Models\Foundation\Summit\Repositories\ISummitTrackRepository; use App\Models\Foundation\Summit\Repositories\ITrackQuestionTemplateRepository; use App\Models\Foundation\Summit\Repositories\ITrackTagGroupAllowedTagsRepository; use App\Models\Foundation\Summit\SelectionPlan; +use App\Models\Foundation\Summit\Speakers\SpeakerEditPermissionRequest; use App\Models\Foundation\Summit\TrackTagGroupAllowedTag; use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; @@ -392,5 +394,12 @@ final class RepositoriesProvider extends ServiceProvider } ); + App::singleton( + ISpeakerEditPermissionRequestRepository::class, + function(){ + return EntityManager::getRepository(SpeakerEditPermissionRequest::class); + } + ); + } } \ No newline at end of file diff --git a/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php b/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php index dcc64539..be375f3c 100644 --- a/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php +++ b/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php @@ -15,7 +15,9 @@ use App\Models\ResourceServer\ApiEndpoint; use App\Models\ResourceServer\IApiEndpoint; use App\Models\ResourceServer\IApiEndpointRepository; +use App\Repositories\ConfigDoctrineRepository; use App\Repositories\DoctrineRepository; +use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\QueryBuilder; use Illuminate\Support\Facades\Log; @@ -24,10 +26,20 @@ use Illuminate\Support\Facades\Log; * @package repositories\resource_server */ final class DoctrineApiEndpointRepository - extends DoctrineRepository + extends ConfigDoctrineRepository implements IApiEndpointRepository { + /** + * Initializes a new EntityRepository. + * + * @param EntityManager $em The EntityManager to use. + * @param ClassMetadata $class The class descriptor. + */ + public function __construct($em, ClassMetadata $class) + { + parent::__construct($em, $class); + } /** * @param string $url * @param string $http_method @@ -59,7 +71,7 @@ final class DoctrineApiEndpointRepository */ protected function getBaseEntity() { - // TODO: Implement getBaseEntity() method. + return ApiEndpoint::class; } /** @@ -67,7 +79,7 @@ final class DoctrineApiEndpointRepository */ protected function getFilterMappings() { - return ApiEndpoint::class; + return []; } /** diff --git a/app/Repositories/ResourceServer/DoctrineEndPointRateLimitByIPRepository.php b/app/Repositories/ResourceServer/DoctrineEndPointRateLimitByIPRepository.php index b865d614..c367be40 100644 --- a/app/Repositories/ResourceServer/DoctrineEndPointRateLimitByIPRepository.php +++ b/app/Repositories/ResourceServer/DoctrineEndPointRateLimitByIPRepository.php @@ -13,15 +13,22 @@ **/ use App\Models\ResourceServer\EndPointRateLimitByIP; use App\Models\ResourceServer\IEndpointRateLimitByIPRepository; +use App\Repositories\ConfigDoctrineRepository; use App\Repositories\DoctrineRepository; use Doctrine\ORM\QueryBuilder; use Illuminate\Support\Facades\Log; +use models\utils\IEntity; +use utils\Filter; +use utils\Order; +use utils\PagingInfo; +use utils\PagingResponse; + /** * Class DoctrineEndPointRateLimitByIPRepository * @package repositories\resource_server */ final class DoctrineEndPointRateLimitByIPRepository - extends DoctrineRepository + extends ConfigDoctrineRepository implements IEndpointRateLimitByIPRepository { /** @@ -84,4 +91,50 @@ final class DoctrineEndPointRateLimitByIPRepository { return $query; } + + /** + * @param int $id + * @return IEntity + */ + public function getById($id) + { + // TODO: Implement getById() method. + } + + /** + * @param IEntity $entity + * @return void + */ + public function add($entity) + { + // TODO: Implement add() method. + } + + /** + * @param IEntity $entity + * @return void + */ + public function delete($entity) + { + // TODO: Implement delete() method. + } + + /** + * @return IEntity[] + */ + public function getAll() + { + // TODO: Implement getAll() method. + } + + /** + * @param PagingInfo $paging_info + * @param Filter|null $filter + * @param Order|null $order + * @return PagingResponse + */ + public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Order $order = null) + { + // TODO: Implement getAllByPage() method. + } } \ No newline at end of file diff --git a/app/Repositories/ResourceServer/EloquentApiEndpointRepository.php b/app/Repositories/ResourceServer/EloquentApiEndpointRepository.php index edada08f..73e474a2 100644 --- a/app/Repositories/ResourceServer/EloquentApiEndpointRepository.php +++ b/app/Repositories/ResourceServer/EloquentApiEndpointRepository.php @@ -1,5 +1,4 @@ firstOrFail(); } + /** + * @param int $id + * @return IEntity + */ + public function getById($id) + { + // TODO: Implement getById() method. + } + + /** + * @param IEntity $entity + * @return void + */ + public function add($entity) + { + // TODO: Implement add() method. + } + + /** + * @param IEntity $entity + * @return void + */ + public function delete($entity) + { + // TODO: Implement delete() method. + } + + /** + * @return IEntity[] + */ + public function getAll() + { + // TODO: Implement getAll() method. + } + + /** + * @param PagingInfo $paging_info + * @param Filter|null $filter + * @param Order|null $order + * @return PagingResponse + */ + public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Order $order = null) + { + // TODO: Implement getAllByPage() method. + } } \ No newline at end of file diff --git a/app/Repositories/SilverStripeDoctrineRepository.php b/app/Repositories/SilverStripeDoctrineRepository.php index 5f9d869a..9047037f 100644 --- a/app/Repositories/SilverStripeDoctrineRepository.php +++ b/app/Repositories/SilverStripeDoctrineRepository.php @@ -1,5 +1,4 @@ EntityRepository. + * + * @param EntityManager $em The EntityManager to use. + * @param ClassMetadata $class The class descriptor. + */ + public function __construct($em, ClassMetadata $class) + { + $em = Registry::getManager(SilverstripeBaseModel::EntityManager); + parent::__construct($em, $class); + } /** * @return array diff --git a/app/Repositories/Summit/DoctrineSpeakerEditPermissionRequestRepository.php b/app/Repositories/Summit/DoctrineSpeakerEditPermissionRequestRepository.php new file mode 100644 index 00000000..3fbebdcb --- /dev/null +++ b/app/Repositories/Summit/DoctrineSpeakerEditPermissionRequestRepository.php @@ -0,0 +1,72 @@ +getEntityManager() + ->createQueryBuilder() + ->select("r") + ->from(SpeakerEditPermissionRequest::class, "r") + ->where("r.speaker = :speaker") + ->andWhere("r.requested_by = :requestor") + ->setParameter("speaker", $speaker) + ->setParameter("requestor", $requestor) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + } + + /** + * @param string $token + * @return ?SpeakerEditPermissionRequest + */ + public function getByToken(string $token): ?SpeakerEditPermissionRequest + { + return $this->getEntityManager() + ->createQueryBuilder() + ->select("r") + ->from(SpeakerEditPermissionRequest::class, "r") + ->where("r.hash = :hash") + ->setParameter("hash", SpeakerEditPermissionRequest::HashConfirmationToken($token)) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + } +} \ No newline at end of file diff --git a/app/Services/Model/ISpeakerService.php b/app/Services/Model/ISpeakerService.php index e219fd76..7c914174 100644 --- a/app/Services/Model/ISpeakerService.php +++ b/app/Services/Model/ISpeakerService.php @@ -11,6 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +use App\Models\Foundation\Summit\Speakers\SpeakerEditPermissionRequest; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; use models\main\EmailCreationRequest; @@ -130,4 +131,40 @@ interface ISpeakerService * @throws ValidationException */ public function sendSpeakerSummitAssistanceAnnouncementMail(Summit $summit, $assistance_id); + + /** + * @param int $requested_by_id + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function requestSpeakerEditPermission(int $requested_by_id, int $speaker_id):SpeakerEditPermissionRequest; + + /** + * @param int $requested_by_id + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function getSpeakerEditPermission(int $requested_by_id, int $speaker_id):SpeakerEditPermissionRequest; + + /** + * @param string $token + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function approveSpeakerEditPermission(string $token, int $speaker_id):SpeakerEditPermissionRequest; + + /** + * @param string $token + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function rejectSpeakerEditPermission(string $token, int $speaker_id):SpeakerEditPermissionRequest; } \ No newline at end of file diff --git a/app/Services/Model/PresentationService.php b/app/Services/Model/PresentationService.php index aec56ec5..1bb7a56e 100644 --- a/app/Services/Model/PresentationService.php +++ b/app/Services/Model/PresentationService.php @@ -23,9 +23,12 @@ use App\Models\Foundation\Summit\Events\Presentations\TrackQuestions\TrackAnswer use Illuminate\Support\Facades\Event; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; +use models\main\IEmailCreationRequestRepository; use models\main\IFolderRepository; use models\main\ITagRepository; use models\main\Member; +use models\main\PresentationCreatorNotificationEmailRequest; +use models\main\PresentationSpeakerNotificationEmailRequest; use models\summit\ISpeakerRepository; use models\summit\ISummitEventRepository; use models\summit\Presentation; @@ -77,6 +80,11 @@ final class PresentationService */ private $folder_repository; + /** + * @var IEmailCreationRequestRepository + */ + private $email_creation_request_repository; + /** * PresentationService constructor. * @param ISummitEventRepository $presentation_repository @@ -85,6 +93,7 @@ final class PresentationService * @param IFolderService $folder_service * @param IFileUploader $file_uploader * @param IFolderRepository $folder_repository + * @param IEmailCreationRequestRepository $email_creation_request_repository * @param ITransactionService $tx_service */ public function __construct @@ -95,6 +104,7 @@ final class PresentationService IFolderService $folder_service, IFileUploader $file_uploader, IFolderRepository $folder_repository, + IEmailCreationRequestRepository $email_creation_request_repository, ITransactionService $tx_service ) { @@ -105,6 +115,7 @@ final class PresentationService $this->folder_service = $folder_service; $this->file_uploader = $file_uploader; $this->folder_repository = $folder_repository; + $this->email_creation_request_repository = $email_creation_request_repository; } /** @@ -605,6 +616,23 @@ final class PresentationService $presentation->setProgress(Presentation::PHASE_COMPLETE); $presentation->setStatus(Presentation::STATUS_RECEIVED); + + // create email requests + + foreach($presentation->getSpeakers() as $speaker){ + if($speaker->getMemberId() == $presentation->getCreatorId()) continue; + + $email = new PresentationSpeakerNotificationEmailRequest(); + + $email->setSpeaker($speaker); + $email->setPresentation($presentation); + $this->email_creation_request_repository->add($email); + } + + $email = new PresentationCreatorNotificationEmailRequest(); + $email->setPresentation($presentation); + $this->email_creation_request_repository->add($email); + return $presentation; }); } diff --git a/app/Services/Model/SpeakerService.php b/app/Services/Model/SpeakerService.php index d9f8360f..995be606 100644 --- a/app/Services/Model/SpeakerService.php +++ b/app/Services/Model/SpeakerService.php @@ -1,5 +1,4 @@ speaker_organizational_role_repository = $speaker_organizational_role_repository; $this->speaker_involvement_repository = $speaker_involvement_repository; $this->file_uploader = $file_uploader; + $this->speaker_edit_permisssion_repository = $speaker_edit_permisssion_repository; } /** @@ -1018,4 +1032,107 @@ final class SpeakerService }); } + + /** + * @param int $requested_by_id + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function requestSpeakerEditPermission(int $requested_by_id, int $speaker_id): SpeakerEditPermissionRequest + { + return $this->tx_service->transaction(function () use ($requested_by_id, $speaker_id) { + + $requestor = $this->member_repository->getById($requested_by_id); + if(is_null($requestor)) + throw new EntityNotFoundException(); + + $speaker = $this->speaker_repository->getById($speaker_id); + if(is_null($speaker)) + throw new EntityNotFoundException(); + + $request = $this->speaker_edit_permisssion_repository->getBySpeakerAndRequestor($speaker, $requestor); + if(!is_null($request) && $request->isActionTaken()) + throw new ValidationException("there is another permission edit request already redeem!"); + + // build request with factory + $request = SpeakerEditPermissionRequestFactory::build($speaker, $requestor); + $token = $request->generateConfirmationToken(); + Mail::to($request->getSpeaker()->getEmail())->send(new SpeakerEditPermissionRequestedEmail($request, $token)); + $this->speaker_edit_permisssion_repository->add($request); + + return $request; + }); + } + + /** + * @param int $requested_by_id + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function getSpeakerEditPermission(int $requested_by_id, int $speaker_id): SpeakerEditPermissionRequest + { + return $this->tx_service->transaction(function () use ($requested_by_id, $speaker_id) { + + $requestor = $this->member_repository->getById($requested_by_id); + if(is_null($requestor)) + throw new EntityNotFoundException(); + + $speaker = $this->speaker_repository->getById($speaker_id); + if(is_null($speaker)) + throw new EntityNotFoundException(); + + $request = $this->speaker_edit_permisssion_repository->getBySpeakerAndRequestor($speaker, $requestor); + + if(is_null($request)) + throw new EntityNotFoundException(); + + return $request; + }); + } + + /** + * @param string $token + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function approveSpeakerEditPermission(string $token, int $speaker_id): SpeakerEditPermissionRequest + { + return $this->tx_service->transaction(function () use ($token, $speaker_id) { + $request = $this->speaker_edit_permisssion_repository->getByToken($token); + if(is_null($request)) + throw new EntityNotFoundException(); + if($request->isApproved()) + throw new ValidationException(); + $request->approve(); + Mail::to($request->getRequestedBy()->getEmail())->send(new SpeakerEditPermissionApprovedEmail($request)); + return $request; + }); + } + + /** + * @param string $token + * @param int $speaker_id + * @return SpeakerEditPermissionRequest + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function rejectSpeakerEditPermission(string $token, int $speaker_id): SpeakerEditPermissionRequest + { + return $this->tx_service->transaction(function () use ($token, $speaker_id) { + $request = $this->speaker_edit_permisssion_repository->getByToken($token); + if(is_null($request)) + throw new EntityNotFoundException(); + if($request->isActionTaken()) + throw new ValidationException(); + $request->reject(); + Mail::to($request->getRequestedBy()->getEmail())->send(new SpeakerEditPermissionRejectedEmail($request)); + return $request; + }); + } } \ No newline at end of file diff --git a/app/Services/ServicesProvider.php b/app/Services/ServicesProvider.php index 7dca82ef..5e3ac57b 100644 --- a/app/Services/ServicesProvider.php +++ b/app/Services/ServicesProvider.php @@ -13,6 +13,7 @@ **/ use App\Permissions\IPermissionsManager; use App\Permissions\PermissionsManager; +use App\Repositories\DoctrineRepository; use App\Services\Apis\CalendarSync\ICalendarSyncRemoteFacadeFactory; use App\Services\Apis\GoogleGeoCodingAPI; use App\Services\Apis\IGeoCodingAPI; @@ -48,6 +49,7 @@ use App\Services\SummitEventTypeService; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; use Illuminate\Support\ServiceProvider; +use models\utils\SilverstripeBaseModel; use ModelSerializers\BaseSerializerTypeSelector; use ModelSerializers\ISerializerTypeSelector; use services\apis\CalendarSync\CalendarSyncRemoteFacadeFactory; @@ -83,7 +85,7 @@ final class ServicesProvider extends ServiceProvider App::singleton(IPermissionsManager::class, PermissionsManager::class); App::singleton(\libs\utils\ITransactionService::class, function(){ - return new \services\utils\DoctrineTransactionService('ss'); + return new \services\utils\DoctrineTransactionService(SilverstripeBaseModel::EntityManager); }); App::singleton(\libs\utils\IEncryptionService::class, function(){ diff --git a/composer.json b/composer.json index 8a016572..4abba62c 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ "guzzlehttp/guzzle": "^6.3", "idct/sftp-client": "dev-master", "laravel-doctrine/extensions": "1.0.*", + "laravel-doctrine/migrations": "^1.2", "laravel-doctrine/orm": "1.4.*", "laravel/framework": "5.6.*", "laravel/tinker": "^1.0", diff --git a/composer.lock b/composer.lock index 7594b461..23523835 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "d9c8d933d23b34781d4010039da200c7", + "content-hash": "d03caf628ec9076f0ab50d8cdab0685d", "packages": [ { "name": "cocur/slugify", @@ -730,6 +730,80 @@ ], "time": "2014-09-09T13:34:57+00:00" }, + { + "name": "doctrine/migrations", + "version": "v1.8.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "215438c0eef3e5f9b7da7d09c6b90756071b43e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/215438c0eef3e5f9b7da7d09c6b90756071b43e6", + "reference": "215438c0eef3e5f9b7da7d09c6b90756071b43e6", + "shasum": "" + }, + "require": { + "doctrine/dbal": "~2.6", + "ocramius/proxy-manager": "^1.0|^2.0", + "php": "^7.1", + "symfony/console": "~3.3|^4.0" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "doctrine/orm": "~2.5", + "jdorn/sql-formatter": "~1.1", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "~7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/yaml": "~3.3|^4.0" + }, + "suggest": { + "jdorn/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "symfony/yaml": "Allows the use of yaml for migration configuration files." + }, + "bin": [ + "bin/doctrine-migrations" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "v1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\Migrations\\": "lib/Doctrine/DBAL/Migrations", + "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Michael Simonson", + "email": "contact@mikesimonson.com" + } + ], + "description": "Database Schema migrations using Doctrine DBAL", + "homepage": "https://www.doctrine-project.org/projects/migrations.html", + "keywords": [ + "database", + "migrations" + ], + "time": "2018-06-06T21:00:30+00:00" + }, { "name": "doctrine/orm", "version": "v2.6.3", @@ -1956,6 +2030,66 @@ ], "time": "2018-03-01T17:07:28+00:00" }, + { + "name": "laravel-doctrine/migrations", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/laravel-doctrine/migrations.git", + "reference": "3fa4ebc8cd5e4ce4c029c4c2a8d7cb5bf8f5f645" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel-doctrine/migrations/zipball/3fa4ebc8cd5e4ce4c029c4c2a8d7cb5bf8f5f645", + "reference": "3fa4ebc8cd5e4ce4c029c4c2a8d7cb5bf8f5f645", + "shasum": "" + }, + "require": { + "doctrine/migrations": "~1.8", + "illuminate/config": "~5.1", + "illuminate/console": "~5.1", + "illuminate/contracts": "~5.1", + "laravel-doctrine/orm": "~1.0", + "php": "^7.1" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelDoctrine\\Migrations\\MigrationsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelDoctrine\\Migrations\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Patrick Brouwers", + "email": "patrick@maatwebsite.nl" + } + ], + "description": "Doctrine Migrations for Laravel", + "keywords": [ + "data mapper", + "database", + "doctrine", + "laravel", + "migrations", + "orm" + ], + "time": "2018-09-03T11:46:53+00:00" + }, { "name": "laravel-doctrine/orm", "version": "v1.4.10", @@ -2577,6 +2711,126 @@ ], "time": "2019-02-16T20:54:15+00:00" }, + { + "name": "ocramius/package-versions", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" + }, + "require-dev": { + "composer/composer": "^1.6.3", + "doctrine/coding-standard": "^5.0.1", + "ext-zip": "*", + "infection/infection": "^0.7.1", + "phpunit/phpunit": "^7.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2019-02-21T12:16:21+00:00" + }, + { + "name": "ocramius/proxy-manager", + "version": "2.2.2", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/ProxyManager.git", + "reference": "14b137b06b0f911944132df9d51e445a35920ab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/14b137b06b0f911944132df9d51e445a35920ab1", + "reference": "14b137b06b0f911944132df9d51e445a35920ab1", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.1.3", + "php": "^7.2.0", + "zendframework/zend-code": "^3.3.0" + }, + "require-dev": { + "couscous/couscous": "^1.6.1", + "ext-phar": "*", + "humbug/humbug": "1.0.0-RC.0@RC", + "nikic/php-parser": "^3.1.1", + "padraic/phpunit-accelerator": "dev-master@DEV", + "phpbench/phpbench": "^0.12.2", + "phpstan/phpstan": "dev-master#856eb10a81c1d27c701a83f167dc870fd8f4236a as 0.9.999", + "phpstan/phpstan-phpunit": "dev-master#5629c0a1f4a9c417cb1077cf6693ad9753895761", + "phpunit/phpunit": "^6.4.3", + "squizlabs/php_codesniffer": "^2.9.1" + }, + "suggest": { + "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects", + "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)", + "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)", + "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "ProxyManager\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.io/" + } + ], + "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", + "homepage": "https://github.com/Ocramius/ProxyManager", + "keywords": [ + "aop", + "lazy loading", + "proxy", + "proxy pattern", + "service proxies" + ], + "time": "2018-09-27T13:45:01+00:00" + }, { "name": "paragonie/random_compat", "version": "v9.99.99", @@ -4908,6 +5162,113 @@ "environment" ], "time": "2019-01-29T11:11:52+00:00" + }, + { + "name": "zendframework/zend-code", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-code.git", + "reference": "c21db169075c6ec4b342149f446e7b7b724f95eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-code/zipball/c21db169075c6ec4b342149f446e7b7b724f95eb", + "reference": "c21db169075c6ec4b342149f446e7b7b724f95eb", + "shasum": "" + }, + "require": { + "php": "^7.1", + "zendframework/zend-eventmanager": "^2.6 || ^3.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "zendframework/zend-coding-standard": "^1.0.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "suggest": { + "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", + "zendframework/zend-stdlib": "Zend\\Stdlib component" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev", + "dev-develop": "3.4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Code\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides facilities to generate arbitrary code using an object oriented interface", + "homepage": "https://github.com/zendframework/zend-code", + "keywords": [ + "code", + "zf2" + ], + "time": "2018-08-13T20:36:59+00:00" + }, + { + "name": "zendframework/zend-eventmanager", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-eventmanager.git", + "reference": "a5e2583a211f73604691586b8406ff7296a946dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/a5e2583a211f73604691586b8406ff7296a946dd", + "reference": "a5e2583a211f73604691586b8406ff7296a946dd", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "athletic/athletic": "^0.1", + "container-interop/container-interop": "^1.1.0", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0" + }, + "suggest": { + "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev", + "dev-develop": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\EventManager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Trigger and listen to events within a PHP application", + "homepage": "https://github.com/zendframework/zend-eventmanager", + "keywords": [ + "event", + "eventmanager", + "events", + "zf2" + ], + "time": "2018-04-25T15:33:34+00:00" } ], "packages-dev": [ diff --git a/config/app.php b/config/app.php index 8b0525fa..9754b1ff 100644 --- a/config/app.php +++ b/config/app.php @@ -158,6 +158,7 @@ return [ libs\utils\CustomDoctrineServiceProvider::class, LaravelDoctrine\Extensions\BeberleiExtensionsServiceProvider::class, Sichikawa\LaravelSendgridDriver\SendgridTransportServiceProvider::class, + LaravelDoctrine\Migrations\MigrationsServiceProvider::class, ], /* diff --git a/config/database.php b/config/database.php index 86fbc787..edf0ea8c 100644 --- a/config/database.php +++ b/config/database.php @@ -26,7 +26,7 @@ return [ | */ - 'default' => env('DB_CONNECTION', 'openstackid_resources'), + 'default' => env('DB_CONNECTION', 'config'), /* |-------------------------------------------------------------------------- @@ -46,8 +46,8 @@ return [ 'connections' => [ - //primary DB - 'openstackid_resources' => array( + // config DB + 'config' => [ 'driver' => 'mysql', 'host' => env('DB_HOST'), 'database' => env('DB_DATABASE'), @@ -57,9 +57,9 @@ return [ 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', - ), - //secondary DB (SS OS) - 'ss' => array( + ], + // Model DB + 'model' => [ 'driver' => 'mysql', 'host' => env('SS_DB_HOST'), 'database' => env('SS_DATABASE'), @@ -69,7 +69,7 @@ return [ 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', - ), + ], ], diff --git a/config/doctrine.php b/config/doctrine.php index 1482454d..eacad589 100644 --- a/config/doctrine.php +++ b/config/doctrine.php @@ -21,10 +21,10 @@ return [ | */ 'managers' => [ - 'default' => [ + 'config' => [ 'dev' => env('APP_DEBUG', true), 'meta' => env('DOCTRINE_METADATA', 'annotations'), - 'connection' => env('DB_CONNECTION', 'openstackid_resources'), + 'connection' => env('DB_CONNECTION', 'config'), 'namespaces' => [ 'App' ], @@ -77,10 +77,10 @@ return [ 'enum' => 'string' ] ], - 'ss' => [ + 'model' => [ 'dev' => env('APP_DEBUG'), 'meta' => env('DOCTRINE_METADATA', 'annotations'), - 'connection' => 'ss', + 'connection' => 'model', 'namespaces' => [ 'App' ], diff --git a/config/migrations.php b/config/migrations.php new file mode 100644 index 00000000..f407c676 --- /dev/null +++ b/config/migrations.php @@ -0,0 +1,108 @@ + [ + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + 'table' => 'DoctrineMigration', + /* + |-------------------------------------------------------------------------- + | Migration Directory + |-------------------------------------------------------------------------- + | + | This directory is where all migrations will be stored for this entity + | manager. Use different directories for each entity manager. + | + */ + 'directory' => sprintf("%s/%s", database_path('migrations') ,"config"), + /* + |-------------------------------------------------------------------------- + | Migration Namespace + |-------------------------------------------------------------------------- + | + | This namespace will be used on all migrations. To prevent collisions, add + | the entity manager name (connection name). + | + */ + 'namespace' => 'Database\\Migrations\\Config', + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | Tables which are filtered by Regular Expression. You optionally + | exclude or limit to certain tables. The default will + | filter all tables. + | + */ + 'schema' => [ + 'filter' => '/^(?!password_resets|failed_jobs).*$/' + ] + ], + 'model' => [ + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + 'table' => 'DoctrineMigration', + /* + |-------------------------------------------------------------------------- + | Migration Directory + |-------------------------------------------------------------------------- + | + | This directory is where all migrations will be stored for this entity + | manager. Use different directories for each entity manager. + | + */ + 'directory' => sprintf("%s/%s", database_path('migrations') ,"model"), + /* + |-------------------------------------------------------------------------- + | Migration Namespace + |-------------------------------------------------------------------------- + | + | This namespace will be used on all migrations. To prevent collisions, add + | the entity manager name (connection name). + | + */ + 'namespace' => 'Database\\Migrations\\Model', + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | Tables which are filtered by Regular Expression. You optionally + | exclude or limit to certain tables. The default will + | filter all tables. + | + */ + 'schema' => [ + 'filter' => '/^(?!password_resets|failed_jobs).*$/' + ] + ], +]; diff --git a/config/queue.php b/config/queue.php index d0f732a6..411eebfe 100644 --- a/config/queue.php +++ b/config/queue.php @@ -15,7 +15,7 @@ return [ | */ - 'default' => env('QUEUE_DRIVER', 'sync'), + 'default' => env('QUEUE_DRIVER', 'redis'), /* |-------------------------------------------------------------------------- @@ -30,38 +30,11 @@ return [ 'connections' => [ - 'sync' => [ - 'driver' => 'sync', - ], - - 'database' => [ - 'driver' => 'database', - 'table' => 'jobs', - 'queue' => 'default', - 'expire' => 60, - ], - - 'beanstalkd' => [ - 'driver' => 'beanstalkd', - 'host' => 'localhost', - 'queue' => 'default', - 'ttr' => 60, - ], - - 'sqs' => [ - 'driver' => 'sqs', - 'key' => 'your-public-key', - 'secret' => 'your-secret-key', - 'prefix' => 'https://sqs.us-east-1.amazonaws.com/your-account-id', - 'queue' => 'your-queue-name', - 'region' => 'us-east-1', - ], - 'redis' => [ - 'driver' => 'redis', + 'driver' => 'redis', 'connection' => 'default', - 'queue' => 'default', - 'expire' => 60, + 'queue' => 'default', + 'expire' => 60, ], ], @@ -78,7 +51,7 @@ return [ */ 'failed' => [ - 'database' => env('DB_CONNECTION', 'mysql'), + 'database' => env('DB_CONNECTION', 'config'), 'table' => 'failed_jobs', ], diff --git a/database/migrations/2015_04_27_141330_create_apis_table.php b/database/migrations/2015_04_27_141330_create_apis_table.php deleted file mode 100644 index 13cc7257..00000000 --- a/database/migrations/2015_04_27_141330_create_apis_table.php +++ /dev/null @@ -1,38 +0,0 @@ -bigIncrements('id'); - $table->string('name',255)->unique(); - $table->text('description')->nullable(); - $table->boolean('active')->default(true); - $table->timestamps(); - }); - } - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::drop('apis'); - } - -} diff --git a/database/migrations/2015_04_27_141832_create_api_scopes_table.php b/database/migrations/2015_04_27_141832_create_api_scopes_table.php deleted file mode 100644 index ee13f3b3..00000000 --- a/database/migrations/2015_04_27_141832_create_api_scopes_table.php +++ /dev/null @@ -1,52 +0,0 @@ -bigIncrements('id'); - $table->string('name', 512); - $table->string('short_description', 512); - $table->text('description'); - $table->boolean('active')->default(true); - $table->boolean('default')->default(false); - $table->boolean('system')->default(false); - $table->timestamps(); - // FK - $table->bigInteger("api_id")->unsigned()->nullable(); - $table->index('api_id'); - $table->foreign('api_id') - ->references('id') - ->on('apis') - ->onDelete('cascade') - ->onUpdate('no action'); - }); - } - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('api_scopes', function ($table) { - $table->dropForeign('api_id'); - }); - - Schema::drop('api_scopes'); - } - -} diff --git a/database/migrations/2015_04_27_141848_create_api_endpoints_table.php b/database/migrations/2015_04_27_141848_create_api_endpoints_table.php deleted file mode 100644 index bb04af55..00000000 --- a/database/migrations/2015_04_27_141848_create_api_endpoints_table.php +++ /dev/null @@ -1,85 +0,0 @@ -bigIncrements('id'); - $table->boolean('active')->default(true); - $table->boolean('allow_cors')->default(true); - $table->boolean('allow_credentials')->default(true); - $table->text('description')->nullable(); - $table->string('name', 255)->unique(); - $table->timestamps(); - $table->text("route"); - $table->enum('http_method', array('GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT', 'OPTIONS', 'PATCH')); - $table->bigInteger("rate_limit")->unsigned()->nullable(); - //FK - $table->bigInteger("api_id")->unsigned(); - $table->index('api_id'); - $table->foreign('api_id') - ->references('id') - ->on('apis') - ->onDelete('cascade') - ->onUpdate('no action'); - }); - } - - if (!Schema::hasTable('api_endpoints')) { - Schema::create('endpoint_api_scopes', function ($table) { - $table->timestamps(); - $table->bigInteger("api_endpoint_id")->unsigned(); - $table->index('api_endpoint_id'); - $table->foreign('api_endpoint_id') - ->references('id') - ->on('api_endpoints') - ->onDelete('cascade') - ->onUpdate('no action');; - // FK 2 - $table->bigInteger("scope_id")->unsigned(); - $table->index('scope_id'); - $table->foreign('scope_id') - ->references('id') - ->on('api_scopes') - ->onDelete('cascade') - ->onUpdate('no action'); - }); - } - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('endpoint_api_scopes', function ($table) { - $table->dropForeign('api_endpoint_id'); - }); - - Schema::table('endpoint_api_scopes', function ($table) { - $table->dropForeign('scope_id'); - }); - - Schema::dropIfExists('endpoint_api_scopes'); - - Schema::table('api_endpoints', function ($table) { - $table->dropForeign('api_id'); - }); - - Schema::drop('api_endpoints'); - } - -} \ No newline at end of file diff --git a/database/migrations/2017_06_01_143808_create_table_ip_rate_limit_route.php b/database/migrations/2017_06_01_143808_create_table_ip_rate_limit_route.php deleted file mode 100644 index 5d3c868a..00000000 --- a/database/migrations/2017_06_01_143808_create_table_ip_rate_limit_route.php +++ /dev/null @@ -1,38 +0,0 @@ -bigIncrements('id'); - $table->string('ip', 255); - $table->text("route"); - $table->boolean('active')->default(true); - $table->enum('http_method', array('GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT', 'OPTIONS', 'PATCH')); - $table->bigInteger("rate_limit")->unsigned()->default(0); - $table->bigInteger("rate_limit_decay")->unsigned()->default(0); - $table->timestamps(); - }); - } - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::drop('ip_rate_limit_routes'); - } -} diff --git a/database/migrations/2017_06_01_144624_update_table_api_endpoint.php b/database/migrations/2017_06_01_144624_update_table_api_endpoint.php deleted file mode 100644 index cd7b67ba..00000000 --- a/database/migrations/2017_06_01_144624_update_table_api_endpoint.php +++ /dev/null @@ -1,53 +0,0 @@ -dropColumn("rate_limit"); - }); - } - - if (!Schema::hasColumn('api_endpoints', 'rate_limit')) { - Schema::table('api_endpoints', function (Blueprint $table) { - $table->bigInteger("rate_limit")->unsigned()->default(0); - }); - } - - if (!Schema::hasColumn('api_endpoints', 'rate_limit_decay')) { - Schema::table('api_endpoints', function (Blueprint $table) { - $table->bigInteger("rate_limit_decay")->unsigned()->default(0); - }); - } - - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('api_endpoints', function(Blueprint $table) - { - $table->dropColumn('rate_limit_decay'); - $table->dropColumn("rate_limit"); - }); - - Schema::table('api_endpoints', function(Blueprint $table) - { - $table->bigInteger("rate_limit")->unsigned()->nullable(); - }); - } -} diff --git a/database/migrations/config/.gitkeep b/database/migrations/config/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/database/migrations/config/.gitkeep @@ -0,0 +1 @@ + diff --git a/database/migrations/config/Version20190422160409.php b/database/migrations/config/Version20190422160409.php new file mode 100644 index 00000000..8027e43b --- /dev/null +++ b/database/migrations/config/Version20190422160409.php @@ -0,0 +1,136 @@ +hasTable("apis")) { + $builder->create('apis', function (Table $table) { + $table->bigIncrements('id'); + $table->string('name',255); + $table->unique('name'); + $table->text('description')->setNotnull(false); + $table->boolean('active')->setDefault(true); + $table->timestamp('created_at')->setDefault('CURRENT_TIMESTAMP'); + $table->timestamp('updated_at')->setDefault('CURRENT_TIMESTAMP'); + }); + } + + if(!$builder->hasTable("api_scopes")) { + $builder->create('api_scopes', function (Table $table) { + $table->bigIncrements('id'); + $table->string('name', 512); + $table->string('short_description', 512); + $table->text('description'); + $table->boolean('active')->setNotnull(true); + $table->boolean('default')->setNotnull(false); + $table->boolean('system')->setNotnull(false); + $table->timestamp('created_at')->setDefault('CURRENT_TIMESTAMP'); + $table->timestamp('updated_at')->setDefault('CURRENT_TIMESTAMP'); + // FK + $table->bigInteger("api_id")->setUnsigned(true)->setNotnull(false); + $table->index('api_id'); + $table->foreign('apis', 'api_id', 'id'); + }); + } + + if(!$builder->hasTable("api_endpoints")) { + $builder->create('api_endpoints', function (Table $table) { + $table->bigIncrements('id'); + $table->boolean('active')->setDefault(true); + $table->boolean('allow_cors')->setDefault(true); + $table->boolean('allow_credentials')->setDefault(true); + $table->text('description')->setNotnull(false); + $table->string('name', 255); + $table->unique('name'); + $table->timestamp('created_at')->setDefault('CURRENT_TIMESTAMP'); + $table->timestamp('updated_at')->setDefault('CURRENT_TIMESTAMP'); + $table->text("route"); + $table->getTable()->addColumn('http_method', 'array'); + $table->bigInteger("rate_limit")->setUnsigned(true)->setDefault(0); + $table->bigInteger("rate_limit_decay")->setUnsigned(true)->setDefault(0); + //FK + $table->bigInteger("api_id")->setUnsigned(true); + $table->index('api_id'); + $table->foreign('apis','api_id', 'id'); + + }); + } + + if(!$builder->hasTable("endpoint_api_scopes")) { + $builder->create('endpoint_api_scopes', function (Table $table) { + $table->bigIncrements('id'); + $table->timestamp('created_at')->setDefault('CURRENT_TIMESTAMP'); + $table->timestamp('updated_at')->setDefault('CURRENT_TIMESTAMP'); + $table->bigInteger("api_endpoint_id")->setUnsigned(true); + $table->index('api_endpoint_id'); + $table->foreign('api_endpoints','api_endpoint_id', 'id'); + // FK 2 + $table->bigInteger("scope_id")->setUnsigned(true); + $table->index('scope_id'); + $table->foreign('api_scopes','scope_id', 'id'); + + }); + } + + if(!$builder->hasTable("ip_rate_limit_routes")) { + $builder->create('ip_rate_limit_routes', function (Table $table) { + $table->bigIncrements('id'); + $table->string('ip',255); + $table->text("route"); + $table->boolean('active')->setDefault(true); + //$table->getTable()->addColumn('http_method', enum ('GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT', 'OPTIONS', 'PATCH')); + $table->getTable()->addColumn('http_method', 'array'); + $table->bigInteger("rate_limit")->setUnsigned(true)->setDefault(0); + $table->bigInteger("rate_limit_decay")->setUnsigned(true)->setDefault(0); + $table->timestamp('created_at')->setDefault('CURRENT_TIMESTAMP'); + $table->timestamp('updated_at')->setDefault('CURRENT_TIMESTAMP'); + + }); + } + + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $builder = new Builder($schema); + + $builder->dropIfExists('endpoint_api_scopes'); + + $builder->dropIfExists('apis'); + + $builder->dropIfExists('api_scopes'); + + $builder->dropIfExists('api_endpoints'); + + $builder->dropIfExists('ip_rate_limit_routes'); + + } +} diff --git a/database/migrations/model/.gitkeep b/database/migrations/model/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/database/migrations/model/.gitkeep @@ -0,0 +1 @@ + diff --git a/database/migrations/model/Version20190422151949.php b/database/migrations/model/Version20190422151949.php new file mode 100644 index 00000000..32c51ca3 --- /dev/null +++ b/database/migrations/model/Version20190422151949.php @@ -0,0 +1,58 @@ +hasTable("SpeakerEditPermissionRequest")) { + $builder->create('SpeakerEditPermissionRequest', function (Table $table) { + $table->increments('ID'); + $table->integer("SpeakerID"); + $table->integer("RequestedByID"); + $table->boolean("Approved")->setDefault(false); + $table->dateTime("ApprovedDate")->setNotnull(false); + $table->dateTime("Created")->setNotnull(true); + $table->dateTime("LastEdited")->setNotnull(true); + $table->text("Hash"); + $table->foreign("PresentationSpeaker", "SpeakerID", "ID"); + $table->foreign("Member", "RequestedByID", "ID"); + }); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $builder = new Builder($schema); + + + if($builder->hasTable("SpeakerEditPermissionRequest")) + $builder->drop('SpeakerEditPermissionRequest'); + } +} diff --git a/database/migrations/model/Version20190506153014.php b/database/migrations/model/Version20190506153014.php new file mode 100644 index 00000000..ded26cb3 --- /dev/null +++ b/database/migrations/model/Version20190506153014.php @@ -0,0 +1,47 @@ +hasTable("PresentationCreatorNotificationEmailRequest")) { + $this->addSql("CREATE TABLE PresentationCreatorNotificationEmailRequest (PresentationID INT DEFAULT NULL, ID INT NOT NULL, INDEX IDX_B302D49879B1711B (PresentationID), PRIMARY KEY(ID)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;"); + $this->addSql("ALTER TABLE PresentationCreatorNotificationEmailRequest ADD CONSTRAINT FK_B302D49879B1711B FOREIGN KEY (PresentationID) REFERENCES Presentation (ID);"); + $this->addSql("ALTER TABLE PresentationCreatorNotificationEmailRequest ADD CONSTRAINT FK_B302D49811D3633A FOREIGN KEY (ID) REFERENCES EmailCreationRequest (ID) ON DELETE CASCADE"); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $builder = new Builder($schema); + $this->addSql("ALTER TABLE `PresentationCreatorNotificationEmailRequest` DROP FOREIGN KEY `FK_B302D49879B1711B`;"); + $this->addSql("ALTER TABLE `PresentationCreatorNotificationEmailRequest` DROP FOREIGN KEY `FK_B302D49811D3633A`;"); + $builder->dropIfExists('PresentationCreatorNotificationEmailRequest'); + } +} diff --git a/database/migrations/model/Version20190506153909.php b/database/migrations/model/Version20190506153909.php new file mode 100644 index 00000000..c2c3d1fe --- /dev/null +++ b/database/migrations/model/Version20190506153909.php @@ -0,0 +1,49 @@ +hasTable("PresentationSpeakerNotificationEmailRequest")){ + $this->addSql("CREATE TABLE PresentationSpeakerNotificationEmailRequest (SpeakerID INT DEFAULT NULL, PresentationID INT DEFAULT NULL, ID INT NOT NULL, INDEX IDX_2BFDC212FEC5CBA6 (SpeakerID), INDEX IDX_2BFDC21279B1711B (PresentationID), PRIMARY KEY(ID)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; "); + $this->addSql("ALTER TABLE PresentationSpeakerNotificationEmailRequest ADD CONSTRAINT FK_2BFDC212FEC5CBA6 FOREIGN KEY (SpeakerID) REFERENCES PresentationSpeaker (ID); "); + $this->addSql("ALTER TABLE PresentationSpeakerNotificationEmailRequest ADD CONSTRAINT FK_2BFDC21279B1711B FOREIGN KEY (PresentationID) REFERENCES Presentation (ID);"); + $this->addSql("ALTER TABLE PresentationSpeakerNotificationEmailRequest ADD CONSTRAINT FK_2BFDC21211D3633A FOREIGN KEY (ID) REFERENCES EmailCreationRequest (ID) ON DELETE CASCADE;"); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $builder = new Builder($schema); + $this->addSql("ALTER TABLE `PresentationSpeakerNotificationEmailRequest` DROP FOREIGN KEY `FK_2BFDC212FEC5CBA6`;"); + $this->addSql("ALTER TABLE `PresentationSpeakerNotificationEmailRequest` DROP FOREIGN KEY `FK_2BFDC21279B1711B`;"); + $this->addSql("ALTER TABLE `PresentationSpeakerNotificationEmailRequest` DROP FOREIGN KEY `FK_2BFDC21211D3633A`;"); + $builder->dropIfExists('PresentationSpeakerNotificationEmailRequest'); + } +} diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 52f35d5c..b1b16a8f 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -355,6 +355,24 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::ReadAllSummitData, $current_realm) ], ), + [ + 'name' => 'request-edit-speaker-permission', + 'route' => '/api/v1/speakers/{speaker_id}/edit-permission', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SummitScopes::WriteSpeakersData, $current_realm), + sprintf(SummitScopes::WriteSummitData, $current_realm) + ], + ], + [ + 'name' => 'get-edit-speaker-permission', + 'route' => '/api/v1/speakers/{speaker_id}/edit-permission', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SummitScopes::ReadSummitData, $current_realm), + sprintf(SummitScopes::ReadAllSummitData, $current_realm) + ], + ], [ 'name' => 'get-my-speaker-presentations-by-role-by-selection-plan', 'route' => '/api/v1/speakers/me/presentations/{role}/selection-plans/{selection_plan_id}', diff --git a/database/seeds/summit/DefaultEventTypesSeeder.php b/database/seeds/summit/DefaultEventTypesSeeder.php index 7ce377b0..6ac2dc93 100644 --- a/database/seeds/summit/DefaultEventTypesSeeder.php +++ b/database/seeds/summit/DefaultEventTypesSeeder.php @@ -33,7 +33,7 @@ final class DefaultEventTypesSeeder extends Seeder public function run() { - $em = Registry::getManager('ss'); + $em = Registry::getManager(\models\utils\SilverstripeBaseModel::EntityManager); $repo = $em->getRepository(DefaultSummitEventType::class); // presentation default types diff --git a/readme.md b/readme.md index 126d6b0d..046034dd 100644 --- a/readme.md +++ b/readme.md @@ -3,7 +3,7 @@ ## Prerequisites * LAMP/LEMP environment - * PHP >= 5.4.0 + * PHP >= 7.1 * Redis * composer (https://getcomposer.org/) @@ -32,4 +32,28 @@ Laravel may require some permissions to be configured: folders within storage an ## create SS schema -php artisan doctrine:schema:create --sql --em=ss > ss.sql \ No newline at end of file +php artisan doctrine:schema:create --sql --em=model > ss.sql + +## Doctrine Migrations + +# For Config Storage + +## create new migration +php artisan doctrine:migrations:generate --connection=config --create= + +## check status +php artisan doctrine:migrations:status --connection=config + +## run +php artisan doctrine:migrations:migrate --connection=config + +# For Model Storage + +## create new migrations +php artisan doctrine:migrations:generate --connection=model --create= + +## check status +php artisan doctrine:migrations:status --connection=model + +## run +php artisan doctrine:migrations:migrate --connection=model \ No newline at end of file diff --git a/resources/views/emails/speakers/permissioneditapproved.blade.php b/resources/views/emails/speakers/permissioneditapproved.blade.php new file mode 100644 index 00000000..ad75aa51 --- /dev/null +++ b/resources/views/emails/speakers/permissioneditapproved.blade.php @@ -0,0 +1,7 @@ +

+ Dear {{ $request->getRequestedBy()->getFullName() }}, + User {{ $request->getSpeaker()->getFullName() }} has approved your request to edit his/her Speaker Profile. +

+

+ The OpenStack Team. +

\ No newline at end of file diff --git a/resources/views/emails/speakers/permissioneditrejected.blade.php b/resources/views/emails/speakers/permissioneditrejected.blade.php new file mode 100644 index 00000000..3d600feb --- /dev/null +++ b/resources/views/emails/speakers/permissioneditrejected.blade.php @@ -0,0 +1,7 @@ +

+ Dear {{ $request->getRequestedBy()->getFullName() }}, + User {{ $request->getSpeaker()->getFullName() }} has rejected your request to edit his/her Speaker Profile. +

+

+ The OpenStack Team. +

\ No newline at end of file diff --git a/resources/views/emails/speakers/permissioneditrequested.blade.php b/resources/views/emails/speakers/permissioneditrequested.blade.php new file mode 100644 index 00000000..9bb8b35f --- /dev/null +++ b/resources/views/emails/speakers/permissioneditrequested.blade.php @@ -0,0 +1,8 @@ +

+ Dear {{ $request->getSpeaker()->getFullName() }}, + User {{ $request->getRequestedBy()->getFullName() }} has requested to be able to edit your Speaker Profile. + To Allow that please click on the following link Allow. +

+

+ The OpenStack Team. +

\ No newline at end of file diff --git a/resources/views/speakers/edit_permissions/approved.blade.php b/resources/views/speakers/edit_permissions/approved.blade.php new file mode 100644 index 00000000..07552086 --- /dev/null +++ b/resources/views/speakers/edit_permissions/approved.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') +@section('title', 'Speaker Edit Permission - Approved') +@section('content') +
+

+ Your Speaker Edit Profile Permission Request was Approved!. +

+
+@stop \ No newline at end of file diff --git a/resources/views/speakers/edit_permissions/approved_error.blade.php b/resources/views/speakers/edit_permissions/approved_error.blade.php new file mode 100644 index 00000000..fcd61d74 --- /dev/null +++ b/resources/views/speakers/edit_permissions/approved_error.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') +@section('title', 'Speaker Edit Permission - Approved Error') +@section('content') +
+

+ There was a problem with your request. +

+
+@stop \ No newline at end of file diff --git a/resources/views/speakers/edit_permissions/approved_validation_error.blade.php b/resources/views/speakers/edit_permissions/approved_validation_error.blade.php new file mode 100644 index 00000000..c013e573 --- /dev/null +++ b/resources/views/speakers/edit_permissions/approved_validation_error.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') +@section('title', 'Speaker Edit Permission - Approved Validation Error') +@section('content') +
+

+ There was a problem with your request. the permission request its already approved!. +

+
+@stop \ No newline at end of file diff --git a/resources/views/speakers/edit_permissions/rejected.blade.php b/resources/views/speakers/edit_permissions/rejected.blade.php new file mode 100644 index 00000000..7a9cca96 --- /dev/null +++ b/resources/views/speakers/edit_permissions/rejected.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') +@section('title', 'Speaker Edit Permission - Rejected') +@section('content') +
+

+ Your Speaker Edit Profile Permission Request was Rejected!. +

+
+@stop \ No newline at end of file diff --git a/resources/views/speakers/edit_permissions/rejected_error.blade.php b/resources/views/speakers/edit_permissions/rejected_error.blade.php new file mode 100644 index 00000000..cd4ec893 --- /dev/null +++ b/resources/views/speakers/edit_permissions/rejected_error.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') +@section('title', 'Speaker Edit Permission - Rejected Error') +@section('content') +
+

+ There was a problem with your request. +

+
+@stop \ No newline at end of file diff --git a/resources/views/speakers/edit_permissions/rejected_validation_error.blade.php b/resources/views/speakers/edit_permissions/rejected_validation_error.blade.php new file mode 100644 index 00000000..a153ae60 --- /dev/null +++ b/resources/views/speakers/edit_permissions/rejected_validation_error.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') +@section('title', 'Speaker Edit Permission - Rejected Validation Error') +@section('content') +
+

+ There was a problem with your request. the permission request its already redeem !. +

+
+@stop \ No newline at end of file diff --git a/tests/OAuth2SpeakersApiTest.php b/tests/OAuth2SpeakersApiTest.php index 85033512..001f6e43 100644 --- a/tests/OAuth2SpeakersApiTest.php +++ b/tests/OAuth2SpeakersApiTest.php @@ -622,4 +622,64 @@ final class OAuth2SpeakersApiTest extends ProtectedApiTest $presentations = json_decode($content); $this->assertTrue(!is_null($presentations)); } + + public function testRequestSpeakerEditPermission() + { + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $params = [ + 'speaker_id' => 9 + ]; + + $response = $this->action + ( + "PUT", + "OAuth2SummitSpeakersApiController@requestSpeakerEditPermission", + $params, + [], + [], + [], + $headers + ); + + $this->assertResponseStatus(201); + $content = $response->getContent(); + $request = json_decode($content); + $this->assertTrue($request->id > 0); + return $request; + } + + public function testGetRequestSpeakerEditPermission() + { + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $params = [ + 'speaker_id' => 9 + ]; + + $response = $this->action + ( + "GET", + "OAuth2SummitSpeakersApiController@getSpeakerEditPermission", + $params, + [], + [], + [], + $headers + ); + + $this->assertResponseStatus(200); + $content = $response->getContent(); + $request = json_decode($content); + $this->assertTrue($request->id > 0); + return $request; + } } \ No newline at end of file diff --git a/tests/ProtectedApiTest.php b/tests/ProtectedApiTest.php index 90b13375..a863dfb6 100644 --- a/tests/ProtectedApiTest.php +++ b/tests/ProtectedApiTest.php @@ -139,7 +139,6 @@ abstract class ProtectedApiTest extends \Tests\BrowserKitTestCase { $app = parent::createApplication(); App::singleton('App\Models\ResourceServer\IAccessTokenService', 'AccessTokenServiceStub'); - return $app; }