Sponsored Projects - Endpoints

POST /api/v1/sponsored-projects

payload

name
description
is_active

scope

REALM_URL/sponsored-projects/write

GET /api/v1/sponsored-projects

scope

REALM_URL/sponsored-projects/read

PUT /api/v1/sponsored-projects/{id}

payload

name
description
is_active

scope

REALM_URL/sponsored-projects/write

GET /api/v1/sponsored-projects/{id}
scope

REALM_URL/sponsored-projects/read

PUBLIC

GET /api/public/v1/sponsored-projects/{slug}

DELETE /api/v1/sponsored-projects/{id}

scope

REALM_URL/sponsored-projects/write

POST /api/v1/sponsored-projects/{id}/sponsorship-types

payload
name
description
is_active
order

scope

REALM_URL/sponsored-projects/write

GET /api/v1/sponsored-projects/{id}/sponsorship-types

scope

REALM_URL/sponsored-projects/read

GET /api/v1/sponsored-projects/{id}/sponsorship-types/{id}

scope

REALM_URL/sponsored-projects/read

DELETE /api/v1/sponsored-projects/{id}/sponsorship-types/{id}

scope

REALM_URL/sponsored-projects/write

PUT /api/v1/sponsored-projects/{id}/sponsorship-types/{id}

payload
name
description
is_active
order

scope

REALM_URL/sponsored-projects/write

PUT /api/v1/sponsored-projects/{id}/sponsorship-types/{id}/supporting-companies/{id}

payload
order (optional)

scope

REALM_URL/sponsored-projects/write

DELETE /api/v1/sponsored-projects/{id}/sponsorship-types/{id}/supporting-companies/{id}

scope

REALM_URL/sponsored-projects/write

GET /api/v1/sponsored-projects/{id}/sponsorship-types/{id}/supporting-companies

scope

REALM_URL/sponsored-projects/read

Change-Id: I9c0b1bb457a1c583afd284f56f2aced5deceaa02
Signed-off-by: smarcet <smarcet@gmail.com>
This commit is contained in:
smarcet 2020-11-23 17:26:06 -03:00
parent 2fb1914c68
commit 35fc57473c
45 changed files with 3067 additions and 7 deletions

View File

@ -73,7 +73,6 @@ SCP_REMOTE_BASE_PATH=/tmp
GOOGLE_GEO_CODING_API_KEY=
# swift configuration
CLOUD_STORAGE_BASE_URL=
CLOUD_STORAGE_AUTH_URL=
CLOUD_STORAGE_USERNAME=
CLOUD_STORAGE_APIKEY=

View File

@ -16,6 +16,8 @@ use Illuminate\Support\Facades\Log;
use libs\utils\JsonUtils;
use models\oauth2\IResourceServerContext;
use models\utils\IEntity;
use ModelSerializers\SerializerRegistry;
/**
* Class AbstractSerializer
* @package Libs\ModelSerializers
@ -157,6 +159,8 @@ abstract class AbstractSerializer implements IModelSerializer
return sprintf("%s:%s", $field, $type);
}
protected $expand_mappings = [];
/**
* @param null $expand
* @param array $fields
@ -254,6 +258,17 @@ abstract class AbstractSerializer implements IModelSerializer
$values = $new_values;
}
// expand logic
if (!empty($expand)) {
$exp_expand = explode(',', $expand);
foreach ($exp_expand as $relation) {
$relation = trim($relation);
if(isset($this->expand_mappings[$relation])){
$values = $this->expand_mappings[$relation]->serialize($values, $expand);
}
}
}
return $values;
}
@ -262,7 +277,7 @@ abstract class AbstractSerializer implements IModelSerializer
* @param string $prefix
* @return string
*/
protected static function filterExpandByPrefix($expand_str, $prefix){
public static function filterExpandByPrefix($expand_str, $prefix){
$expand_to = explode(',', $expand_str);
$filtered_expand = array_filter($expand_to, function($element) use($prefix){

View File

@ -0,0 +1,37 @@
<?php namespace Libs\ModelSerializers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use ModelSerializers\SerializerRegistry;
/**
* Class Many2OneExpandSerializer
* @package Libs\ModelSerializers
*/
class Many2OneExpandSerializer extends One2ManyExpandSerializer
{
/**
* @param array $values
* @param string $expand
* @return array
*/
public function serialize(array $values, string $expand): array
{
$values = $this->unsetOriginalAttribute($values);
$callback = $this->getRelationFn;
$res = [];
foreach ($callback($this) as $item){
$res[] = SerializerRegistry::getInstance()->getSerializer($item)->serialize(AbstractSerializer::filterExpandByPrefix($expand, $this->attribute_name));
}
$values[$this->attribute_name] = $res;
return $values;
}
}

View File

@ -0,0 +1,78 @@
<?php namespace Libs\ModelSerializers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use ModelSerializers\SerializerRegistry;
use Closure;
/**
* Class One2ManyExpandSerializer
* @package Libs\ModelSerializers
*/
class One2ManyExpandSerializer
{
/**
* @var string
*/
protected $original_attribute;
/**
* @var string
*/
protected $attribute_name;
/**
* @var Closure
*/
protected $getRelationFn;
/**
* One2ManyExpandSerializer constructor.
* @param string $attribute_name
* @param Closure $getRelationFn
* @param string|null $original_attribute
*/
public function __construct(
string $attribute_name,
Closure $getRelationFn,
string $original_attribute = null
)
{
$this->attribute_name = $attribute_name;
$this->getRelationFn = $getRelationFn;
$this->original_attribute = $original_attribute;
}
/**
* @param array $values
* @return array
*/
protected function unsetOriginalAttribute(array $values)
{
if (isset($values[$this->original_attribute]))
unset($values[$this->original_attribute]);
return $values;
}
/**
* @param array $values
* @param string $expand
* @return array
*/
public function serialize(array $values, string $expand): array
{
$values = $this->unsetOriginalAttribute($values);
$callback = $this->getRelationFn;
$values[$this->attribute_name] = SerializerRegistry::getInstance()->getSerializer($callback($this))->serialize(AbstractSerializer::filterExpandByPrefix($expand, $this->attribute_name));
return $values;
}
}

View File

@ -0,0 +1,44 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class ProjectSponsorshipTypeValidationRulesFactory
* @package App\Http\Controllers
*/
final class ProjectSponsorshipTypeValidationRulesFactory
{
/**
* @param array $data
* @param bool $update
* @return array
*/
public static function build(array $data, $update = false)
{
if ($update) {
return [
'name' => 'sometimes|string',
'description' => 'sometimes|string',
'is_active' => 'sometimes|boolean',
'order' => 'sometimes|integer|min:1',
];
}
return [
'name' => 'required|string',
'description' => 'sometimes|string',
'is_active' => 'sometimes|boolean',
'order' => 'sometimes|integer|min:1',
];
}
}

View File

@ -0,0 +1,41 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class SponsoredProjectValidationRulesFactory
* @package App\Http\Controllers
*/
class SponsoredProjectValidationRulesFactory
{
/**
* @param array $data
* @param bool $update
* @return array
*/
public static function build(array $data, $update = false){
if($update){
return [
'name' => 'sometimes|string',
'description' => 'sometimes|string',
'is_active' => 'sometimes|boolean',
];
}
return [
'name' => 'required|string',
'description' => 'sometimes|string',
'is_active' => 'sometimes|boolean',
];
}
}

View File

@ -0,0 +1,378 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\Repositories\IProjectSponsorshipTypeRepository;
use App\Models\Foundation\Main\Repositories\ISponsoredProjectRepository;
use App\Models\Foundation\Main\Repositories\ISupportingCompanyRepository;
use App\Services\Model\ISponsoredProjectService;
use libs\utils\HTMLCleaner;
use models\oauth2\IResourceServerContext;
use models\utils\IEntity;
use ModelSerializers\SerializerRegistry;
use utils\Filter;
use utils\FilterElement;
use utils\PagingInfo;
/**
* Class OAuth2SponsoredProjectApiController
* @package App\Http\Controllers
*/
final class OAuth2SponsoredProjectApiController extends OAuth2ProtectedController
{
use ParametrizedGetAll;
use AddEntity;
use UpdateEntity;
use DeleteEntity;
use GetEntity;
use ParametrizedAddEntity;
use ParametrizedUpdateEntity;
use ParametrizedDeleteEntity;
use ParametrizedGetEntity;
/**
* @var ISponsoredProjectService
*/
private $service;
/**
* @var IProjectSponsorshipTypeRepository
*/
private $project_sponsorship_type_repository;
/**
* @var ISupportingCompanyRepository
*/
private $supporting_company_repository;
/**
* OAuth2SponsoredProjectApiController constructor.
* @param ISponsoredProjectRepository $company_repository
* @param IProjectSponsorshipTypeRepository $project_sponsorship_type_repository
* @param ISupportingCompanyRepository $supporting_company_repository
* @param IResourceServerContext $resource_server_context
* @param ISponsoredProjectService $service
*/
public function __construct
(
ISponsoredProjectRepository $company_repository,
IProjectSponsorshipTypeRepository $project_sponsorship_type_repository,
ISupportingCompanyRepository $supporting_company_repository,
IResourceServerContext $resource_server_context,
ISponsoredProjectService $service
)
{
parent::__construct($resource_server_context);
$this->repository = $company_repository;
$this->project_sponsorship_type_repository = $project_sponsorship_type_repository;
$this->supporting_company_repository = $supporting_company_repository;
$this->service = $service;
}
/**
* @inheritDoc
*/
function getAddValidationRules(array $payload): array
{
return SponsoredProjectValidationRulesFactory::build($payload);
}
/**
* @inheritDoc
*/
protected function addEntity(array $payload): IEntity
{
return $this->service->add(HTMLCleaner::cleanData($payload, ['description']));
}
/**
* @inheritDoc
*/
protected function deleteEntity(int $id): void
{
$this->service->delete($id);
}
/**
* @inheritDoc
*/
protected function getEntity(int $id): IEntity
{
return $this->repository->getById($id);
}
/**
* @inheritDoc
*/
function getUpdateValidationRules(array $payload): array
{
return SponsoredProjectValidationRulesFactory::build($payload, true);
}
/**
* @inheritDoc
*/
protected function updateEntity($id, array $payload): IEntity
{
return $this->service->update($id, HTMLCleaner::cleanData($payload, ['description']));
}
/**
* @return mixed
*/
public function getAll()
{
return $this->_getAll(
function () {
return [
'name' => ['=@', '=='],
'slug' => ['=@', '=='],
'is_active' => ['==']
];
},
function () {
return [
'is_active' => 'sometimes|boolean',
'name' => 'sometimes|string',
'slug' => 'sometimes|string',
];
},
function () {
return [
'name',
'id',
];
},
function ($filter) {
return $filter;
},
function () {
return SerializerRegistry::SerializerType_Public;
}
);
}
// sponsorship types
/**
* @param $id string|int
*/
public function getAllSponsorshipTypes($id)
{
return $this->_getAll(
function () {
return [
'name' => ['=@', '=='],
'slug' => ['=@', '=='],
'is_active' => ['==']
];
},
function () {
return [
'is_active' => 'sometimes|boolean',
'name' => 'sometimes|string',
'slug' => 'sometimes|string',
];
},
function () {
return [
'name',
'id',
];
},
function ($filter) use($id) {
if($filter instanceof Filter){
if(is_integer($id))
$filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_id', intval($id)));
else
$filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_slug', $id));
}
return $filter;
},
function () {
return SerializerRegistry::SerializerType_Public;
},
null,
null,
function ($page, $per_page, $filter, $order, $applyExtraFilters) {
return $this->project_sponsorship_type_repository->getAllByPage
(
new PagingInfo($page, $per_page),
call_user_func($applyExtraFilters, $filter),
$order
);
}
);
}
/**
* @param $id
* @param $sponsorship_type_id
*/
public function getSponsorshipType($id, $sponsorship_type_id){
$this->_get($sponsorship_type_id, function($id){
return $this->project_sponsorship_type_repository->getById(intval($id));
});
}
/**
* @param $id
* @return mixed
*/
public function addSponsorshipType($id)
{
$args = [intval($id)];
return $this->_add(
function ($payload) {
return ProjectSponsorshipTypeValidationRulesFactory::build($payload);
},
function ($payload, $id){
return $this->service->addProjectSponsorshipType($id, HTMLCleaner::cleanData($payload, ['description']));
},
...$args
);
}
/**
* @param $id
* @param $sponsorship_type_id
* @return mixed
*/
public function updateSponsorshipType($id, $sponsorship_type_id){
$args = [ intval($id) ];
return $this->_update(
$sponsorship_type_id,
function($payload){
return ProjectSponsorshipTypeValidationRulesFactory::build($payload, true);
},
function($sponsorship_type_id, $payload, $project_id){
return $this->service->updateProjectSponsorshipType($project_id, $sponsorship_type_id, HTMLCleaner::cleanData($payload, ['description']));
},
...$args
);
}
/**
* @param $id
* @param $sponsorship_type_id
* @return mixed
*/
public function deleteSponsorshipType($id, $sponsorship_type_id){
$args = [ intval($id) ];
return $this->_delete(
$sponsorship_type_id,
function ($sponsorship_type_id, $project_id){
$this->service->deleteProjectSponsorshipType($project_id, $sponsorship_type_id);
},
...$args
);
}
// supporting companies
public function getSupportingCompanies($id, $sponsorship_type_id){
return $this->_getAll(
function () {
return [
'name' => ['=@', '=='],
];
},
function () {
return [
'name' => 'sometimes|string',
];
},
function () {
return [
'name',
'order',
];
},
function ($filter) use($id, $sponsorship_type_id) {
if($filter instanceof Filter){
if(is_integer($id))
$filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_id', intval($id)));
else
$filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_slug', $id));
if(is_integer($sponsorship_type_id))
$filter->addFilterCondition(FilterElement::makeEqual('sponsorship_type_id', intval($sponsorship_type_id)));
else
$filter->addFilterCondition(FilterElement::makeEqual('sponsorship_type_slug', $sponsorship_type_id));
}
return $filter;
},
function () {
return SerializerRegistry::SerializerType_Public;
},
null,
null,
function ($page, $per_page, $filter, $order, $applyExtraFilters) {
return $this->supporting_company_repository->getAllByPage
(
new PagingInfo($page, $per_page),
call_user_func($applyExtraFilters, $filter),
$order
);
}
);
}
/**
* @param $id
* @param $sponsorship_type_id
* @param $company_id
* @return mixed
*/
public function addSupportingCompanies($id, $sponsorship_type_id, $company_id){
return $this->_update($company_id,
function($payload){
return [
'order' => 'sometimes|integer|min:1',
];
},
function($id, $payload, $project_id, $sponsorship_type_id){
return $this->service->addCompanyToProjectSponsorshipType
(
$project_id,
$sponsorship_type_id,
$id,
$payload
);
},
$id,
$sponsorship_type_id
);
}
/**
* @param $id
* @param $sponsorship_type_id
* @param $company_id
* @return mixed
*/
public function deleteSupportingCompanies($id, $sponsorship_type_id, $company_id){
return $this->_delete($company_id, function($id, $project_id, $sponsorship_type_id){
$this->service->removeCompanyToProjectSponsorshipType($id, $sponsorship_type_id, $id);
}, $id, $sponsorship_type_id);
}
}

View File

@ -0,0 +1,23 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class OAuth2SponsoredProjectsApiController
* @package App\Http\Controllers
*/
final class OAuth2SponsoredProjectsApiController extends OAuth2ProtectedController
{
}

View File

@ -0,0 +1,90 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Http\Exceptions\HTTP403ForbiddenException;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Validator;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use ModelSerializers\SerializerRegistry;
/**
* Trait ParametrizedAddEntity
* @package App\Http\Controllers
*/
trait ParametrizedAddEntity
{
use BaseAPI;
public function _add(
callable $getAddValidationRulesFn,
callable $addEntityFn,
...$args
){
try {
if(!Request::isJson()) return $this->error400();
$data = Input::json();
$payload = $data->all();
// Creates a Validator instance and validates the data.
$validation = Validator::make($payload, $getAddValidationRulesFn($payload));
if ($validation->fails()) {
$messages = $validation->messages()->toArray();
return $this->error412
(
$messages
);
}
$fields = Request::input('fields', '');
$relations = Request::input('relations', '');
$relations = !empty($relations) ? explode(',', $relations) : [];
$fields = !empty($fields) ? explode(',', $fields) : [];
$entity = $addEntityFn($payload, ...$args);
return $this->created(SerializerRegistry::getInstance()->getSerializer($entity)->serialize
(
Request::input('expand', ''),
$fields,
$relations
));
}
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);
}
}
}

View File

@ -0,0 +1,54 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Http\Exceptions\HTTP403ForbiddenException;
use Illuminate\Support\Facades\Log;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
/**
* Trait ParametrizedDeleteEntity
* @package App\Http\Controllers
*/
trait ParametrizedDeleteEntity
{
use BaseAPI;
/**
* @param $id
* @param callable $deleteEntityFn
* @param mixed ...$args
* @return mixed
*/
public function _delete($id, callable $deleteEntityFn, ...$args)
{
try {
$deleteEntityFn($id,...$args);
return $this->deleted();
} 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);
}
}
}

View File

@ -0,0 +1,67 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Http\Exceptions\HTTP403ForbiddenException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use ModelSerializers\SerializerRegistry;
/**
* Trait ParametrizedGetEntity
* @package App\Http\Controllers
*/
trait ParametrizedGetEntity
{
use BaseAPI;
/**
* @param $id
* @param callable $getEntityFn
* @param mixed ...$args
* @return mixed
*/
public function _get($id, callable $getEntityFn, ...$args)
{
try {
$entity = $getEntityFn($id, ...$args);
$fields = Request::input('fields', '');
$relations = Request::input('relations', '');
$relations = !empty($relations) ? explode(',', $relations) : [];
$fields = !empty($fields) ? explode(',', $fields) : [];
return $this->ok(SerializerRegistry::getInstance()->getSerializer($entity)->serialize(
Request::input('expand', ''),
$fields,
$relations
));
} 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);
}
}
}

View File

@ -0,0 +1,96 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Http\Exceptions\HTTP403ForbiddenException;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Validator;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use ModelSerializers\SerializerRegistry;
/**
* Trait ParametrizedUpdateEntity
* @package App\Http\Controllers
*/
trait ParametrizedUpdateEntity
{
use BaseAPI;
/**
* @param int $id
* @param callable $getUpdateValidationRulesFn
* @param callable $updateEntityFn
* @param mixed ...$args
* @return mixed
*/
public function _update(
int $id,
callable $getUpdateValidationRulesFn,
callable $updateEntityFn,
...$args){
try {
if(Request::isJson()) return $this->error400();
$data = Input::json();
$payload = $data->all();
// Creates a Validator instance and validates the data.
$validation = Validator::make($payload, $getUpdateValidationRulesFn($payload));
if ($validation->fails()) {
$messages = $validation->messages()->toArray();
return $this->error412
(
$messages
);
}
$entity = $updateEntityFn($id, $payload, ...$args);
$fields = Request::input('fields', '');
$relations = Request::input('relations', '');
$relations = !empty($relations) ? explode(',', $relations) : [];
$fields = !empty($fields) ? explode(',', $fields) : [];
return $this->updated(SerializerRegistry::getInstance()->getSerializer($entity)->serialize
(
Request::input('expand', ''),
$fields,
$relations
));
}
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);
}
}
}

View File

@ -28,6 +28,12 @@ Route::group([
]
], function () {
Route::group(['prefix' => 'sponsored-projects'], function(){
Route::group(['prefix'=>'{id}'], function(){
Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@get']);
});
});
// files
Route::group(['prefix' => 'files'], function () {
Route::post('upload','OAuth2ChunkedFilesApiController@uploadFile' );

View File

@ -87,6 +87,39 @@ Route::group([
});
});
// sponsored projects
Route::group(['prefix'=>'sponsored-projects'], function(){
Route::get('', 'OAuth2SponsoredProjectApiController@getAll');
Route::post('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@add']);
Route::group(['prefix'=>'{id}'], function(){
Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@get']);
Route::put('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@update']);
Route::delete('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@delete']);
Route::group(['prefix'=>'sponsorship-types'], function(){
Route::get('', 'OAuth2SponsoredProjectApiController@getAllSponsorshipTypes');
Route::post('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@addSponsorshipType']);
Route::group(['prefix'=>'{sponsorship_type_id}'], function(){
Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@getSponsorshipType']);
Route::put('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@updateSponsorshipType']);
Route::delete('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@deleteSponsorshipType']);
Route::group(['prefix'=>'supporting-companies'], function(){
Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@getSupportingCompanies']);
Route::group(['prefix'=>'{company_id}'], function(){
Route::put('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@addSupportingCompanies']);
Route::delete('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@deleteSupportingCompanies']);
});
});
});
});
});
});
// organizations
Route::group(['prefix'=>'organizations'], function(){
Route::get('', 'OAuth2OrganizationsApiController@getAll');

View File

@ -0,0 +1,46 @@
<?php namespace ModelSerializers;
use Libs\ModelSerializers\Many2OneExpandSerializer;
use Libs\ModelSerializers\One2ManyExpandSerializer;
use models\oauth2\IResourceServerContext;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class ProjectSponsorshipTypeSerializer
* @package ModelSerializers
*/
class ProjectSponsorshipTypeSerializer extends SilverStripeSerializer
{
protected static $array_mappings = [
'Name' => 'name:json_string',
'Description' => 'description:json_string',
'Active' => 'active:json_boolean',
'Order' => 'order:json_int',
'SponsoredProjectId' => 'sponsored_project_id:json_int',
'SupportingCompaniesIds' => 'supporting_companies',
];
public function __construct($object, IResourceServerContext $resource_server_context)
{
parent::__construct($object, $resource_server_context);
$this->expand_mappings = [
'sponsored_project' => new One2ManyExpandSerializer('sponsored_project', function () use ($object) {
return $object->getSponsoredProject();
}, "sponsored_project_id"),
'supporting_companies' => new Many2OneExpandSerializer('supporting_companies', function () use ($object) {
return $object->getSupportingCompanies();
}, "supporting_companies"),
];
}
}

View File

@ -0,0 +1,40 @@
<?php namespace ModelSerializers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Libs\ModelSerializers\Many2OneExpandSerializer;
use models\oauth2\IResourceServerContext;
/**
* Class SponsoredProjectSerializer
* @package ModelSerializers
*/
final class SponsoredProjectSerializer extends SilverStripeSerializer
{
protected static $array_mappings = [
'Name' => 'name:json_string',
'Description' => 'description:json_string',
'Slug' => 'slug:json_string',
'Active' => 'is_active:json_boolean',
'SponsorshipTypesIds' => 'sponsorship_types',
];
public function __construct($object, IResourceServerContext $resource_server_context)
{
parent::__construct($object, $resource_server_context);
$this->expand_mappings = [
'sponsorship_types' => new Many2OneExpandSerializer('sponsorship_types', function () use ($object) {
return $object->getSponsorshipTypes();
}, "sponsorship_types"),
];
}
}

View File

@ -0,0 +1,48 @@
<?php namespace ModelSerializers;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Libs\ModelSerializers\AbstractSerializer;
use Libs\ModelSerializers\One2ManyExpandSerializer;
use models\oauth2\IResourceServerContext;
/**
* Class SupportingCompanySerializer
* @package ModelSerializers
*/
final class SupportingCompanySerializer extends AbstractSerializer
{
protected static $array_mappings = [
'CompanyId' => 'company_id:json_int',
'SponsorshipId' => 'sponsorship_type_id:json_int',
'Order' => 'order:json_int',
];
/***
* SupportingCompanySerializer constructor.
* @param $object
* @param IResourceServerContext $resource_server_context
*/
public function __construct($object, IResourceServerContext $resource_server_context)
{
parent::__construct($object, $resource_server_context);
$this->expand_mappings = [
'company' => new One2ManyExpandSerializer('company', function () use ($object) {
return $object->getCompany();
}, "company_id"),
'sponsorship_type' => new One2ManyExpandSerializer('sponsorship_type', function () use ($object) {
return $object->getSponsorshipType();
}, "sponsorship_type_id"),
];
}
}

View File

@ -206,7 +206,12 @@ final class SerializerRegistry
self::SerializerType_Public => PresentationMediaUploadSerializer::class,
self::SerializerType_Private => AdminPresentationMediaUploadSerializer::class
];
$this->registry['Company'] = CompanySerializer::class;
// Company
$this->registry['Company'] = CompanySerializer::class;
$this->registry['SponsoredProject'] = SponsoredProjectSerializer::class;
$this->registry['ProjectSponsorshipType'] = ProjectSponsorshipTypeSerializer::class;
$this->registry['SupportingCompany'] = SupportingCompanySerializer::class;
$this->registry['PresentationSpeaker'] =
[

View File

@ -11,14 +11,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\ICompanyMemberLevel;
use Doctrine\Common\Collections\ArrayCollection;
use Illuminate\Support\Facades\Log;
use models\exceptions\ValidationException;
use models\utils\SilverstripeBaseModel;
use Doctrine\ORM\Mapping AS ORM;
/**
* @ORM\Entity(repositoryClass="repositories\main\DoctrineCompanyRepository")
* @ORM\Table(name="Company")

View File

@ -0,0 +1,242 @@
<?php namespace models\main;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\IOrderable;
use App\Models\Foundation\Main\OrderableChilds;
use Cocur\Slugify\Slugify;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use models\exceptions\ValidationException;
use models\utils\One2ManyPropertyTrait;
use models\utils\SilverstripeBaseModel;
use Doctrine\ORM\Mapping AS ORM;
/**
* @ORM\Entity(repositoryClass="repositories\main\DoctrineProjectSponsorshipTypeRepository")
* @ORM\Table(name="ProjectSponsorshipType")
* Class ProjectSponsorshipType
* @package models\main
*/
class ProjectSponsorshipType extends SilverstripeBaseModel implements IOrderable
{
/**
* @ORM\Column(name="Name", type="string")
* @var string
*/
private $name;
/**
* @ORM\Column(name="Description", type="string")
* @var string
*/
private $description;
/**
* @ORM\Column(name="IsActive", type="boolean")
* @var bool
*/
private $is_active;
/**
* @ORM\Column(name="`Order`", type="integer")
* @var int
*/
private $order;
/**
* @ORM\ManyToOne(targetEntity="SponsoredProject", fetch="EXTRA_LAZY")
* @ORM\JoinColumn(name="SponsoredProjectID", referencedColumnName="ID", onDelete="SET NULL")
* @var SponsoredProject
*/
private $sponsored_project;
/**
* @ORM\OneToMany(targetEntity="SupportingCompany", mappedBy="sponsorship_type", cascade={"persist"}, orphanRemoval=true)
* @var SupportingCompany[]
*/
private $supporting_companies;
/**
* @ORM\Column(name="Slug", type="string")
* @var string
*/
private $slug;
/**
* @inheritDoc
*/
public function setOrder($order)
{
$this->order = $order;
}
/**
* @inheritDoc
*/
public function getOrder()
{
return $this->order;
}
public function __construct()
{
parent::__construct();
$this->supporting_companies = new ArrayCollection();
$this->is_active = false;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @param string $name
*/
public function setName(string $name): void
{
$this->name = $name;
$slugify = new Slugify();
$this->slug = $slugify->slugify($name);
}
/**
* @return string
*/
public function getSlug(): string
{
return $this->slug;
}
/**
* @return string
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* @param string $description
*/
public function setDescription(string $description): void
{
$this->description = $description;
}
/**
* @return bool
*/
public function isActive(): bool
{
return $this->is_active;
}
/**
* @param bool $is_active
*/
public function setIsActive(bool $is_active): void
{
$this->is_active = $is_active;
}
/**
* @return SponsoredProject
*/
public function getSponsoredProject(): ?SponsoredProject
{
return $this->sponsored_project;
}
/**
* @param SponsoredProject $sponsored_project
*/
public function setSponsoredProject(SponsoredProject $sponsored_project): void
{
$this->sponsored_project = $sponsored_project;
}
public function clearSponsoredProject(){
$this->sponsored_project = null;
}
use OrderableChilds;
/**
* @param SupportingCompany $value
* @param int $new_order
* @throws ValidationException
*/
public function recalculateSupportingCompanyOrder(SupportingCompany $value, $new_order){
self::recalculateOrderForSelectable($this->supporting_companies, $value, $new_order);
}
/**
* @param Company $company
* @return SupportingCompany|null
*/
public function addSupportingCompany(Company $company):?SupportingCompany {
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('company', $company));
$supporting_company = $this->supporting_companies->matching($criteria)->first();
if($supporting_company) return $supporting_company;
$supporting_company = new SupportingCompany();
$supporting_company->setCompany($company);
$supporting_company->setSponsorshipType($this);
$this->supporting_companies->add($supporting_company);
$supporting_company->setOrder($this->supporting_companies->count());
return $supporting_company;
}
/**
* @param Company $company
*/
public function removeSupportingCompany(Company $company){
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('company', $company));
$supporting_company = $this->supporting_companies->matching($criteria)->first();
if(!$supporting_company) return;
$this->supporting_companies->removeElement($supporting_company);
}
use One2ManyPropertyTrait;
protected $getIdMappings = [
'getSponsoredProjectId' => 'sponsored_project',
];
protected $hasPropertyMappings = [
'hasSponsoredProject' => 'sponsored_project',
];
/**
* @return array
*/
public function getSupportingCompaniesIds():array {
$res = [];
foreach ($this->supporting_companies as $supporting_company){
$res[] = $supporting_company->getCompany()->getId();
}
return $res;
}
public function getSupportingCompanies(){
return $this->supporting_companies;
}
}

View File

@ -0,0 +1,192 @@
<?php namespace models\main;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use models\exceptions\ValidationException;
use models\utils\SilverstripeBaseModel;
use Doctrine\ORM\Mapping AS ORM;
use Cocur\Slugify\Slugify;
use App\Models\Foundation\Main\OrderableChilds;
/**
* @ORM\Entity(repositoryClass="repositories\main\DoctrineSponsoredProjectRepository")
* @ORM\Table(name="SponsoredProject")
* Class SponsoredProject
* @package models\main
*/
class SponsoredProject extends SilverstripeBaseModel
{
/**
* @ORM\Column(name="Name", type="string")
* @var string
*/
private $name;
/**
* @ORM\Column(name="Description", type="string")
* @var string
*/
private $description;
/**
* @ORM\Column(name="IsActive", type="boolean")
* @var bool
*/
private $is_active;
/**
* @ORM\Column(name="Slug", type="string")
* @var string
*/
private $slug;
/**
* @param string $name
*/
public function setName(string $name):void{
$this->name = $name;
$slugify = new Slugify();
$this->slug = $slugify->slugify($name);
}
/**
* @return string|null
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* @param string $description
*/
public function setDescription(string $description): void
{
$this->description = $description;
}
/**
* @return bool
*/
public function isActive(): bool
{
return $this->is_active;
}
/**
* @param bool $is_active
*/
public function setIsActive(bool $is_active): void
{
$this->is_active = $is_active;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getSlug(): string
{
return $this->slug;
}
use OrderableChilds;
/**
* @ORM\OneToMany(targetEntity="ProjectSponsorshipType", mappedBy="sponsored_project", cascade={"persist"}, orphanRemoval=true)
* @var ProjectSponsorshipType[]
*/
private $sponsorship_types;
/**
* SponsoredProject constructor.
*/
public function __construct()
{
parent::__construct();
$this->sponsorship_types = new ArrayCollection;
$this->is_active = false;
}
/**
* @param ProjectSponsorshipType $value
* @param int $new_order
* @throws ValidationException
*/
public function recalculateProjectSponsorshipTypeOrder(ProjectSponsorshipType $value, $new_order){
self::recalculateOrderForSelectable($this->sponsorship_types, $value, $new_order);
}
/**
* @return ProjectSponsorshipType[]
*/
public function getSponsorshipTypes(): array
{
return $this->sponsorship_types;
}
/**
* @return array|int[]
*/
public function getSponsorshipTypesIds(): array {
$res = [];
foreach($this->sponsorship_types as $item){
$res[] = $item->getId();
}
return $res;
}
/**
* @param string $name
* @return ProjectSponsorshipType|null
*/
public function getSponsorshipTypeByName(string $name):?ProjectSponsorshipType{
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('name', trim($name)));
$sponsorshipType = $this->sponsorship_types->matching($criteria)->first();
return $sponsorshipType === false ? null : $sponsorshipType;
}
/**
* @param int $id
* @return ProjectSponsorshipType|null
*/
public function getSponsorshipTypeById(int $id):?ProjectSponsorshipType{
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('id', $id));
$sponsorshipType = $this->sponsorship_types->matching($criteria)->first();
return $sponsorshipType === false ? null : $sponsorshipType;
}
public function addSponsorshipType(ProjectSponsorshipType $sponsorshipType){
if($this->sponsorship_types->contains($sponsorshipType)) return;
$this->sponsorship_types->add($sponsorshipType);
$sponsorshipType->setSponsoredProject($this);
$sponsorshipType->setOrder($this->sponsorship_types->count());
}
public function removeSponsorshipType(ProjectSponsorshipType $sponsorshipType){
if(!$this->sponsorship_types->contains($sponsorshipType)) return;
$this->sponsorship_types->removeElement($sponsorshipType);
$sponsorshipType->clearSponsoredProject();
}
}

View File

@ -0,0 +1,114 @@
<?php namespace models\main;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\IOrderable;
use App\Models\Utils\BaseEntity;
use models\utils\One2ManyPropertyTrait;
use Doctrine\ORM\Mapping AS ORM;
/**
* @ORM\Entity(repositoryClass="repositories\main\DoctrineSupportingCompanyRepository")
* @ORM\Table(name="SupportingCompany")
* Class SupportingCompany
* @package models\main
*/
class SupportingCompany extends BaseEntity implements IOrderable
{
use One2ManyPropertyTrait;
protected $getIdMappings = [
'getCompanyId' => 'company',
'getSponsorshipId' => 'sponsorship_type',
];
protected $hasPropertyMappings = [
'hasCompany' => 'company',
'hasSponsorshipType' => 'sponsorship_type',
];
/**
* @ORM\ManyToOne(targetEntity="Company", fetch="EXTRA_LAZY")
* @ORM\JoinColumn(name="CompanyID", referencedColumnName="ID", onDelete="SET NULL")
* @var Company
*/
private $company;
/**
* @ORM\ManyToOne(targetEntity="ProjectSponsorshipType", fetch="EXTRA_LAZY")
* @ORM\JoinColumn(name="ProjectSponsorshipTypeID", referencedColumnName="ID", onDelete="SET NULL")
* @var ProjectSponsorshipType
*/
private $sponsorship_type;
/**
* @ORM\Column(name="`Order`", type="integer")
* @var int
*/
private $order;
/**
* @inheritDoc
*/
public function setOrder($order)
{
$this->order = $order;
}
/**
* @inheritDoc
*/
public function getOrder()
{
return $this->order;
}
/**
* @return Company
*/
public function getCompany(): Company
{
return $this->company;
}
/**
* @param Company $company
*/
public function setCompany(Company $company): void
{
$this->company = $company;
}
/**
* @return ProjectSponsorshipType
*/
public function getSponsorshipType(): ProjectSponsorshipType
{
return $this->sponsorship_type;
}
/**
* @param ProjectSponsorshipType $sponsorship_type
*/
public function setSponsorshipType(ProjectSponsorshipType $sponsorship_type): void
{
$this->sponsorship_type = $sponsorship_type;
}
public function clearCompany(){
$this->company = null;
}
public function clearSponsorshipType(){
$this->sponsorship_type = null;
}
}

View File

@ -0,0 +1,39 @@
<?php namespace App\Models\Foundation\Main\Factories;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\main\ProjectSponsorshipType;
/**
* Class ProjectSponsorshipTypeFactory
* @package App\Models\Foundation\Main\Factories
*/
final class ProjectSponsorshipTypeFactory
{
public static function build(array $payload):ProjectSponsorshipType
{
return self::populate(new ProjectSponsorshipType, $payload);
}
public static function populate(ProjectSponsorshipType $projectSponsorshipType, array $payload):ProjectSponsorshipType {
if(isset($payload['name']))
$projectSponsorshipType->setName(trim($payload['name']));
if(isset($payload['description']))
$projectSponsorshipType->setDescription(trim($payload['description']));
if(isset($payload['is_active']))
$projectSponsorshipType->setIsActive(boolval($payload['is_active']));
return $projectSponsorshipType;
}
}

View File

@ -0,0 +1,49 @@
<?php namespace App\Models\Foundation\Main\Factories;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\main\SponsoredProject;
/**
* Class SponsoredProjectFactory
* @package App\Models\Foundation\Main\Factories
*/
final class SponsoredProjectFactory
{
/**
* @param array $payload
* @return SponsoredProject
*/
public static function build(array $payload):SponsoredProject{
return self::populate(new SponsoredProject,$payload);
}
/**
* @param SponsoredProject $sponsoredProject
* @param array $payload
* @return SponsoredProject
*/
public static function populate(SponsoredProject $sponsoredProject, array $payload):SponsoredProject{
if(isset($payload['name']))
$sponsoredProject->setName(trim($payload['name']));
if(isset($payload['description']))
$sponsoredProject->setDescription(trim($payload['description']));
if(isset($payload['is_active']))
$sponsoredProject->setIsActive(boolval($payload['is_active']));
return $sponsoredProject;
}
}

View File

@ -0,0 +1,22 @@
<?php namespace App\Models\Foundation\Main\Repositories;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\utils\IBaseRepository;
/**
* Interface IProjectSponsorshipTypeRepository
* @package App\Models\Foundation\Main\Repositories
*/
interface IProjectSponsorshipTypeRepository extends IBaseRepository
{
}

View File

@ -0,0 +1,23 @@
<?php namespace App\Models\Foundation\Main\Repositories;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\main\SponsoredProject;
use models\utils\IBaseRepository;
/**
* Interface ISponsoredProjectRepository
* @package App\Models\Foundation\Main\Repositories
*/
interface ISponsoredProjectRepository extends IBaseRepository
{
public function getByName(string $name):?SponsoredProject;
}

View File

@ -0,0 +1,22 @@
<?php namespace App\Models\Foundation\Main\Repositories;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\utils\IBaseRepository;
/**
* Interface ISupportingCompanyRepository
* @package App\Models\Foundation\Main\Repositories
*/
interface ISupportingCompanyRepository extends IBaseRepository
{
}

View File

@ -0,0 +1,70 @@
<?php namespace repositories\main;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\Repositories\IProjectSponsorshipTypeRepository;
use App\Repositories\SilverStripeDoctrineRepository;
use Doctrine\ORM\QueryBuilder;
use models\main\ProjectSponsorshipType;
/**
* Class DoctrineProjectSponsorshipTypeRepository
* @package repositories\main
*/
final class DoctrineProjectSponsorshipTypeRepository
extends SilverStripeDoctrineRepository
implements IProjectSponsorshipTypeRepository
{
/**
* @return array
*/
protected function getFilterMappings()
{
return [
'name' => 'e.name:json_string',
'slug' => 'e.slug:json_string',
'is_active' => 'e.is_active:json_int',
'sponsored_project_slug' => 'sp.slug:json_string',
'sponsored_project_id' => 'sp.id:json_int'
];
}
/**
* @param QueryBuilder $query
* @return QueryBuilder
*/
protected function applyExtraJoins(QueryBuilder $query){
$query = $query->innerJoin("e.sponsored_project", "sp");
return $query;
}
/**
* @return array
*/
protected function getOrderMappings()
{
return [
'id' => 'e.id',
'name' => 'e.name',
];
}
/**
* @inheritDoc
*/
protected function getBaseEntity()
{
return ProjectSponsorshipType::class;
}
}

View File

@ -0,0 +1,61 @@
<?php namespace repositories\main;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\Repositories\ISponsoredProjectRepository;
use App\Repositories\SilverStripeDoctrineRepository;
use models\main\SponsoredProject;
/**
* Class DoctrineSponsoredProjectRepository
* @package repositories\main
*/
final class DoctrineSponsoredProjectRepository
extends SilverStripeDoctrineRepository
implements ISponsoredProjectRepository
{
/**
* @return array
*/
protected function getFilterMappings()
{
return [
'name' => 'e.name:json_string',
'slug' => 'e.slug:json_string',
'is_active' => 'e.is_active:json_int',
];
}
/**
* @return array
*/
protected function getOrderMappings()
{
return [
'id' => 'e.id',
'name' => 'e.name',
];
}
/**
* @inheritDoc
*/
protected function getBaseEntity()
{
return SponsoredProject::class;
}
public function getByName(string $name): ?SponsoredProject
{
return $this->findOneBy(['name' => trim($name)]);
}
}

View File

@ -0,0 +1,73 @@
<?php namespace repositories\main;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\Repositories\ISupportingCompanyRepository;
use App\Repositories\SilverStripeDoctrineRepository;
use Doctrine\ORM\QueryBuilder;
use models\main\SupportingCompany;
/**
* Class DoctrineSupportingCompanyRepository
* @package App\Repositories\Main
*/
final class DoctrineSupportingCompanyRepository
extends SilverStripeDoctrineRepository
implements ISupportingCompanyRepository
{
/**
* @return array
*/
protected function getFilterMappings()
{
return [
'name' => 'c.name',
'sponsorship_type_id' => 'st.id',
'sponsorship_type_slug' => 'st.slug',
'sponsored_project_id' => 'sp.id',
'sponsored_project_slug' => 'sp.slug',
];
}
/**
* @return array
*/
protected function getOrderMappings()
{
return [
'name' => 'c.name',
'order' => 'e.order',
];
}
/**
* @param QueryBuilder $query
* @return QueryBuilder
*/
protected function applyExtraJoins(QueryBuilder $query)
{
$query = $query->innerJoin("e.sponsorship_type", "st");
$query = $query->innerJoin("e.company", "c");
$query = $query->innerJoin("st.sponsored_project", "sp");
return $query;
}
/**
* @inheritDoc
*/
protected function getBaseEntity()
{
return SupportingCompany::class;
}
}

View File

@ -14,7 +14,10 @@
use App\Models\Foundation\Main\Language;
use App\Models\Foundation\Main\Repositories\ILanguageRepository;
use App\Models\Foundation\Main\Repositories\IProjectSponsorshipTypeRepository;
use App\Models\Foundation\Main\Repositories\ISponsoredProjectRepository;
use App\Models\Foundation\Main\Repositories\ISummitAdministratorPermissionGroupRepository;
use App\Models\Foundation\Main\Repositories\ISupportingCompanyRepository;
use App\Models\Foundation\Summit\Defaults\DefaultSummitEventType;
use App\Models\Foundation\Summit\DefaultTrackTagGroup;
use App\Models\Foundation\Summit\EmailFlows\SummitEmailEventFlow;
@ -70,7 +73,10 @@ use models\main\File;
use models\main\Group;
use models\main\IOrganizationRepository;
use models\main\Organization;
use models\main\ProjectSponsorshipType;
use models\main\SponsoredProject;
use models\main\SummitAdministratorPermissionGroup;
use models\main\SupportingCompany;
use models\summit\ISponsorUserInfoGrantRepository;
use models\summit\ISummitRegistrationPromoCodeRepository;
use models\summit\ISummitTicketTypeRepository;
@ -83,7 +89,6 @@ use models\summit\SpeakerOrganizationalRole;
use models\summit\SpeakerRegistrationRequest;
use models\summit\SpeakerSummitRegistrationPromoCode;
use models\summit\Sponsor;
use models\summit\SponsorBadgeScan;
use models\summit\SponsorshipType;
use models\summit\SponsorUserInfoGrant;
use models\summit\SummitAbstractLocation;
@ -610,5 +615,26 @@ final class RepositoriesProvider extends ServiceProvider
return EntityManager::getRepository(SummitMetric::class);
}
);
App::singleton(
ISponsoredProjectRepository::class,
function(){
return EntityManager::getRepository(SponsoredProject::class);
}
);
App::singleton(
IProjectSponsorshipTypeRepository::class,
function(){
return EntityManager::getRepository(ProjectSponsorshipType::class);
}
);
App::singleton(
ISupportingCompanyRepository::class,
function(){
return EntityManager::getRepository(SupportingCompany::class);
}
);
}
}

View File

@ -0,0 +1,23 @@
<?php namespace App\Security;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class SponsoredProjectScope
* @package App\Security
*/
final class SponsoredProjectScope
{
const Read = '%s/sponsored-projects/read';
const Write = '%s/sponsored-projects/write';
}

View File

@ -0,0 +1,94 @@
<?php namespace App\Services\Model;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\main\ProjectSponsorshipType;
use models\main\SponsoredProject;
use models\main\SupportingCompany;
/**
* Interface ISponsoredProjectService
* @package App\Services\Model
*/
interface ISponsoredProjectService
{
/**
* @param array $payload
* @return SponsoredProject
* @throws ValidationException
*/
public function add(array $payload):SponsoredProject;
/**
* @param int $project_id
* @param array $payload
* @return SponsoredProject
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function update(int $project_id, array $payload):SponsoredProject;
/**
* @param int $project_id
* @throws EntityNotFoundException
*/
public function delete(int $project_id):void;
/**
* @param int $project_id
* @param array $payload
* @return ProjectSponsorshipType
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function addProjectSponsorshipType(int $project_id, array $payload):ProjectSponsorshipType;
/**
* @param int $project_id
* @param int $sponsorship_id
* @param array $payload
* @return ProjectSponsorshipType
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function updateProjectSponsorshipType(int $project_id, int $sponsorship_id, array $payload):ProjectSponsorshipType;
/**
* @param int $project_id
* @param int $sponsorship_id
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function deleteProjectSponsorshipType(int $project_id, int $sponsorship_id):void;
/**
* @param int $project_id
* @param int $sponsorship_id
* @param int $company_id
* @param array $payload
* @return SupportingCompany
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function addCompanyToProjectSponsorshipType(int $project_id, int $sponsorship_id, int $company_id, array $payload):SupportingCompany;
/**
* @param int $project_id
* @param int $sponsorship_id
* @param int $company_id
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function removeCompanyToProjectSponsorshipType(int $project_id, int $sponsorship_id, int $company_id):void;
}

View File

@ -0,0 +1,262 @@
<?php namespace App\Services\Model\Imp;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Main\Factories\ProjectSponsorshipTypeFactory;
use App\Models\Foundation\Main\Factories\SponsoredProjectFactory;
use App\Models\Foundation\Main\Repositories\ISponsoredProjectRepository;
use App\Services\Model\AbstractService;
use App\Services\Model\ISponsoredProjectService;
use libs\utils\ITransactionService;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\main\Company;
use models\main\ICompanyRepository;
use models\main\ProjectSponsorshipType;
use models\main\SponsoredProject;
use models\main\SupportingCompany;
/**
* Class SponsoredProjectService
* @package App\Services\Model\Imp
*/
final class SponsoredProjectService
extends AbstractService
implements ISponsoredProjectService
{
/**
* @var ISponsoredProjectRepository
*/
private $repository;
/**
* @var ICompanyRepository
*/
private $company_repository;
/**
* SponsoredProjectService constructor.
* @param ISponsoredProjectRepository $repository
* @param ICompanyRepository $company_repository
* @param ITransactionService $tx_service
*/
public function __construct
(
ISponsoredProjectRepository $repository,
ICompanyRepository $company_repository,
ITransactionService $tx_service
)
{
parent::__construct($tx_service);
$this->repository = $repository;
$this->company_repository = $company_repository;
}
/**
* @inheritDoc
*/
public function add(array $payload): SponsoredProject
{
return $this->tx_service->transaction(function() use ($payload){
$name = trim($payload['name']);
$formerProject = $this->repository->getByName($name);
if(!is_null($formerProject)){
throw new ValidationException(sprintf("sponsored project %s already exists.", $name));
}
$sponsoredProject = SponsoredProjectFactory::build($payload);
$this->repository->add($sponsoredProject);
return $sponsoredProject;
});
}
/**
* @inheritDoc
*/
public function update(int $project_id, array $payload): SponsoredProject
{
return $this->tx_service->transaction(function() use ($project_id, $payload){
if(isset($payload['name'])) {
$name = trim($payload['name']);
$formerProject = $this->repository->getByName($name);
if (!is_null($formerProject) && $formerProject->getId() !== $project_id) {
throw new ValidationException(sprintf("sponsored project %s already exists.", $name));
}
}
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
SponsoredProjectFactory::populate($sponsoredProject, $payload);
return $sponsoredProject;
});
}
/**
* @inheritDoc
*/
public function delete(int $project_id): void
{
$this->tx_service->transaction(function() use ($project_id){
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
$this->repository->delete($sponsoredProject);
});
}
/**
* @inheritDoc
*/
public function addProjectSponsorshipType(int $project_id, array $payload): ProjectSponsorshipType
{
return $this->tx_service->transaction(function() use ($project_id, $payload){
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
$name = trim($payload['name']);
if($sponsoredProject->getSponsorshipTypeByName($name)){
throw new ValidationException(sprintf("sponsorship type %s already exists.", $name));
}
$projectSponsorshipType = ProjectSponsorshipTypeFactory::build($payload);
$sponsoredProject->addSponsorshipType($projectSponsorshipType);
return $projectSponsorshipType;
});
}
/**
* @inheritDoc
*/
public function updateProjectSponsorshipType(int $project_id, int $sponsorship_id, array $payload): ProjectSponsorshipType
{
return $this->tx_service->transaction(function() use ($project_id, $sponsorship_id, $payload){
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
if(isset($payload['name'])) {
$name = trim($payload['name']);
$formerProjectSponsorshipType = $sponsoredProject->getSponsorshipTypeByName($name);
if ($formerProjectSponsorshipType && $formerProjectSponsorshipType->getId() !== $sponsorship_id) {
throw new ValidationException(sprintf("sponsorship type %s already exists.", $name));
}
}
$projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id);
if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType)
throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id));
$projectSponsorshipType = ProjectSponsorshipTypeFactory::populate($projectSponsorshipType, $payload);
if (isset($payload['order']) && intval($payload['order']) != $projectSponsorshipType->getOrder()) {
// request to update order
$sponsoredProject->recalculateProjectSponsorshipTypeOrder($projectSponsorshipType, intval($payload['order']));
}
return $projectSponsorshipType;
});
}
/**
* @param int $project_id
* @param int $sponsorship_id
* @throws \Exception
*/
public function deleteProjectSponsorshipType(int $project_id, int $sponsorship_id): void
{
$this->tx_service->transaction(function() use ($project_id, $sponsorship_id){
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
$projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id);
if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType)
throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id));
$sponsoredProject->removeSponsorshipType($projectSponsorshipType);
});
}
/**
* @param int $project_id
* @param int $sponsorship_id
* @param int $company_id
* @param array $payload
* @return SupportingCompany
* @throws \Exception
*/
public function addCompanyToProjectSponsorshipType(int $project_id, int $sponsorship_id, int $company_id, array $payload): SupportingCompany
{
return $this->tx_service->transaction(function() use ($project_id, $sponsorship_id, $company_id, $payload){
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
$projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id);
if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType)
throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id));
$company = $this->company_repository->getById($company_id);
if(is_null($company) || !$company instanceof Company)
throw new EntityNotFoundException(sprintf("company %s not found.", $company_id));
$supportingCompany = $projectSponsorshipType->addSupportingCompany($company);
if (isset($payload['order']) && intval($payload['order']) != $supportingCompany->getOrder()) {
// request to update order
$projectSponsorshipType->recalculateSupportingCompanyOrder($supportingCompany, intval($payload['order']));
}
return $supportingCompany;
});
}
/**
* @inheritDoc
*/
public function removeCompanyToProjectSponsorshipType(int $project_id, int $sponsorship_id, int $company_id): void
{
$this->tx_service->transaction(function() use ($project_id, $sponsorship_id, $company_id){
$sponsoredProject = $this->repository->getById($project_id);
if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject)
throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id));
$projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id);
if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType)
throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id));
$company = $this->company_repository->getById($company_id);
if(is_null($company) || !$company instanceof Company)
throw new EntityNotFoundException(sprintf("company %s not found.", $company_id));
$projectSponsorshipType->removeSupportingCompany($company);
});
}
}

View File

@ -24,6 +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\SponsoredProjectService;
use App\Services\Model\Imp\SponsorUserInfoGrantService;
use App\Services\Model\Imp\SummitAdministratorPermissionGroupService;
use App\Services\Model\Imp\SummitDocumentService;
@ -38,6 +39,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\ISponsoredProjectService;
use App\Services\Model\ISponsorUserInfoGrantService;
use App\Services\Model\ISponsorshipTypeService;
use App\Services\Model\ISummitAccessLevelTypeService;
@ -394,6 +396,12 @@ final class ModelServicesProvider extends ServiceProvider
ISummitMetricService::class,
SummitMetricService::class
);
App::singleton
(
ISponsoredProjectService::class,
SponsoredProjectService::class
);
}
/**

View File

@ -11,7 +11,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\TransactionIsolationLevel;
use Illuminate\Support\Facades\Log;

View File

@ -0,0 +1,108 @@
<?php namespace Database\Migrations\Model;
/**
* Copyright 2019 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema as Schema;
use LaravelDoctrine\Migrations\Schema\Builder;
use LaravelDoctrine\Migrations\Schema\Table;
/**
* Class Version20201119155826
* @package Database\Migrations\Model
*/
class Version20201119155826 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$builder = new Builder($schema);
if(!$schema->hasTable("SponsoredProject")) {
$builder->create('SponsoredProject', function (Table $table) {
$table->integer("ID", true, false);
$table->primary("ID");
$table->timestamp('Created');
$table->timestamp('LastEdited');
$table->string('ClassName');
$table->string('Name')->setLength(255);
$table->string('Description')->setNotnull(false)->setLength(1024);
$table->string('Slug')->setLength(255);
$table->boolean('IsActive');
$table->unique("Name");
$table->unique("Slug");
});
}
if(!$schema->hasTable("ProjectSponsorshipType")) {
$builder->create('ProjectSponsorshipType', function (Table $table) {
$table->integer("ID", true, false);
$table->primary("ID");
$table->timestamp('Created');
$table->timestamp('LastEdited');
$table->string('ClassName');
$table->string('Name')->setLength(255);
$table->string('Description')->setNotnull(false)->setLength(1024);
$table->string('Slug')->setLength(255);
$table->integer('Order')->setDefault(1);;
$table->boolean('IsActive');
// FK
$table->integer("SponsoredProjectID", false, false)->setNotnull(false)->setDefault('NULL');
$table->index("SponsoredProjectID", "SponsoredProjectID");
$table->foreign("SponsoredProject", "SponsoredProjectID", "ID", ["onDelete" => "CASCADE"]);
$table->unique(["Name", "SponsoredProjectID"]);
$table->unique(["Slug", "SponsoredProjectID"]);
});
}
if(!$schema->hasTable("SupportingCompany")) {
$builder->create('SupportingCompany', function (Table $table) {
$table->integer("ID", true, false);
$table->primary("ID");
$table->integer('Order')->setDefault(1);
// FK
$table->integer("CompanyID", false, false)->setNotnull(false)->setDefault('NULL');
$table->index("CompanyID", "CompanyID");
$table->foreign("Company", "CompanyID", "ID", ["onDelete" => "CASCADE"]);
// FK
$table->integer("ProjectSponsorshipTypeID", false, false)->setNotnull(false)->setDefault('NULL');
$table->index("ProjectSponsorshipTypeID", "ProjectSponsorshipTypeID");
$table->foreign("ProjectSponsorshipType", "ProjectSponsorshipTypeID", "ID", ["onDelete" => "CASCADE"]);
});
}
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
$builder = new Builder($schema);
$builder->dropIfExists("SupportingCompany");
$builder->dropIfExists("ProjectSponsorshipType");
$builder->dropIfExists("SponsoredProject");
}
}

View File

@ -0,0 +1,45 @@
<?php namespace Database\Migrations\Model;
/**
* Copyright 2019 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema as Schema;
/**
* Class Version20201120143925
* @package Database\Migrations\Model
*/
class Version20201120143925 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$sql = <<<SQL
ALTER TABLE `SponsoredProject` CHANGE `ClassName` `ClassName` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT 'SponsoredProject';
SQL;
$this->addSql($sql);
$sql = <<<SQL
ALTER TABLE `ProjectSponsorshipType` CHANGE `ClassName` `ClassName` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT 'ProjectSponsorshipType';
SQL;
$this->addSql($sql);
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
}
}

View File

@ -20,6 +20,7 @@ use App\Security\OrganizationScopes;
use App\Security\MemberScopes;
use App\Models\Foundation\Main\IGroup;
use App\Security\CompanyScopes;
use App\Security\SponsoredProjectScope;
/**
* Class ApiEndpointsSeeder
*/
@ -36,6 +37,7 @@ class ApiEndpointsSeeder extends Seeder
$this->seedMemberEndpoints();
$this->seedTagsEndpoints();
$this->seedCompaniesEndpoints();
$this->seedSponsoredProjectsEndpoints();
$this->seedGroupsEndpoints();
$this->seedOrganizationsEndpoints();
$this->seedTrackQuestionTemplateEndpoints();
@ -5683,6 +5685,152 @@ class ApiEndpointsSeeder extends Seeder
);
}
private function seedSponsoredProjectsEndpoints(){
$current_realm = Config::get('app.scope_base_realm');
$this->seedApiEndpoints('sponsored-projects', [
[
'name' => 'get-sponsored-projects',
'route' => '/api/v1/sponsored-projects',
'http_method' => 'GET',
'scopes' => [
sprintf(SponsoredProjectScope::Read, $current_realm)
],
],
[
'name' => 'add-sponsored-projects',
'route' => '/api/v1/sponsored-projects',
'http_method' => 'POST',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'update-sponsored-projects',
'route' => '/api/v1/sponsored-projects/{id}',
'http_method' => 'PUT',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'delete-sponsored-projects',
'route' => '/api/v1/sponsored-projects/{id}',
'http_method' => 'DELETE',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'get-sponsored-project',
'route' => '/api/v1/sponsored-projects/{id}',
'http_method' => 'GET',
'scopes' => [
sprintf(SponsoredProjectScope::Read, $current_realm)
]
],
// sponsorship types
[
'name' => 'get-sponsored-project-sponsorship-types',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types',
'http_method' => 'GET',
'scopes' => [
sprintf(SponsoredProjectScope::Read, $current_realm)
],
],
[
'name' => 'add-sponsored-project-sponsorship-types',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types',
'http_method' => 'POST',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'update-sponsored-project-sponsorship-types',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}',
'http_method' => 'PUT',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'delete-sponsored-project-sponsorship-types',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}',
'http_method' => 'DELETE',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'get-sponsored-project-sponsorship-type',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}',
'http_method' => 'GET',
'scopes' => [
sprintf(SponsoredProjectScope::Read, $current_realm)
],
],
[
'name' => 'get-sponsored-project-supporting-companies',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}/supporting-companies',
'http_method' => 'GET',
'scopes' => [
sprintf(SponsoredProjectScope::Read, $current_realm)
],
],
[
'name' => 'add-sponsored-project-supporting-companies',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}/supporting-companies/{company_id}',
'http_method' => 'PUT',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
[
'name' => 'delete-sponsored-project-supporting-companies',
'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}/supporting-companies/{company_id}',
'http_method' => 'DELETE',
'scopes' => [
sprintf(SponsoredProjectScope::Write, $current_realm)
],
'authz_groups' => [
IGroup::SuperAdmins,
IGroup::Administrators,
]
],
]
);
}
private function seedGroupsEndpoints(){
$current_realm = Config::get('app.scope_base_realm');

View File

@ -20,6 +20,7 @@ use App\Security\SummitScopes;
use App\Security\OrganizationScopes;
use App\Security\MemberScopes;
use App\Security\CompanyScopes;
use App\Security\SponsoredProjectScope;
/**
* Class ApiScopesSeeder
*/
@ -36,6 +37,7 @@ final class ApiScopesSeeder extends Seeder
$this->seedTeamsScopes();
$this->seedTagsScopes();
$this->seedCompaniesScopes();
$this->seedSponsoredProjectsScopes();
$this->seedGroupsScopes();
$this->seedOrganizationScopes();
$this->seedSummitAdminGroupScopes();
@ -516,6 +518,37 @@ final class ApiScopesSeeder extends Seeder
EntityManager::flush();
}
private function seedSponsoredProjectsScopes(){
$current_realm = Config::get('app.scope_base_realm');
$api = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'sponsored-projects']);
$scopes = [
[
'name' => sprintf(SponsoredProjectScope::Read, $current_realm),
'short_description' => 'Get Sponsored Projects Data',
'description' => 'Grants read only access for Sponsored Projects Data',
],
[
'name' => sprintf(SponsoredProjectScope::Write, $current_realm),
'short_description' => 'Write Sponsored Projects Data',
'description' => 'Grants write only access for Sponsored Projects Data',
],
];
foreach ($scopes as $scope_info) {
$scope = new ApiScope();
$scope->setName($scope_info['name']);
$scope->setShortDescription($scope_info['short_description']);
$scope->setDescription($scope_info['description']);
$scope->setActive(true);
$scope->setDefault(false);
$scope->setApi($api);
EntityManager::persist($scope);
}
EntityManager::flush();
}
private function seedGroupsScopes(){
$current_realm = Config::get('app.scope_base_realm');
$api = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'groups']);

View File

@ -76,6 +76,16 @@ final class ApiSeeder extends Seeder
EntityManager::flush();
// sponsored projects
$api = new Api();
$api->setName('sponsored-projects');
$api->setActive(true);
$api->setDescription('Sponsored Projects API');
EntityManager::persist($api);
EntityManager::flush();
//groups
$api = new Api();

View File

@ -0,0 +1,221 @@
<?php
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class OAuth2SponsoredProjectsApiTest
*/
class OAuth2SponsoredProjectsApiTest extends ProtectedApiTest
{
public function testAddSponsoredProject(){
$data = [
'name' => str_random(16).'_sponsored project',
'description' => str_random(16).'_sponsored project description',
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action(
"POST",
"OAuth2SponsoredProjectApiController@add",
[],
[],
[],
[],
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(201);
$sponsored_projects = json_decode($content);
$this->assertTrue(!is_null($sponsored_projects));
return $sponsored_projects;
}
public function testGelAll()
{
$params = [
//AND FILTER
'filter' => ['name=@sponsored project'],
'order' => '-id'
];
$headers = array("HTTP_Authorization" => " Bearer " . $this->access_token);
$response = $this->action(
"GET",
"OAuth2SponsoredProjectApiController@getAll",
$params,
array(),
array(),
array(),
$headers
);
$content = $response->getContent();
$companies = json_decode($content);
$this->assertTrue(!is_null($companies));
$this->assertResponseStatus(200);
}
public function testAddSponsorshipType(){
$params = [
'id' => 1,
];
$data = [
'name' => str_random(16).' sponsorship type',
'description' => str_random(16).' sponsorship type description',
'is_active' => true,
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action(
"POST",
"OAuth2SponsoredProjectApiController@addSponsorshipType",
$params,
[],
[],
[],
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(201);
$sponsorship_type = json_decode($content);
$this->assertTrue(!is_null($sponsorship_type));
return $sponsorship_type;
}
public function testUpdateSponsorshipType(){
$params = [
'id' => 1,
'sponsorship_type_id' => 6
];
$data = [
'order' => 1
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action(
"PUT",
"OAuth2SponsoredProjectApiController@updateSponsorshipType",
$params,
[],
[],
[],
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(204);
$sponsorship_type = json_decode($content);
$this->assertTrue(!is_null($sponsorship_type));
return $sponsorship_type;
}
public function testGetAllSponsorshipTypes(){
$params = [
'id' => 'kata-containers',
'expand' => 'supporting_companies, supporting_companies.company'
];
$headers = array("HTTP_Authorization" => " Bearer " . $this->access_token);
$response = $this->action(
"GET",
"OAuth2SponsoredProjectApiController@getAllSponsorshipTypes",
$params,
array(),
array(),
array(),
$headers
);
$content = $response->getContent();
$page = json_decode($content);
$this->assertTrue(!is_null($page));
$this->assertResponseStatus(200);
}
public function testAddSupportingCompany(){
$params = [
'id' => 1,
'sponsorship_type_id' => 1,
'company_id' => 12,
];
$data = [
'order' => 2
];
$headers = array("HTTP_Authorization" => " Bearer " . $this->access_token);
$response = $this->action(
"PUT",
"OAuth2SponsoredProjectApiController@addSupportingCompanies",
$params,
array(),
array(),
array(),
$headers,
json_encode($data)
);
$content = $response->getContent();
$company = json_decode($content);
$this->assertTrue(!is_null($company));
$this->assertResponseStatus(200);
}
public function testGetAllSupportingCompanies(){
$params = [
'id' => 'kata-containers',
'sponsorship_type_id' => 'platinum-members',
'expand' => 'company'
];
$headers = array("HTTP_Authorization" => " Bearer " . $this->access_token);
$response = $this->action(
"GET",
"OAuth2SponsoredProjectApiController@getSupportingCompanies",
$params,
array(),
array(),
array(),
$headers
);
$content = $response->getContent();
$page = json_decode($content);
$this->assertTrue(!is_null($page));
$this->assertResponseStatus(200);
}
}

View File

@ -20,6 +20,7 @@ use App\Security\OrganizationScopes;
use App\Security\MemberScopes;
use App\Models\Foundation\Main\IGroup;
use App\Security\CompanyScopes;
use App\Security\SponsoredProjectScope;
/**
* Class AccessTokenServiceStub
*/
@ -109,6 +110,8 @@ class AccessTokenServiceStub implements IAccessTokenService
sprintf(SummitScopes::WriteSummitMediaFileTypes, $url),
sprintf(CompanyScopes::Write, $url),
sprintf(CompanyScopes::Read, $url),
sprintf(SponsoredProjectScope::Write, $url),
sprintf(SponsoredProjectScope::Read, $url),
sprintf(SummitScopes::WriteMetrics, $url),
sprintf(SummitScopes::ReadMetrics, $url),
);
@ -208,6 +211,8 @@ class AccessTokenServiceStub2 implements IAccessTokenService
sprintf(SummitScopes::ReadMetrics, $url),
sprintf(CompanyScopes::Write, $url),
sprintf(CompanyScopes::Read, $url),
sprintf(SponsoredProjectScope::Write, $url),
sprintf(SponsoredProjectScope::Read, $url),
);
return AccessToken::createFromParams(

View File

@ -0,0 +1,73 @@
<?php namespace Tests;
use LaravelDoctrine\ORM\Facades\EntityManager;
use models\main\Company;
use models\main\ProjectSponsorshipType;
use models\main\SponsoredProject;
use models\summit\SponsorshipType;
/**
* Copyright 2020 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class SponsoredProjectModelTest
* @package Tests
*/
class SponsoredProjectModelTest extends BrowserKitTestCase
{
use \InsertSummitTestData;
protected function setUp()
{
parent::setUp();
self::insertTestData();
self::$em->persist(self::$summit);
self::$em->flush();
}
protected function tearDown()
{
self::clearTestData();
parent::tearDown();
}
public function testCreateSponsoredProject(){
$company_repository = EntityManager::getRepository(Company::class);
$p1 = new SponsoredProject();
$p1->setName("Kata Containers");
$p1->setIsActive(true);
$sponsorship1 = new ProjectSponsorshipType();
$sponsorship1->setName("PLATINUM MEMBERS");
$description1 = <<<HTML
Open Infrastructure Foundation Platinum Members provide a significant portion of the funding to achieve the Foundation's mission of protecting, empowering and promoting the Open Infrastructure community and open source software projects. Each Platinum Member's company strategy aligns with the OIF mission and is responsible for committing full-time resources toward the project. There are eight Platinum Members at any given time, each of which holds a seat on the Board of Directors. Thank you to the following Platinum Members who are committed to the Open Infrastructure community's success.
HTML;
$sponsorship1->setDescription($description1);
$sponsorship1->setIsActive(true);
$p1->addSponsorshipType($sponsorship1);
$companies = $company_repository->findAll();
$sponsorship1->addSupportingCompany($companies[0]);
$sponsorship1->addSupportingCompany($companies[1]);
self::$em->persist($p1);
self::$em->flush();
}
}