diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php index 1486858b..4d82f1c0 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php @@ -13,11 +13,14 @@ **/ use App\Http\Exceptions\HTTP403ForbiddenException; use App\Http\Utils\EpochCellFormatter; -use App\Services\Model\ISponsorBadgeScanService; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Request; +use models\exceptions\EntityNotFoundException; +use models\summit\ISponsorUserInfoGrantRepository; use Illuminate\Support\Facades\Input; use models\exceptions\ValidationException; use models\oauth2\IResourceServerContext; -use models\summit\ISponsorBadgeScanRepository; +use App\Services\Model\ISponsorUserInfoGrantService; use models\summit\ISummitRepository; use models\summit\Summit; use models\utils\IEntity; @@ -32,7 +35,7 @@ final class OAuth2SummitBadgeScanApiController extends OAuth2ProtectedController { /** - * @var ISponsorBadgeScanService + * @var ISponsorUserInfoGrantService */ private $service; @@ -43,17 +46,17 @@ final class OAuth2SummitBadgeScanApiController /** * OAuth2SummitBadgeScanApiController constructor. - * @param ISponsorBadgeScanRepository $repository + * @param ISponsorUserInfoGrantRepository $repository * @param ISummitRepository $summit_repository * @param IResourceServerContext $resource_server_context - * @param ISponsorBadgeScanService $service + * @param ISponsorUserInfoGrantService $service */ public function __construct ( - ISponsorBadgeScanRepository $repository, + ISponsorUserInfoGrantRepository $repository, ISummitRepository $summit_repository, IResourceServerContext $resource_server_context, - ISponsorBadgeScanService $service + ISponsorUserInfoGrantService $service ) { parent::__construct($resource_server_context); @@ -89,6 +92,49 @@ final class OAuth2SummitBadgeScanApiController return $this->service->addBadgeScan($summit, $current_member, $payload); } + /** + * @param $summit_id + * @param $sponsor_id + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function addGrant($summit_id, $sponsor_id){ + try{ + $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->getResourceServerContext())->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $current_member = $this->resource_server_context->getCurrentUser(); + if (is_null($current_member)) throw new HTTP403ForbiddenException(); + + $grant = $this->service->addGrant($summit, intval($sponsor_id), $current_member); + return $this->created(SerializerRegistry::getInstance()->getSerializer + ( + $grant, + $this->addSerializerType() + )->serialize(Request::input('expand', ''))); + } + catch (ValidationException $ex) { + Log::warning($ex); + return $this->error412(array($ex->getMessage())); + } + catch(EntityNotFoundException $ex) + { + Log::warning($ex); + return $this->error404(array('message'=> $ex->getMessage())); + } + catch (\HTTP401UnauthorizedException $ex) { + Log::warning($ex); + return $this->error401(); + } + catch (HTTP403ForbiddenException $ex) { + Log::warning($ex); + return $this->error403(); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + /** * @return ISummitRepository */ diff --git a/app/Http/routes.php b/app/Http/routes.php index 4bb6f1ee..cbd205c8 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -692,6 +692,9 @@ Route::group([ Route::get('', ['middleware' => 'auth.user', 'uses' => 'OAuth2SummitSponsorApiController@getAllBySummit']); Route::post('', ['middleware' => 'auth.user', 'uses' => 'OAuth2SummitSponsorApiController@add']); Route::group(['prefix' => '{sponsor_id}'], function () { + Route::group(['prefix' => 'user-info-grants'], function () { + Route::post('me', ['uses' => 'OAuth2SummitBadgeScanApiController@addGrant']); + }); Route::get('', ['middleware' => 'auth.user', 'uses' => 'OAuth2SummitSponsorApiController@get']); Route::put('', ['middleware' => 'auth.user', 'uses' => 'OAuth2SummitSponsorApiController@update']); Route::delete('', ['middleware' => 'auth.user', 'uses' => 'OAuth2SummitSponsorApiController@delete']); @@ -745,9 +748,8 @@ Route::group([ }); }); - // badge-feature-types + // badge-scans Route::group(['prefix' => 'badge-scans'], function () { - Route::get('me','OAuth2SummitBadgeScanApiController@getAllMyBadgeScans' ); Route::get('', 'OAuth2SummitBadgeScanApiController@getAllBySummit'); Route::get('csv','OAuth2SummitBadgeScanApiController@getAllBySummitCSV'); diff --git a/app/ModelSerializers/SerializerRegistry.php b/app/ModelSerializers/SerializerRegistry.php index 9bea4e58..3bf31d44 100644 --- a/app/ModelSerializers/SerializerRegistry.php +++ b/app/ModelSerializers/SerializerRegistry.php @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - use App\ModelSerializers\CCLA\TeamSerializer; use App\ModelSerializers\FileSerializer; use App\ModelSerializers\ISummitAttendeeTicketSerializerTypes; @@ -65,6 +64,7 @@ use App\ModelSerializers\Summit\Registration\SummitAttendeeCSVSerializer; use App\ModelSerializers\Summit\Registration\SummitAttendeeTicketCSVSerializer; use App\ModelSerializers\Summit\SponsorBadgeScanCSVSerializer; use App\ModelSerializers\Summit\SponsorBadgeScanSerializer; +use App\ModelSerializers\Summit\SponsorUserInfoGrantSerializer; use App\ModelSerializers\Summit\StripePaymentProfileSerializer; use App\ModelSerializers\Summit\SummitAttendeeBadgeSerializer; use App\ModelSerializers\Summit\RSVP\Templates\RSVPDropDownQuestionTemplateSerializer; @@ -298,11 +298,17 @@ final class SerializerRegistry ]; $this->registry['SummitAttendeeBadge'] = SummitAttendeeBadgeSerializer::class; + $this->registry['SponsorBadgeScan'] = [ self::SerializerType_Public => SponsorBadgeScanSerializer::class, self::SerializerType_CSV => SponsorBadgeScanCSVSerializer::class, ]; + $this->registry['SponsorUserInfoGrant'] = [ + self::SerializerType_Public => SponsorUserInfoGrantSerializer::class, + self::SerializerType_CSV => SponsorUserInfoGrantSerializer::class, + ]; + $this->registry['SummitAttendeeTicketTax'] = SummitAttendeeTicketTaxSerializer::class; // summit sponsors diff --git a/app/ModelSerializers/Summit/Registration/SponsorBadgeScanCSVSerializer.php b/app/ModelSerializers/Summit/Registration/SponsorBadgeScanCSVSerializer.php index 16602e6d..e2dbd84f 100644 --- a/app/ModelSerializers/Summit/Registration/SponsorBadgeScanCSVSerializer.php +++ b/app/ModelSerializers/Summit/Registration/SponsorBadgeScanCSVSerializer.php @@ -25,8 +25,12 @@ final class SponsorBadgeScanCSVSerializer extends AbstractSerializer 'ScanDate' => 'scan_date:datetime_epoch', 'QRCode' => 'qr_code:json_string', 'SponsorId' => 'sponsor_id:json_int', - 'UserId' => 'user_id:json_int', + 'UserId' => 'scanned_by_id:json_int', 'BadgeId' => 'badge_id:json_int', + 'AttendeeFirstName' => 'attendee_first_name:json_string', + 'AttendeeLastName' => 'attendee_last_name:json_string', + 'AttendeeEmail' => 'attendee_email:json_string', + 'AttendeeCompany' => 'attendee_company:json_string', ]; /** @@ -41,13 +45,6 @@ final class SponsorBadgeScanCSVSerializer extends AbstractSerializer $scan = $this->object; if (!$scan instanceof SponsorBadgeScan) return []; $values = parent::serialize($expand, $fields, $relations, $params); - - $attendee = $scan->getBadge()->getTicket()->getOwner(); - - $values['attendee_first_name'] = $attendee->hasMember() ? $attendee->getMember()->getFirstName() : $attendee->getFirstName(); - $values['attendee_last_name'] = $attendee->hasMember() ? $attendee->getMember()->getLastName() :$attendee->getSurname(); - $values['attendee_email'] = $attendee->getEmail(); - $values['attendee_company'] = $attendee->getCompanyName(); return $values; } } \ No newline at end of file diff --git a/app/ModelSerializers/Summit/Registration/SponsorBadgeScanSerializer.php b/app/ModelSerializers/Summit/Registration/SponsorBadgeScanSerializer.php index 02fa3d75..c9874fdf 100644 --- a/app/ModelSerializers/Summit/Registration/SponsorBadgeScanSerializer.php +++ b/app/ModelSerializers/Summit/Registration/SponsorBadgeScanSerializer.php @@ -22,11 +22,12 @@ use ModelSerializers\SilverStripeSerializer; final class SponsorBadgeScanSerializer extends SilverStripeSerializer { + protected static $array_mappings = [ 'ScanDate' => 'scan_date:datetime_epoch', 'QRCode' => 'qr_code:json_string', 'SponsorId' => 'sponsor_id:json_int', - 'UserId' => 'user_id:json_int', + 'UserId' => 'scanned_by_id:json_int', 'BadgeId' => 'badge_id:json_int', ]; @@ -53,10 +54,10 @@ final class SponsorBadgeScanSerializer extends SilverStripeSerializer $values['sponsor'] = SerializerRegistry::getInstance()->getSerializer($scan->getSponsor())->serialize(AbstractSerializer::filterExpandByPrefix($expand, "sponsor")); } break; - case 'user': { + case 'scanned_by_id': { if(!$scan->hasUser()) continue; - unset($values['user_id']); - $values['user'] = SerializerRegistry::getInstance()->getSerializer($scan->getUser())->serialize(AbstractSerializer::filterExpandByPrefix($expand, "user")); + unset($values['scanned_by_id']); + $values['scanned_by'] = SerializerRegistry::getInstance()->getSerializer($scan->getUser())->serialize(AbstractSerializer::filterExpandByPrefix($expand, "user")); } break; case 'badge': { diff --git a/app/ModelSerializers/Summit/Registration/SponsorUserInfoGrantSerializer.php b/app/ModelSerializers/Summit/Registration/SponsorUserInfoGrantSerializer.php new file mode 100644 index 00000000..fb968e4f --- /dev/null +++ b/app/ModelSerializers/Summit/Registration/SponsorUserInfoGrantSerializer.php @@ -0,0 +1,30 @@ + 'scan_date:datetime_epoch', + 'SponsorId' => 'sponsor_id:json_int', + 'AllowedUserId' => 'allowed_user_id:json_int', + 'AttendeeFirstName' => 'attendee_first_name:json_string', + 'AttendeeLastName' => 'attendee_last_name:json_string', + 'AttendeeEmail' => 'attendee_email:json_string', + 'AttendeeCompany' => 'attendee_company:json_string', + ]; +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Factories/SponsorUserInfoGrantFactory.php b/app/Models/Foundation/Summit/Factories/SponsorUserInfoGrantFactory.php new file mode 100644 index 00000000..7cc874f6 --- /dev/null +++ b/app/Models/Foundation/Summit/Factories/SponsorUserInfoGrantFactory.php @@ -0,0 +1,56 @@ + 'sponsor', 'getUserId' => 'user', 'getBadgeId' => 'badge', ]; protected $hasPropertyMappings = [ - 'hasSponsor' => 'sponsor', 'hasUser' => 'user', 'hasBadge' => 'badge', ]; @@ -45,13 +43,6 @@ class SponsorBadgeScan extends SilverstripeBaseModel */ private $qr_code; - /** - * @ORM\ManyToOne(targetEntity="models\summit\Sponsor", inversedBy="badge_scans") - * @ORM\JoinColumn(name="SponsorID", referencedColumnName="ID") - * @var Sponsor - */ - private $sponsor; - /** * @var \DateTime * @ORM\Column(name="ScanDate", type="datetime") @@ -152,4 +143,24 @@ class SponsorBadgeScan extends SilverstripeBaseModel $this->scan_date = $scan_date; } + public function getAttendeeFirstName():?string{ + $attendee = $this->getBadge()->getTicket()->getOwner(); + return $attendee->hasMember() ? $attendee->getMember()->getFirstName() : $attendee->getFirstName(); + } + + public function getAttendeeLastName():?string{ + $attendee = $this->getBadge()->getTicket()->getOwner(); + return $attendee->hasMember() ? $attendee->getMember()->getLastName() :$attendee->getSurname(); + } + + public function getAttendeeEmail():?string{ + $attendee = $this->getBadge()->getTicket()->getOwner(); + return $attendee->getEmail(); + } + + public function getAttendeeCompany():?string{ + $attendee = $this->getBadge()->getTicket()->getOwner(); + $attendee->getCompanyName(); + } + } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Registration/SponsorUserInfoGrant.php b/app/Models/Foundation/Summit/Registration/SponsorUserInfoGrant.php new file mode 100644 index 00000000..e3c4d400 --- /dev/null +++ b/app/Models/Foundation/Summit/Registration/SponsorUserInfoGrant.php @@ -0,0 +1,102 @@ + 'sponsor', + 'getAllowedUserId' => 'allowed_user', + ]; + + protected $hasPropertyMappings = [ + 'hasSponsor' => 'sponsor', + 'hasAllowedUser' => 'allowed_user', + ]; + + /** + * @return Sponsor + */ + public function getSponsor(): Sponsor + { + return $this->sponsor; + } + + /** + * @param Sponsor $sponsor + */ + public function setSponsor(Sponsor $sponsor): void + { + $this->sponsor = $sponsor; + } + + /** + * @return Member|null + */ + public function getAllowedUser(): ?Member + { + return $this->allowed_user; + } + + /** + * @param Member|null $allowed_user + */ + public function setAllowedUser(?Member $allowed_user): void + { + $this->allowed_user = $allowed_user; + } + + public function getAttendeeFirstName():?string{ + return $this->allowed_user->getFirstName(); + } + + public function getAttendeeLastName():?string{ + return $this->allowed_user->getLastName(); + } + + public function getAttendeeEmail():?string{ + return $this->allowed_user->getEmail(); + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Repositories/ISponsorBadgeScanRepository.php b/app/Models/Foundation/Summit/Repositories/ISponsorUserInfoGrantRepository.php similarity index 86% rename from app/Models/Foundation/Summit/Repositories/ISponsorBadgeScanRepository.php rename to app/Models/Foundation/Summit/Repositories/ISponsorUserInfoGrantRepository.php index c47a9280..715569b6 100644 --- a/app/Models/Foundation/Summit/Repositories/ISponsorBadgeScanRepository.php +++ b/app/Models/Foundation/Summit/Repositories/ISponsorUserInfoGrantRepository.php @@ -13,10 +13,10 @@ **/ use models\utils\IBaseRepository; /** - * Interface ISponsorBadgeScanRepository + * Interface ISponsorUserInfoGrantRepository * @package models\summit */ -interface ISponsorBadgeScanRepository extends IBaseRepository +interface ISponsorUserInfoGrantRepository extends IBaseRepository { } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Sponsor.php b/app/Models/Foundation/Summit/Sponsor.php index 45aff487..8c89cb63 100644 --- a/app/Models/Foundation/Summit/Sponsor.php +++ b/app/Models/Foundation/Summit/Sponsor.php @@ -13,6 +13,7 @@ **/ use App\Models\Foundation\Main\IOrderable; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Mapping AS ORM; use models\main\Company; use models\main\Member; @@ -54,10 +55,10 @@ class Sponsor extends SilverstripeBaseModel implements IOrderable protected $sponsorship; /** - * @ORM\OneToMany(targetEntity="SponsorBadgeScan", mappedBy="sponsor", cascade={"persist"}, orphanRemoval=true) - * @var SponsorBadgeScan[] + * @ORM\OneToMany(targetEntity="SponsorUserInfoGrant", mappedBy="sponsor", cascade={"persist"}, orphanRemoval=true) + * @var SponsorUserInfoGrant[] */ - protected $badge_scans; + protected $user_info_grants; /** * @ORM\ManyToMany(targetEntity="models\main\Member", inversedBy="sponsor_memberships") @@ -76,7 +77,7 @@ class Sponsor extends SilverstripeBaseModel implements IOrderable { parent::__construct(); $this->members = new ArrayCollection(); - $this->badge_scans = new ArrayCollection(); + $this->user_info_grants = new ArrayCollection(); } /** @@ -164,16 +165,27 @@ class Sponsor extends SilverstripeBaseModel implements IOrderable } /** - * @param SponsorBadgeScan $scan + * @param SponsorUserInfoGrant $grant */ - public function addBadgeScan(SponsorBadgeScan $scan){ - if($this->badge_scans->contains($scan)) return; - $this->badge_scans->add($scan); - $scan->setSponsor($this); + public function addUserInfoGrant(SponsorUserInfoGrant $grant){ + if($this->user_info_grants->contains($grant)) return; + $this->user_info_grants->add($grant); + $grant->setSponsor($this); } - public function getScans(){ - return $this->badge_scans; + public function getUserInfoGrants(){ + return $this->user_info_grants; + } + + /** + * @param Member $member + * @return bool + */ + public function hasGrant(Member $member):bool { + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('allowed_user', $member)); + $grant = $this->user_info_grants->matching($criteria)->first(); + return $grant !== false; } public function hasCompany():bool{ diff --git a/app/Repositories/RepositoriesProvider.php b/app/Repositories/RepositoriesProvider.php index 792c255f..910a2003 100644 --- a/app/Repositories/RepositoriesProvider.php +++ b/app/Repositories/RepositoriesProvider.php @@ -71,7 +71,7 @@ use models\main\Group; use models\main\IOrganizationRepository; use models\main\Organization; use models\main\SummitAdministratorPermissionGroup; -use models\summit\ISponsorBadgeScanRepository; +use models\summit\ISponsorUserInfoGrantRepository; use models\summit\ISummitRegistrationPromoCodeRepository; use models\summit\ISummitTicketTypeRepository; use models\summit\PaymentGatewayProfile; @@ -85,6 +85,7 @@ use models\summit\SpeakerSummitRegistrationPromoCode; use models\summit\Sponsor; use models\summit\SponsorBadgeScan; use models\summit\SponsorshipType; +use models\summit\SponsorUserInfoGrant; use models\summit\SummitAbstractLocation; use models\summit\SummitAccessLevelType; use models\summit\SummitAttendeeBadge; @@ -541,9 +542,9 @@ final class RepositoriesProvider extends ServiceProvider ); App::singleton( - ISponsorBadgeScanRepository::class, + ISponsorUserInfoGrantRepository::class, function(){ - return EntityManager::getRepository(SponsorBadgeScan::class); + return EntityManager::getRepository(SponsorUserInfoGrant::class); } ); diff --git a/app/Repositories/Summit/DoctrineSponsorBadgeScanRepository.php b/app/Repositories/Summit/DoctrineSponsorUserInfoGrantRepository.php similarity index 78% rename from app/Repositories/Summit/DoctrineSponsorBadgeScanRepository.php rename to app/Repositories/Summit/DoctrineSponsorUserInfoGrantRepository.php index ed5d7ff3..f99be088 100644 --- a/app/Repositories/Summit/DoctrineSponsorBadgeScanRepository.php +++ b/app/Repositories/Summit/DoctrineSponsorUserInfoGrantRepository.php @@ -13,17 +13,17 @@ **/ use App\Repositories\SilverStripeDoctrineRepository; use Doctrine\ORM\QueryBuilder; -use models\summit\ISponsorBadgeScanRepository; +use models\summit\ISponsorUserInfoGrantRepository; use models\summit\SponsorBadgeScan; +use models\summit\SponsorUserInfoGrant; use utils\DoctrineFilterMapping; - /** - * Class DoctrineSponsorBadgeScanRepository + * Class DoctrineSponsorUserInfoGrantRepository * @package App\Repositories\Summit */ -final class DoctrineSponsorBadgeScanRepository +final class DoctrineSponsorUserInfoGrantRepository extends SilverStripeDoctrineRepository - implements ISponsorBadgeScanRepository + implements ISponsorUserInfoGrantRepository { /** @@ -65,16 +65,16 @@ final class DoctrineSponsorBadgeScanRepository { return [ 'id' => 'e.id', - 'scan_date' => 'e.scan_date', + 'scan_date' => 'sbs.scan_date', 'created' => 'e.created', 'ticket_number' => "t.number", 'order_number' => "ord.order_number", 'sponsor_id' => "sp.id", 'attendee_company' => 'o.company_name', - "attendee_full_name" => "LOWER(CONCAT(o.first_name, ' ', o.surname))", - 'attendee_first_name' => 'o.first_name', - 'attendee_last_name' => 'o.surname', - 'attendee_email' => 'o.email', + "attendee_full_name" => "(LOWER(CONCAT(o.first_name, ' ', o.surname)) OR LOWER(CONCAT(au.first_name, ' ', au.last_name)))", + 'attendee_first_name' => 'o.first_name OR au.first_name', + 'attendee_last_name' => 'o.surname OR au.last_name', + 'attendee_email' => 'o.email OR au.email', ]; } @@ -86,8 +86,10 @@ final class DoctrineSponsorBadgeScanRepository $query = $query->join('e.sponsor', 'sp') ->join('sp.summit', 's') ->join('sp.company', 'c') - ->join('e.user', 'u') - ->join('e.badge', 'b') + ->leftJoin('e.allowed_user', 'au') + ->leftJoin(SponsorBadgeScan::class, 'sbs', 'WITH', 'e.id = sbs.id') + ->join('sbs.user', 'u') + ->join('sbs.badge', 'b') ->join('b.ticket', 't') ->join('t.order', 'ord') ->leftJoin('t.owner', 'o') @@ -100,6 +102,6 @@ final class DoctrineSponsorBadgeScanRepository */ protected function getBaseEntity() { - return SponsorBadgeScan::class; + return SponsorUserInfoGrant::class; } } \ No newline at end of file diff --git a/app/Security/SummitScopes.php b/app/Security/SummitScopes.php index 0ae3d0e6..6fb8e428 100644 --- a/app/Security/SummitScopes.php +++ b/app/Security/SummitScopes.php @@ -51,6 +51,7 @@ final class SummitScopes const ReadMyRegistrationOrders = '%s/summits/registration-orders/read/me'; const ReadRegistrationOrders = '%s/summits/registration-orders/read'; const WriteBadgeScan = '%s/summits/badge-scans/write'; + const WriteMyBadgeScan = '%s/summits/badge-scans/write/me'; const ReadBadgeScan = '%s/summits/badge-scans/read'; const ReadMyBadgeScan = '%s/summits/badge-scans/read/me'; const WriteRegistrationData = '%s/summits/registration/write'; diff --git a/app/Services/Model/ISponsorBadgeScanService.php b/app/Services/Model/ISponsorUserInfoGrantService.php similarity index 74% rename from app/Services/Model/ISponsorBadgeScanService.php rename to app/Services/Model/ISponsorUserInfoGrantService.php index d3616f64..cc0485e9 100644 --- a/app/Services/Model/ISponsorBadgeScanService.php +++ b/app/Services/Model/ISponsorUserInfoGrantService.php @@ -15,13 +15,25 @@ use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; use models\main\Member; use models\summit\SponsorBadgeScan; +use models\summit\SponsorUserInfoGrant; use models\summit\Summit; /** * Interface ISponsorBadgeScanService * @package App\Services\Model */ -interface ISponsorBadgeScanService +interface ISponsorUserInfoGrantService { + + /** + * @param Summit $summit + * @param int $sponsor_id + * @param Member $current_member + * @return SponsorUserInfoGrant + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function addGrant(Summit $summit, int $sponsor_id, Member $current_member):SponsorUserInfoGrant; + /** * @param Summit $summit * @param Member $current_member diff --git a/app/Services/Model/Imp/SponsorBadgeScanService.php b/app/Services/Model/Imp/SponsorUserInfoGrantService.php similarity index 65% rename from app/Services/Model/Imp/SponsorBadgeScanService.php rename to app/Services/Model/Imp/SponsorUserInfoGrantService.php index ef4444cb..b94263dd 100644 --- a/app/Services/Model/Imp/SponsorBadgeScanService.php +++ b/app/Services/Model/Imp/SponsorUserInfoGrantService.php @@ -11,28 +11,30 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +use App\Models\Foundation\Summit\Factories\SponsorUserInfoGrantFactory; use App\Models\Foundation\Summit\Repositories\ISummitAttendeeBadgeRepository; use App\Services\Model\AbstractService; -use App\Services\Model\ISponsorBadgeScanService; +use App\Services\Model\ISponsorUserInfoGrantService; use libs\utils\ITransactionService; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; use models\main\Member; -use models\summit\ISponsorBadgeScanRepository; +use models\summit\ISponsorUserInfoGrantRepository; use models\summit\SponsorBadgeScan; +use models\summit\SponsorUserInfoGrant; use models\summit\Summit; use models\summit\SummitAttendeeBadge; /** - * Class SponsorBadgeScanService + * Class SponsorUserInfoGrantService * @package App\Services\Model\Imp */ -final class SponsorBadgeScanService +final class SponsorUserInfoGrantService extends AbstractService - implements ISponsorBadgeScanService + implements ISponsorUserInfoGrantService { /** - * @var ISponsorBadgeScanRepository + * @var ISponsorUserInfoGrantRepository */ private $repository; @@ -43,13 +45,13 @@ final class SponsorBadgeScanService /** * SponsorBadgeScanService constructor. - * @param ISponsorBadgeScanRepository $repository + * @param ISponsorUserInfoGrantRepository $repository * @param ISummitAttendeeBadgeRepository $badge_repository * @param ITransactionService $tx_service */ public function __construct ( - ISponsorBadgeScanRepository $repository, + ISponsorUserInfoGrantRepository $repository, ISummitAttendeeBadgeRepository $badge_repository, ITransactionService $tx_service ) @@ -59,6 +61,29 @@ final class SponsorBadgeScanService $this->badge_repository = $badge_repository; } + /** + * @param Summit $summit + * @param int $sponsor_id + * @param Member $current_member + * @return SponsorUserInfoGrant + * @throws \Exception + */ + public function addGrant(Summit $summit, int $sponsor_id, Member $current_member):SponsorUserInfoGrant { + return $this->tx_service->transaction(function() use($summit, $sponsor_id, $current_member){ + $grant = SponsorUserInfoGrantFactory::build(['class_name' => SponsorUserInfoGrant::ClassName]); + $sponsor = $summit->getSummitSponsorById($sponsor_id); + if(is_null($sponsor)){ + throw new EntityNotFoundException(sprintf("Sponsor not found.")); + } + if($sponsor->hasGrant($current_member)){ + throw new ValidationException(sprintf("User %s already gave grant to sponsor %s", $current_member->getEmail(), $sponsor_id)); + } + $grant->setAllowedUser($current_member); + $sponsor->addUserInfoGrant($grant); + return $grant; + }); + } + /** * @param Summit $summit * @param Member $current_member @@ -79,7 +104,7 @@ final class SponsorBadgeScanService $end_date = $summit->getEndDate(); if(!($scan_date >= $begin_date && $scan_date <= $end_date)) - throw new ValidationException("scan_date is does not belong to summit period"); + throw new ValidationException("scan_date is does not belong to summit period."); if($summit->getBadgeQRPrefix() != $prefix) throw new ValidationException @@ -102,15 +127,15 @@ final class SponsorBadgeScanService $sponsor = $current_member->getSponsorBySummit($summit); if(is_null($sponsor)) - throw new ValidationException("current member does not belongs to any summit sponsor"); - - $scan = new SponsorBadgeScan(); + throw new ValidationException("Current member does not belongs to any summit sponsor."); + $scan = SponsorUserInfoGrantFactory::build(['class_name' => SponsorBadgeScan::ClassName]); $scan->setScanDate($scan_date); $scan->setQRCode($qr_code); $scan->setUser($current_member); $scan->setBadge($badge); - $sponsor->addBadgeScan($scan); + + $sponsor->addUserInfoGrant($scan); return $scan; }); diff --git a/app/Services/ModelServicesProvider.php b/app/Services/ModelServicesProvider.php index f8ee1bc7..a0d1f0c8 100644 --- a/app/Services/ModelServicesProvider.php +++ b/app/Services/ModelServicesProvider.php @@ -24,7 +24,7 @@ use App\Services\Model\IMemberService; use App\Services\Model\Imp\CompanyService; use App\Services\Model\Imp\PaymentGatewayProfileService; use App\Services\Model\Imp\RegistrationIngestionService; -use App\Services\Model\Imp\SponsorBadgeScanService; +use App\Services\Model\Imp\SponsorUserInfoGrantService; use App\Services\Model\Imp\SummitAdministratorPermissionGroupService; use App\Services\Model\Imp\SummitDocumentService; use App\Services\Model\Imp\SummitEmailEventFlowService; @@ -38,7 +38,7 @@ use App\Services\Model\IPresentationCategoryGroupService; use App\Services\Model\IRegistrationIngestionService; use App\Services\Model\IRSVPTemplateService; use App\Services\Model\IScheduleIngestionService; -use App\Services\Model\ISponsorBadgeScanService; +use App\Services\Model\ISponsorUserInfoGrantService; use App\Services\Model\ISponsorshipTypeService; use App\Services\Model\ISummitAccessLevelTypeService; use App\Services\Model\ISummitAdministratorPermissionGroupService; @@ -326,7 +326,8 @@ final class ModelServicesProvider extends ServiceProvider App::singleton(ISummitOrderService::class, SummitOrderService::class); - App::singleton(ISponsorBadgeScanService::class, SponsorBadgeScanService::class); + App::singleton(ISponsorUserInfoGrantService::class, + SponsorUserInfoGrantService::class); App::singleton( IRegistrationIngestionService::class, diff --git a/database/migrations/model/Version20201015153512.php b/database/migrations/model/Version20201015153512.php new file mode 100644 index 00000000..302bc2d1 --- /dev/null +++ b/database/migrations/model/Version20201015153512.php @@ -0,0 +1,61 @@ +hasTable("SponsorUserInfoGrant")) { + $builder->create('SponsorUserInfoGrant', function (Table $table) { + + $table->integer("ID", true, false); + $table->primary("ID"); + + $table->timestamp('Created'); + $table->timestamp('LastEdited'); + $table->string('ClassName'); + + // FK + $table->integer("AllowedUserID", false, false)->setNotnull(false)->setDefault('NULL'); + $table->index("AllowedUserID", "AllowedUserID"); + $table->foreign("Member", "AllowedUserID", "ID", ["onDelete" => "CASCADE"]); + + // FK + $table->integer("SponsorID", false, false)->setNotnull(false)->setDefault('NULL'); + $table->index("SponsorID", "SponsorID"); + $table->foreign("Sponsor", "SponsorID", "ID", ["onDelete" => "CASCADE"]); + }); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + + } +} diff --git a/database/migrations/model/Version20201015153514.php b/database/migrations/model/Version20201015153514.php new file mode 100644 index 00000000..c80fbfb6 --- /dev/null +++ b/database/migrations/model/Version20201015153514.php @@ -0,0 +1,44 @@ +addSql($sql); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + + } +} diff --git a/database/migrations/model/Version20201015153516.php b/database/migrations/model/Version20201015153516.php new file mode 100644 index 00000000..6af0ba84 --- /dev/null +++ b/database/migrations/model/Version20201015153516.php @@ -0,0 +1,72 @@ +addSql($sql); + + // update PK + $sql = <<addSql($sql); + + // FK inheritance + $sql = <<addSql($sql); + + // DROP IDX + $sql = <<addSql($sql); + + $sql = <<addSql($sql); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + + } +} diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 272f1182..25d1e1e4 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -1451,6 +1451,14 @@ class ApiEndpointsSeeder extends Seeder IGroup::SummitAdministrators, ] ], + [ + 'name' => 'share-my-user-info-with-sponsor', + 'route' => '/api/v1/summits/{id}/sponsors/{sponsor_id}/user-info-grants/me', + 'http_method' => 'POST', + 'scopes' => [ + sprintf(SummitScopes::WriteMyBadgeScan, $current_realm), + ] + ], // sponsorship-types [ 'name' => 'get-sponsorship-types', diff --git a/database/seeds/ApiScopesSeeder.php b/database/seeds/ApiScopesSeeder.php index 336be4c4..06f0fe19 100644 --- a/database/seeds/ApiScopesSeeder.php +++ b/database/seeds/ApiScopesSeeder.php @@ -325,6 +325,11 @@ final class ApiScopesSeeder extends Seeder 'short_description' => 'read my badge scans', 'description' => 'read my badge scans', ], + [ + 'name' => sprintf(SummitScopes::WriteMyBadgeScan, $current_realm), + 'short_description' => 'allow to share my badge with sponsors', + 'description' => 'allow to share my badge with sponsors', + ], [ 'name' => sprintf(SummitScopes::ReadBadgeScan, $current_realm), 'short_description' => 'read badge scans',