Migration of resource server

* removed resource server code
* removed marketplace api
* removed marketplace api test
* made tests agnostic of realm
* added missing http headers
* fix on db schemes ( added default values on some tables).
Change-Id: I857bc2c795107bb63c03652397c406b97ba8c86a
This commit is contained in:
Sebastian Marcet 2015-04-29 19:00:13 -03:00
parent 6a0196376e
commit 2a65750477
78 changed files with 673 additions and 2552 deletions

View File

@ -26,7 +26,7 @@ return array(
|
*/
'url' => 'https://dev.openstackid.com',
'url' => 'https://local.openstackid.openstack.org',
/*
|--------------------------------------------------------------------------

View File

@ -107,7 +107,7 @@ class ApiController extends AbstractRESTController implements ICRUDController
{
try {
$res = $this->api_service->delete($id);
return $res?$this->deleted():$this->error404(array('error'=>'operation failed'));
return $res ? $this->deleted() : $this->error404(array('error'=>'operation failed'));
} catch (Exception $ex) {
$this->log_service->error($ex);
return $this->error500($ex);

View File

@ -1,8 +1,25 @@
<?php
/**
* Copyright 2015 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 utils\services\ILogService;
use openid\services\IUserService;
use oauth2\services\ITokenService;
use oauth2\exceptions\ExpiredAccessTokenException;
/**
* Class UserApiController
*/
class UserApiController extends AbstractRESTController implements ICRUDController {
private $user_service;
@ -46,6 +63,8 @@ class UserApiController extends AbstractRESTController implements ICRUDControlle
switch($hint){
case 'access_token':{
$token = $this->token_service->getAccessToken($value,true);
if(is_null($token))
throw new Exception(sprintf("access token %s expired!.",$value));
if(is_null($token->getUserId()) || intval($token->getUserId())!=intval($id))
throw new Exception(sprintf("access token %s does not belongs to user id %s!.",$value,$id));
$this->token_service->revokeAccessToken($value,true);
@ -53,6 +72,8 @@ class UserApiController extends AbstractRESTController implements ICRUDControlle
break;
case 'refresh_token':
$token = $this->token_service->getRefreshToken($value,true);
if(is_null($token))
throw new Exception(sprintf("access token %s expired!.",$value));
if(is_null($token->getUserId()) || intval($token->getUserId())!=intval($id))
throw new Exception(sprintf("refresh token %s does not belongs to user id %s!.",$value,$id));
$this->token_service->revokeRefreshToken($value,true);
@ -63,6 +84,10 @@ class UserApiController extends AbstractRESTController implements ICRUDControlle
}
return $this->ok();
}
catch(ExpiredAccessTokenException $ex1){
$this->log_service->warning($ex1);
return $this->error404();
}
catch(Exception $ex){
$this->log_service->error($ex);
return $this->error500($ex);

View File

@ -29,5 +29,4 @@ class OAuth2UserApiController extends OAuth2ProtectedController {
return $this->error500($ex);
}
}
}
}

View File

@ -1,81 +0,0 @@
<?php
/**
* Copyright 2015 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 oauth2\IResourceServerContext;
use utils\services\ILogService;
use models\marketplace\repositories\ICloudServiceRepository;
/**
* Class OAuth2CloudApiController
*/
abstract class OAuth2CloudApiController extends OAuth2CompanyServiceApiController {
/**
* query string params:
* page: You can specify further pages
* per_page: custom page size up to 100 ( min 10)
* status: cloud status ( active , not active, all)
* order_by: order by field
* order_dir: order direction
* @return mixed
*/
public function getClouds()
{
return $this->getCompanyServices();
}
/**
* @param $id
* @return mixed
*/
public function getCloud($id)
{
return $this->getCompanyService($id);
}
/**
* @param $id
* @return mixed
*/
public function getCloudDataCenters($id)
{
try{
$cloud = $this->repository->getById($id);
if(!$cloud)
return $this->error404();
$data_center_regions = $cloud->datacenters_regions();
$res = array();
foreach($data_center_regions as $region){
$data = $region->toArray();
$locations = $region->locations();
$data_locations = array();
foreach($locations as $loc){
array_push($data_locations, $loc->toArray());
}
$data['locations'] = $data_locations;
array_push($res, $data);
}
return $this->ok(array('datacenters' => $res ));
}
catch(Exception $ex){
$this->log_service->error($ex);
return $this->error500($ex);
}
}
}

View File

@ -1,133 +0,0 @@
<?php
/**
* Copyright 2015 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\marketplace\repositories\ICompanyServiceRepository;
use oauth2\IResourceServerContext;
use utils\services\ILogService;
/**
* Class OAuth2CompanyServiceApiController
*/
abstract class OAuth2CompanyServiceApiController extends OAuth2ProtectedController{
/**
* @var ICompanyServiceRepository
*/
protected $repository;
public function __construct (IResourceServerContext $resource_server_context, ILogService $log_service){
parent::__construct($resource_server_context,$log_service);
Validator::extend('status', function($attribute, $value, $parameters)
{
return $value == ICompanyServiceRepository::Status_All ||
$value == ICompanyServiceRepository::Status_non_active ||
$value == ICompanyServiceRepository::Status_active;
});
Validator::extend('order', function($attribute, $value, $parameters)
{
return $value == ICompanyServiceRepository::Order_date ||
$value == ICompanyServiceRepository::Order_name ;
});
Validator::extend('order_dir', function($attribute, $value, $parameters)
{
return $value == 'desc' ||
$value == 'asc';
});
}
/**
* query string params:
* page: You can specify further pages
* per_page: custom page size up to 100 ( min 10)
* status: cloud status ( active , not active, all)
* order_by: order by field
* order_dir: order direction
* @return mixed
*/
public function getCompanyServices()
{
try{
//default params
$page = 1;
$per_page = 10;
$status = ICompanyServiceRepository::Status_All;
$order_by = ICompanyServiceRepository::Order_date;
$order_dir = 'asc';
//validation of optional parameters
$values = Input::all();
$messages = array(
'status' => 'The :attribute field is does not has a valid value (all, active, non_active).',
'order' => 'The :attribute field is does not has a valid value (date, name).',
'order_dir' => 'The :attribute field is does not has a valid value (desc, asc).',
);
$rules = array(
'page' => 'integer|min:1',
'per_page' => 'required_with:page|integer|min:10|max:100',
'status' => 'status',
'order_by' => 'order',
'order_dir' => 'required_with:order_by|order_dir',
);
// Creates a Validator instance and validates the data.
$validation = Validator::make($values, $rules, $messages);
if ($validation->fails()) {
$messages = $validation->messages()->toArray();
return $this->error412($messages);
}
if(Input::has('page')){
$page = intval(Input::get('page'));
$per_page = intval(Input::get('per_page'));
}
if(Input::has('status')){
$status = Input::get('status');
}
if(Input::has('order_by')){
$order_by = Input::get('order_by');
$order_dir = Input::get('order_dir');
}
$data = $this->repository->getAll($page, $per_page, $status, $order_by, $order_dir);
return $this->ok($data);
}
catch(Exception $ex){
$this->log_service->error($ex);
return $this->error500($ex);
}
}
/**
* @param $id
* @return mixed
*/
public function getCompanyService($id)
{
try{
$data = $this->repository->getById($id);
return ($data)? $this->ok($data) : $this->error404();
}
catch(Exception $ex){
$this->log_service->error($ex);
return $this->error500($ex);
}
}
}

View File

@ -1,82 +0,0 @@
<?php
/**
* Copyright 2015 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\marketplace\repositories\IConsultantRepository;
use oauth2\IResourceServerContext;
use utils\services\ILogService;
/**
* Class OAuth2ConsultantsApiController
*/
class OAuth2ConsultantsApiController extends OAuth2CompanyServiceApiController {
/**
* @param IConsultantRepository $repository
* @param IResourceServerContext $resource_server_context
* @param ILogService $log_service
*/
public function __construct (IConsultantRepository $repository, IResourceServerContext $resource_server_context, ILogService $log_service){
$this->repository = $repository;
parent::__construct($resource_server_context,$log_service);
}
/**
* query string params:
* page: You can specify further pages
* per_page: custom page size up to 100 ( min 10)
* status: cloud status ( active , not active, all)
* order_by: order by field
* order_dir: order direction
* @return mixed
*/
public function getConsultants()
{
return $this->getCompanyServices();
}
/**
* @param $id
* @return mixed
*/
public function getConsultant($id)
{
return $this->getCompanyService($id);
}
/**
* @param $id
* @return mixed
*/
public function getOffices($id)
{
try{
$consultant = $this->repository->getById($id);
if(!$consultant)
return $this->error404();
$offices = $consultant->offices();
$res = array();
foreach($offices as $office){
array_push($res, $office->toArray());
}
return $this->ok(array('offices' => $res));
}
catch(Exception $ex){
$this->log_service->error($ex);
return $this->error500($ex);
}
}
}

View File

@ -1,27 +0,0 @@
<?php
/**
* Copyright 2014 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\marketplace\repositories\IPrivateCloudServiceRepository;
use oauth2\IResourceServerContext;
use utils\services\ILogService;
/**
* Class OAuth2PrivateCloudApiController
*/
final class OAuth2PrivateCloudApiController extends OAuth2CloudApiController {
public function __construct (IPrivateCloudServiceRepository $repository, IResourceServerContext $resource_server_context, ILogService $log_service){
parent::__construct($resource_server_context,$log_service);
$this->repository = $repository;
}
}

View File

@ -1,29 +0,0 @@
<?php
/**
* Copyright 2015 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\marketplace\repositories\IPublicCloudServiceRepository;
use oauth2\IResourceServerContext;
use utils\services\ILogService;
/**
* Class OAuth2PublicCloudApiController
*/
final class OAuth2PublicCloudApiController extends OAuth2CloudApiController {
public function __construct (IPublicCloudServiceRepository $repository, IResourceServerContext $resource_server_context, ILogService $log_service){
parent::__construct($resource_server_context,$log_service);
$this->repository = $repository;
}
}

View File

@ -14,12 +14,12 @@ class CreateExtensionTable extends Migration {
Schema::create('server_extensions', function($table)
{
$table->bigIncrements('id');
$table->string('name',100);
$table->string('namespace',255);
$table->string('name',100)->nullable()->default('');
$table->string('namespace',255)->nullable()->default('');
$table->boolean('active')->default(false);
$table->string('extension_class',255);
$table->string('description',255)->nullable();
$table->string('view_name',255);
$table->string('extension_class',255)->nullable()->default('');
$table->string('description',255)->nullable()->default('');
$table->string('view_name',255)->nullable()->default('');
$table->timestamps();
});
}

View File

@ -14,14 +14,14 @@ class CreateUsersTable extends Migration {
Schema::create('openid_users', function($table)
{
$table->bigIncrements('id');
$table->string('identifier',255);
$table->string('identifier',255)->nullable();
$table->string('external_id',100);
$table->boolean('active')->default(true);
$table->boolean('lock')->default(false);
$table->boolean('public_profile_show_photo')->default(false);
$table->boolean('public_profile_show_fullname')->default(false);
$table->boolean('public_profile_show_email')->default(false);
$table->dateTime('last_login_date');
$table->dateTime('last_login_date')->default(date("Y-m-d H:i:s"));
$table->integer('login_failed_attempt')->default(0);
$table->timestamps();
});

View File

@ -14,8 +14,8 @@ class CreateOauth2ClientsTable extends Migration {
Schema::create('oauth2_client', function($table)
{
$table->bigIncrements('id')->unsigned();
$table->string('app_name',255);
$table->text('app_description');
$table->string('app_name',255)->nullable();
$table->text('app_description')->nullable();
$table->string('app_logo',255)->nullable();
$table->string('client_id',255)->unique();
$table->string('client_secret',255)->nullable();
@ -30,13 +30,13 @@ class CreateOauth2ClientsTable extends Migration {
$table->timestamps();
$table->integer('max_auth_codes_issuance_qty')->default(0);
$table->smallInteger('max_auth_codes_issuance_basis');
$table->smallInteger('max_auth_codes_issuance_basis')->default(0);
$table->integer('max_access_token_issuance_qty')->default(0);
$table->smallInteger('max_access_token_issuance_basis');
$table->smallInteger('max_access_token_issuance_basis')->default(0);
$table->integer('max_refresh_token_issuance_qty')->default(0);
$table->smallInteger('max_refresh_token_issuance_basis');
$table->smallInteger('max_refresh_token_issuance_basis')->default(0);
$table->boolean('use_refresh_token')->default(false);
$table->boolean('rotate_refresh_token')->default(false);

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class UpdateOauth2ApiTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('oauth2_api', function($table)
{
$table->dropUnique('oauth2_api_name_unique');
$table->unique(array('name','resource_server_id'));
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('oauth2_api', function($table)
{
});
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class UpdateOauth2ApiEndpointTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('oauth2_api_endpoint', function($table)
{
$table->dropUnique('oauth2_api_endpoint_name_unique');
$table->unique(array('name','http_method','api_id'));
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DeleteMarketplaceApiEndpointsScopes extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$public_clouds = Api::where('name','=','public-clouds')->first();
if($public_clouds) $public_clouds->delete();
$private_clouds = Api::where('name','=','private-clouds')->first();
if($private_clouds) $private_clouds->delete();
$consultants = Api::where('name','=','consultants')->first();
if($consultants) $consultants->delete();
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -12,9 +12,6 @@ class ApiEndpointSeeder extends Seeder
DB::table('oauth2_api_endpoint_api_scope')->delete();
DB::table('oauth2_api_endpoint')->delete();
$this->seedUsersEndpoints();
$this->seedPublicCloudsEndpoints();
$this->seedPrivateCloudsEndpoints();
$this->seedConsultantsEndpoints();
}
private function seedUsersEndpoints()
@ -42,146 +39,4 @@ class ApiEndpointSeeder extends Seeder
$get_user_info_endpoint->scopes()->attach($address_scope->id);
}
private function seedPublicCloudsEndpoints(){
$public_clouds = Api::where('name','=','public-clouds')->first();
$current_realm = Config::get('app.url');
// endpoints scopes
ApiEndpoint::create(
array(
'name' => 'get-public-clouds',
'active' => true,
'api_id' => $public_clouds->id,
'route' => '/api/v1/marketplace/public-clouds',
'http_method' => 'GET'
)
);
ApiEndpoint::create(
array(
'name' => 'get-public-cloud',
'active' => true,
'api_id' => $public_clouds->id,
'route' => '/api/v1/marketplace/public-clouds/{id}',
'http_method' => 'GET'
)
);
ApiEndpoint::create(
array(
'name' => 'get-public-cloud-datacenters',
'active' => true,
'api_id' => $public_clouds->id,
'route' => '/api/v1/marketplace/public-clouds/{id}/data-centers',
'http_method' => 'GET'
)
);
$public_cloud_read_scope = ApiScope::where('name','=',sprintf('%s/public-clouds/read',$current_realm))->first();
$endpoint_get_public_clouds = ApiEndpoint::where('name','=','get-public-clouds')->first();
$endpoint_get_public_clouds->scopes()->attach($public_cloud_read_scope->id);
$endpoint_get_public_cloud = ApiEndpoint::where('name','=','get-public-cloud')->first();
$endpoint_get_public_cloud->scopes()->attach($public_cloud_read_scope->id);
$endpoint_get_public_cloud_datacenters = ApiEndpoint::where('name','=','get-public-cloud-datacenters')->first();
$endpoint_get_public_cloud_datacenters->scopes()->attach($public_cloud_read_scope->id);
}
private function seedPrivateCloudsEndpoints(){
$private_clouds = Api::where('name','=','private-clouds')->first();
$current_realm = Config::get('app.url');
// endpoints scopes
ApiEndpoint::create(
array(
'name' => 'get-private-clouds',
'active' => true,
'api_id' => $private_clouds->id,
'route' => '/api/v1/marketplace/private-clouds',
'http_method' => 'GET'
)
);
ApiEndpoint::create(
array(
'name' => 'get-private-cloud',
'active' => true,
'api_id' => $private_clouds->id,
'route' => '/api/v1/marketplace/private-clouds/{id}',
'http_method' => 'GET'
)
);
ApiEndpoint::create(
array(
'name' => 'get-private-cloud-datacenters',
'active' => true,
'api_id' => $private_clouds->id,
'route' => '/api/v1/marketplace/private-clouds/{id}/data-centers',
'http_method' => 'GET'
)
);
$private_cloud_read_scope = ApiScope::where('name','=',sprintf('%s/private-clouds/read',$current_realm))->first();
$endpoint_get_private_clouds = ApiEndpoint::where('name','=','get-private-clouds')->first();
$endpoint_get_private_clouds->scopes()->attach($private_cloud_read_scope->id);
$endpoint_get_private_cloud = ApiEndpoint::where('name','=','get-private-cloud')->first();
$endpoint_get_private_cloud->scopes()->attach($private_cloud_read_scope->id);
$endpoint_get_private_cloud_datacenters = ApiEndpoint::where('name','=','get-private-cloud-datacenters')->first();
$endpoint_get_private_cloud_datacenters->scopes()->attach($private_cloud_read_scope->id);
}
private function seedConsultantsEndpoints(){
$consultants = Api::where('name','=','consultants')->first();
$current_realm = Config::get('app.url');
// endpoints scopes
ApiEndpoint::create(
array(
'name' => 'get-consultants',
'active' => true,
'api_id' => $consultants->id,
'route' => '/api/v1/marketplace/consultants',
'http_method' => 'GET'
)
);
ApiEndpoint::create(
array(
'name' => 'get-consultant',
'active' => true,
'api_id' => $consultants->id,
'route' => '/api/v1/marketplace/consultants/{id}',
'http_method' => 'GET'
)
);
ApiEndpoint::create(
array(
'name' => 'get-consultant-offices',
'active' => true,
'api_id' => $consultants->id,
'route' => '/api/v1/marketplace/consultants/{id}/offices',
'http_method' => 'GET'
)
);
$consultant_read_scope = ApiScope::where('name','=',sprintf('%s/consultants/read',$current_realm))->first();
$endpoint = ApiEndpoint::where('name','=','get-consultants')->first();
$endpoint->scopes()->attach($consultant_read_scope->id);
$endpoint = ApiEndpoint::where('name','=','get-consultant')->first();
$endpoint->scopes()->attach($consultant_read_scope->id);
$endpoint = ApiEndpoint::where('name','=','get-consultant-offices')->first();
$endpoint->scopes()->attach($consultant_read_scope->id);
}
}

View File

@ -5,16 +5,12 @@
*/
class ApiScopeSeeder extends Seeder {
public function run()
{
DB::table('oauth2_api_endpoint_api_scope')->delete();
DB::table('oauth2_client_api_scope')->delete();
DB::table('oauth2_api_scope')->delete();
$this->seedUsersScopes();
$this->seedPublicCloudScopes();
$this->seedPrivateCloudScopes();
$this->seedConsultantScopes();
}
private function seedUsersScopes(){
@ -53,53 +49,4 @@ class ApiScopeSeeder extends Seeder {
}
private function seedPublicCloudScopes(){
$current_realm = Config::get('app.url');
$public_clouds = Api::where('name','=','public-clouds')->first();
ApiScope::create(
array(
'name' => sprintf('%s/public-clouds/read',$current_realm),
'short_description' => 'Get Public Clouds',
'description' => 'Grants read only access for Public Clouds',
'api_id' => $public_clouds->id,
'system' => false,
)
);
}
private function seedPrivateCloudScopes(){
$current_realm = Config::get('app.url');
$private_clouds = Api::where('name','=','private-clouds')->first();
ApiScope::create(
array(
'name' => sprintf('%s/private-clouds/read',$current_realm),
'short_description' => 'Get Private Clouds',
'description' => 'Grants read only access for Private Clouds',
'api_id' => $private_clouds->id,
'system' => false,
)
);
}
private function seedConsultantScopes(){
$current_realm = Config::get('app.url');
$consultants = Api::where('name','=','consultants')->first();
ApiScope::create(
array(
'name' => sprintf('%s/consultants/read',$current_realm),
'short_description' => 'Get Consultants',
'description' => 'Grants read only access for Consultants',
'api_id' => $consultants->id,
'system' => false,
)
);
}
}

View File

@ -25,38 +25,5 @@ class ApiSeeder extends Seeder {
'logo' => asset('img/apis/server.png')
)
);
// public clouds
Api::create(
array(
'name' => 'public-clouds',
'logo' => null,
'active' => true,
'Description' => 'Marketplace Public Clouds',
'resource_server_id' => $resource_server->id,
'logo' => asset('img/apis/server.png')
)
);
// private clouds
Api::create(
array(
'name' => 'private-clouds',
'logo' => null,
'active' => true,
'Description' => 'Marketplace Private Clouds',
'resource_server_id' => $resource_server->id,
'logo' => asset('img/apis/server.png')
)
);
// consultants
Api::create(
array(
'name' => 'consultants',
'logo' => null,
'active' => true,
'Description' => 'Marketplace Consultants',
'resource_server_id' => $resource_server->id,
'logo' => asset('img/apis/server.png')
)
);
}
}

View File

@ -23,7 +23,7 @@ class OpenIdExtensionsSeeder extends Seeder {
'namespace' => 'http://openid.net/extensions/sreg/1.1',
'active' => true,
'extension_class' => 'openid\extensions\implementations\OpenIdSREGExtension',
'description' => 'OpenID Simple Registation is an extension to the OpenID Authentication protocol that allows for very light-weight profile exchange. It is designed to pass eight commonly requested pieces of information when an End User goes to register a new account with a web service',
'description' => 'OpenID Simple Registration is an extension to the OpenID Authentication protocol that allows for very light-weight profile exchange.',
'view_name' => 'extensions.sreg',
)
);
@ -35,7 +35,7 @@ class OpenIdExtensionsSeeder extends Seeder {
'namespace' => 'http://specs.openid.net/extensions/oauth/2.0',
'active' => true,
'extension_class' => 'openid\extensions\implementations\OpenIdOAuth2Extension',
'description' => 'The OpenID OAuth2 Extension describes how to make the OpenID Authentication and OAuth2 Core specifications work well togethe',
'description' => 'The OpenID OAuth2 Extension describes how to make the OpenID Authentication and OAuth2 Core specifications work well together.',
'view_name' => 'extensions.oauth2',
)
);

View File

@ -38,11 +38,13 @@ class TestSeeder extends Seeder {
$this->seedServerConfiguration();
$this->seedServerExtensions();
$current_realm = Config::get('app.url');
$components = parse_url($current_realm);
ResourceServer::create(
array(
'friendly_name' => 'test resource server',
'host' => 'dev.openstackid.com',
'host' => $components['host'],
'ip' => '127.0.0.1'
)
);
@ -281,7 +283,7 @@ class TestSeeder extends Seeder {
'namespace' => 'http://openid.net/extensions/sreg/1.1',
'active' => true,
'extension_class' => 'openid\extensions\implementations\OpenIdSREGExtension',
'description' => 'OpenID Simple Registation is an extension to the OpenID Authentication protocol that allows for very light-weight profile exchange. It is designed to pass eight commonly requested pieces of information when an End User goes to register a new account with a web service',
'description' => 'OpenID Simple Registration is an extension to the OpenID Authentication protocol that allows for very light-weight profile exchange.',
'view_name' => 'extensions.sreg',
)
);
@ -292,7 +294,7 @@ class TestSeeder extends Seeder {
'namespace' => 'http://specs.openid.net/extensions/oauth/2.0',
'active' => true,
'extension_class' => 'openid\extensions\implementations\OpenIdOAuth2Extension',
'description' => 'The OpenID OAuth2 Extension describes how to make the OpenID Authentication and OAuth2 Core specifications work well togethe',
'description' => 'The OpenID OAuth2 Extension describes how to make the OpenID Authentication and OAuth2 Core specifications work well together.',
'view_name' => 'extensions.oauth2',
)
);

View File

@ -36,8 +36,22 @@ App::before(function($request){
});
App::after(function($request, $response){
// https://www.owasp.org/index.php/List_of_useful_HTTP_headers
$response->headers->set('X-content-type-options','nosniff');
$response->headers->set('X-xss-protection','1; mode=block');
// http://tools.ietf.org/html/rfc6797
/**
* The HSTS header field below stipulates that the HSTS Policy is to
* remain in effect for one year (there are approximately 31536000
* seconds in a year)
* applies to the domain of the issuing HSTS Host and all of its
* subdomains:
*/
$response->headers->set('Strict-Transport-Security','max-age=31536000; includeSubDomains');
//cache
$response->headers->set('pragma','no-cache');
$response->headers->set('Expires','-1');
$response->headers->set('cache-control','no-store, must-revalidate, no-cache');
$cors = ServiceLocator::getInstance()->getService('CORSMiddleware');
$cors->modifyResponse($request, $response);
});
@ -207,12 +221,6 @@ Route::filter('is.current.user',function($route, $request){
Route::filter('oauth2.protected.endpoint','OAuth2BearerAccessTokenRequestValidator');
Route::filter('oauth2.rate.limiter','ApiEndpointRateLimiter');
Route::filter('oauth2.rate.limiter.headers','ApiEndpointRateLimiterHeaders');
Route::filter('oauth2.etag','ETagChecker');
//oauth2 server admin filter
Route::filter('oauth2.server.admin.json',function(){

View File

@ -1,84 +0,0 @@
<?php
/**
* Copyright 2015 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 oauth2\services\IApiEndpointService;
use utils\services\ILogService;
use utils\services\ICheckPointService;
use utils\services\ICacheService;
/**
* Class ApiEndpointRateLimiter
*/
class ApiEndpointRateLimiter {
/**
* @var IApiEndpointService
*/
private $api_endpoint_service;
/**
* @var ILogService
*/
private $log_service;
/**
* @var ICheckPointService
*/
private $checkpoint_service;
/**
* @var ICacheService
*/
private $cache_service;
/**
* @param IApiEndpointService $api_endpoint_service
* @param ILogService $log_service
* @param ICheckPointService $checkpoint_service
* @param ICacheService $cache_service
*/
public function __construct(IApiEndpointService $api_endpoint_service, ILogService $log_service, ICheckPointService $checkpoint_service, ICacheService $cache_service){
$this->api_endpoint_service = $api_endpoint_service;
$this->log_service = $log_service;
$this->checkpoint_service = $checkpoint_service;
$this->cache_service = $cache_service;
}
/**
* @param $route
* @param $request
* @return mixed
*/
public function filter($route, $request)
{
$url = $route->getPath();
if(strpos($url, '/') != 0){
$url = '/'.$url;
}
$method = $request->getMethod();
try {
$endpoint = $this->api_endpoint_service->getApiEndpointByUrlAndMethod($url, $method);
if(!is_null($endpoint->rate_limit) && (int)$endpoint->rate_limit > 0){
//do rate limit checking
$key = sprintf('rate.limit.%s_%s_%s',$url,$method,$request->getClientIp());
$res = (int)$this->cache_service->getSingleValue($key);
if($res >= (int)$endpoint->rate_limit)
return Response::json(array('message' => "You have triggered an abuse detection mechanism and have been temporarily blocked from content creation. Please retry your request again later."), 403);
$this->cache_service->incCounter($key, (3600 * 60));
}
}
catch(Exception $ex){
$this->log_service->error($ex);
$this->checkpoint_service->trackException($ex);
}
}
}

View File

@ -1,87 +0,0 @@
<?php
/**
* Copyright 2015 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 oauth2\services\IApiEndpointService;
use utils\services\ILogService;
use utils\services\ICheckPointService;
use utils\services\ICacheService;
/**
* Class ApiEndpointRateLimiterHeaders
*/
class ApiEndpointRateLimiterHeaders {
/**
* @var IApiEndpointService
*/
private $api_endpoint_service;
/**
* @var ILogService
*/
private $log_service;
/**
* @var ICheckPointService
*/
private $checkpoint_service;
/**
* @var ICacheService
*/
private $cache_service;
/**
* @param IApiEndpointService $api_endpoint_service
* @param ILogService $log_service
* @param ICheckPointService $checkpoint_service
* @param ICacheService $cache_service
*/
public function __construct(IApiEndpointService $api_endpoint_service, ILogService $log_service, ICheckPointService $checkpoint_service, ICacheService $cache_service){
$this->api_endpoint_service = $api_endpoint_service;
$this->log_service = $log_service;
$this->checkpoint_service = $checkpoint_service;
$this->cache_service = $cache_service;
}
/**
* @param $route
* @param $request
* @param $response
*/
public function filter($route, $request, $response)
{
$url = $route->getPath();
if(strpos($url, '/') != 0){
$url = '/'.$url;
}
$method = $request->getMethod();
try {
$endpoint = $this->api_endpoint_service->getApiEndpointByUrlAndMethod($url, $method);
if(!is_null($endpoint->rate_limit) && (int)$endpoint->rate_limit > 0){
//do rate limit checking
$key = sprintf('rate.limit.%s_%s_%s',$url,$method,$request->getClientIp());
$res = (int)$this->cache_service->getSingleValue($key);
if($res <= (int)$endpoint->rate_limit)
{
$response->headers->set('X-Ratelimit-Limit', $endpoint->rate_limit, false);
$response->headers->set('X-Ratelimit-Remaining', $endpoint->rate_limit-(int)$res, false);
$response->headers->set('X-RateLimit-Reset', $this->cache_service->ttl(($key)) , false);
}
}
}
catch(Exception $ex){
$this->log_service->error($ex);
$this->checkpoint_service->trackException($ex);
}
}
}

View File

@ -1,36 +0,0 @@
<?php
/**
* Copyright 2015 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 ETagChecker
*/
class ETagChecker {
/**
* @param $route
* @param $request
* @param $response
*/
public function filter($route, $request, $response)
{
if($response->getStatusCode()!= 200) return;
$etag = md5($response->getContent());
$requestETag = str_replace('"', '', $request->getETags());
if($requestETag && $requestETag[0] == $etag){
$response->setNotModified();
}
$response->setEtag($etag);
}
}

View File

@ -8,10 +8,12 @@ use oauth2\responses\OAuth2WWWAuthenticateErrorResponse;
use utils\services\ILogService;
use oauth2\exceptions\OAuth2ResourceServerException;
use oauth2\exceptions\InvalidGrantTypeException;
use oauth2\exceptions\ExpiredAccessTokenException;
use utils\services\ICheckPointService;
use oauth2\IResourceServerContext;
use oauth2\services\IClientService;
use oauth2\models\IClient;
/**
* Class OAuth2BearerAccessTokenRequestValidator
* this class implements the logic to Accessing to Protected Resources
@ -107,7 +109,8 @@ class OAuth2BearerAccessTokenRequestValidator {
// get access token from service
$access_token = $this->token_service->getAccessToken($access_token_value);
if(is_null($access_token))
throw new ExpiredAccessTokenException(sprintf('Access token %s is expired!', $access_token_value));
//check token audience
$audience = explode(' ',$access_token->getAudience());
if((!in_array($realm,$audience)))
@ -177,6 +180,19 @@ class OAuth2BearerAccessTokenRequestValidator {
$http_response->header('WWW-Authenticate',$response->getWWWAuthenticateHeaderValue());
return $http_response;
}
catch(ExpiredAccessTokenException $ex3){
$this->log_service->error($ex3);
$this->checkpoint_service->trackException($ex3);
$response = new OAuth2WWWAuthenticateErrorResponse($realm,
OAuth2Protocol::OAuth2Protocol_Error_InvalidToken,
'the access token provided is expired, revoked, malformed, or invalid for other reasons.',
null,
401
);
$http_response = Response::json($response->getContent(), $response->getHttpCode());
$http_response->header('WWW-Authenticate',$response->getWWWAuthenticateHeaderValue());
return $http_response;
}
catch(Exception $ex){
$this->log_service->error($ex);
$this->checkpoint_service->trackException($ex);

View File

@ -10,13 +10,13 @@ namespace oauth2;
interface IResourceServerContext {
/**
* returns given scopes for current requewt
* returns given scopes for current request
* @return array
*/
public function getCurrentScope();
/**
* gets current access token valaue
* gets current access token values
* @return string
*/
public function getCurrentAccessToken();

View File

@ -31,6 +31,7 @@ use oauth2\exceptions\UriNotAllowedException;
use oauth2\exceptions\MissingClientAuthorizationInfo;
use oauth2\exceptions\InvalidRedeemAuthCodeException;
use oauth2\exceptions\InvalidClientCredentials;
use oauth2\exceptions\ExpiredAccessTokenException;
//grant types
use oauth2\grant_types\AuthorizationCodeGrantType;
@ -120,7 +121,7 @@ class OAuth2Protocol implements IOAuth2Protocol
const OAuth2Protocol_Error_ServerError = 'server_error';
const OAuth2Protocol_Error_TemporallyUnavailable = 'temporally_unavailable';
//http://tools.ietf.org/html/rfc7009#section-2.2.1
const OAuth2Protocol_Error_Unsupported_TokenType = ' unsupported_token_type';
const OAuth2Protocol_Error_Unsupported_TokenType = 'unsupported_token_type';
//http://tools.ietf.org/html/rfc6750#section-3-1
const OAuth2Protocol_Error_InvalidToken = 'invalid_token';
const OAuth2Protocol_Error_InsufficientScope = 'insufficient_scope';
@ -488,6 +489,11 @@ class OAuth2Protocol implements IOAuth2Protocol
$this->checkpoint_service->trackException($ex3);
return new OAuth2DirectErrorResponse(OAuth2Protocol::OAuth2Protocol_Error_UnauthorizedClient);
}
catch(ExpiredAccessTokenException $ex4){
$this->log_service->warning($ex4);
$this->checkpoint_service->trackException($ex4);
return new OAuth2DirectErrorResponse(OAuth2Protocol::OAuth2Protocol_Error_InvalidToken);
}
catch (Exception $ex) {
$this->log_service->error($ex);
$this->checkpoint_service->trackException($ex);

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright 2015 Openstack Foundation
* Copyright 2015 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
@ -12,18 +12,21 @@
* limitations under the License.
**/
namespace models\marketplace;
namespace oauth2\exceptions;
use Exception;
/**
* Class Consultant
* @package models\marketplace
* Class ExpiredAccessTokenException
* @package oauth2\exceptions
*/
class Consultant extends CompanyService implements IConsultant {
class ExpiredAccessTokenException extends Exception
{
/**
* @return Office[]
*/
public function offices(){
return $this->hasMany('models\marketplace\Office', 'ConsultantID', 'ID')->get();
public function __construct($message = "")
{
$message = "Expired Access Token: " . $message;
parent::__construct($message, 0, null);
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace oauth2\exceptions;
use Exception;
class InvalidAllowedClientUriException extends Exception {
public function __construct($message = "")
{
$message = "Invalid Allowed Client Uri : " . $message;
parent::__construct($message, 0, null);
}
}

View File

@ -6,6 +6,7 @@ use oauth2\exceptions\InvalidOAuth2Request;
use oauth2\exceptions\UnAuthorizedClientException;
use oauth2\exceptions\BearerTokenDisclosureAttemptException;
use oauth2\exceptions\InvalidGrantTypeException;
use oauth2\exceptions\ExpiredAccessTokenException;
use oauth2\OAuth2Protocol;
use oauth2\requests\OAuth2Request;
@ -96,6 +97,10 @@ class RevokeBearerTokenGrantType extends AbstractGrantType
{
//check ownership
$access_token = $this->token_service->getAccessToken($token_value);
if(is_null($access_token))
throw new ExpiredAccessTokenException(sprintf('Access token %s is expired!', $token_value));
if ($access_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('access token %s does not belongs to client id %s',$token_value, $this->current_client_id));
@ -106,6 +111,7 @@ class RevokeBearerTokenGrantType extends AbstractGrantType
{
//check ownership
$refresh_token = $this->token_service->getRefreshToken($token_value);
if ($refresh_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('refresh token %s does not belongs to client id %s',$token_value, $this->current_client_id));
@ -125,8 +131,13 @@ class RevokeBearerTokenGrantType extends AbstractGrantType
try{
//check ownership
$access_token = $this->token_service->getAccessToken($token_value);
if(is_null($access_token))
throw new ExpiredAccessTokenException(sprintf('Access token %s is expired!', $token_value));
if ($access_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('access token %s does not belongs to client id %s',$token_value, $this->current_client_id));
$this->token_service->revokeAccessToken($token_value, false);
}
catch(UnAuthorizedClientException $ex1){

View File

@ -2,6 +2,7 @@
namespace oauth2\grant_types;
use oauth2\exceptions\ExpiredAccessTokenException;
use oauth2\exceptions\InvalidApplicationType;
use oauth2\exceptions\InvalidOAuth2Request;
use oauth2\exceptions\InvalidAccessTokenException;
@ -102,7 +103,8 @@ class ValidateBearerTokenGrantType extends AbstractGrantType
try{
$access_token = $this->token_service->getAccessToken($token_value);
if(is_null($access_token))
throw new ExpiredAccessTokenException(sprintf('Access token %s is expired!', $token_value));
if(!$this->current_client->isResourceServerClient()){
// if current client is not a resource server, then we could only access to our own tokens
if($access_token->getClientId()!== $this->current_client_id)
@ -127,16 +129,21 @@ class ValidateBearerTokenGrantType extends AbstractGrantType
}
$allowed_origins = array();
foreach($this->current_client->getClientAllowedOrigins() as $origin){
$allowed_urls = array();
$issued_client = $this->client_service->getClientById($access_token->getClientId());
if(is_null($issued_client))
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('access token %s does not belongs to client id %s',$token_value, $access_token->getClientId()));
foreach($issued_client->getClientAllowedOrigins() as $origin){
array_push($allowed_origins, $origin->allowed_origin);
}
$allowed_urls = array();
foreach($this->current_client->getClientRegisteredUris() as $url){
foreach($issued_client->getClientRegisteredUris() as $url){
array_push($allowed_urls, $url->uri);
}
return new OAuth2AccessTokenValidationResponse($token_value, $access_token->getScope(), $access_token->getAudience(), $access_token->getClientId(), $access_token->getRemainingLifetime(), $access_token->getUserId(), $allowed_urls, $allowed_origins);
return new OAuth2AccessTokenValidationResponse($token_value, $access_token->getScope(), $access_token->getAudience(), $access_token->getClientId(), $access_token->getRemainingLifetime(), $access_token->getUserId(), $issued_client->getApplicationType(), $allowed_urls, $allowed_origins);
}
catch(InvalidAccessTokenException $ex1){
$this->log_service->error($ex1);

View File

@ -6,7 +6,18 @@ use oauth2\OAuth2Protocol;
class OAuth2AccessTokenValidationResponse extends OAuth2DirectResponse {
public function __construct($access_token,$scope, $audience,$client_id,$expires_in, $user_id = null, $allowed_urls = array(), $allowed_origins = array())
/**
* @param array|int $access_token
* @param string $scope
* @param $audience
* @param $client_id
* @param $expires_in
* @param null $user_id
* @param null $application_type
* @param array $allowed_urls
* @param array $allowed_origins
*/
public function __construct($access_token,$scope, $audience, $client_id, $expires_in, $user_id = null, $application_type = null, $allowed_urls = array(), $allowed_origins = array())
{
// Successful Responses: A server receiving a valid request MUST send a
// response with an HTTP status code of 200.
@ -22,6 +33,10 @@ class OAuth2AccessTokenValidationResponse extends OAuth2DirectResponse {
$this[OAuth2Protocol::OAuth2Protocol_UserId] = $user_id;
}
if(!is_null($application_type)){
$this['application_type'] = $application_type;
}
if(count($allowed_urls)){
$this['allowed_return_uris'] = implode(' ', $allowed_urls);
}

View File

@ -1,40 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
use utils\model\BaseModelEloquent;
/**
* Class CompanyService
* @package model\marketplace
*/
class CompanyService extends BaseModelEloquent implements \IEntity{
protected $hidden = array('ClassName', 'MarketPlaceTypeID', 'EditedByID');
protected $table = 'CompanyService';
protected $connection = 'os_members';
protected $stiClassField = 'ClassName';
protected $stiBaseClass = 'models\marketplace\CompanyService';
/**
* @return int
*/
public function getIdentifier()
{
return (int)$this->ID;
}
}

View File

@ -1,36 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
use utils\model\BaseModelEloquent;
/**
* Class DataCenterLocation
* @package model\marketplace
*/
class DataCenterLocation extends BaseModelEloquent {
protected $table = 'DataCenterLocation';
protected $connection = 'os_members';
protected $hidden = array('ClassName','CloudServiceID','DataCenterRegionID');
/**
* @return DataCenterRegion
*/
public function region(){
return $this->belongsTo('models\marketplace\DataCenterRegion', 'DataCenterRegionID');
}
}

View File

@ -1,35 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
use utils\model\BaseModelEloquent;
/**
* Class DataCenterRegion
* @package model\marketplace
*/
class DataCenterRegion extends BaseModelEloquent {
protected $table = 'DataCenterRegion';
protected $connection = 'os_members';
protected $hidden = array('ClassName','CloudServiceID','PublicCloudID');
/**
* @return DataCenterLocation[]
*/
public function locations(){
return $this->hasMany('models\marketplace\DataCenterLocation','DataCenterRegionID','ID')->get();
}
}

View File

@ -1,27 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
/**
* Interface ICloudService
* @package models\marketplace
*/
interface ICloudService {
/**
* @return DataCenterRegion[]
*/
public function datacenters_regions();
}

View File

@ -1,26 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
/**
* Interface IConsultant
* @package models\marketplace
*/
interface IConsultant {
/**
* @return Office[]
*/
public function offices();
}

View File

@ -1,38 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
use utils\model\BaseModelEloquent;
/**
* Class Office
* @package models\marketplace
*/
class Office extends BaseModelEloquent {
protected $table = 'Office';
protected $connection = 'os_members';
protected $hidden = array('ClassName','Order','ConsultantID');
/**
* @return Consultant
*/
public function region(){
return $this->belongsTo('models\marketplace\Consultant', 'ConsultantID');
}
}

View File

@ -1,32 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace;
/**
* Class PrivateCloudService
* @package models\marketplace
*/
class PrivateCloudService extends CompanyService implements ICloudService
{
/**
* @return DataCenterRegion[]
*/
public function datacenters_regions()
{
return $this->hasMany('models\marketplace\DataCenterRegion', 'CloudServiceID', 'ID')->get();
}
}

View File

@ -1,29 +0,0 @@
<?php
/*
* Copyright 2015 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.
**/
namespace models\marketplace;
/**
* Class PublicCloudService
* @package model\marketplace
*/
class PublicCloudService extends CompanyService implements ICloudService {
/**
* @return DataCenterRegion[]
*/
public function datacenters_regions()
{
return $this->hasMany('models\marketplace\DataCenterRegion','CloudServiceID', 'ID')->get();
}
}

View File

@ -1,25 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace\repositories;
use models\marketplace\ICloudService;
/**
* Interface ICloudServiceRepository
* @package models\marketplace\repositories
*/
interface ICloudServiceRepository extends ICompanyServiceRepository {
}

View File

@ -1,36 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace\repositories;
use IBaseRepository;
interface ICompanyServiceRepository extends IBaseRepository {
const Status_All = 'all';
const Status_active = 'active';
const Status_non_active = 'non_active';
const Order_date = 'date';
const Order_name = 'name';
/**
* @param int $page
* @param int $per_page
* @param string $status
* @param string $order_by
* @param string $order_dir
* @return \IEntity[]
*/
public function getAll($page = 1, $per_page = 1000, $status = ICompanyServiceRepository::Status_All, $order_by = ICompanyServiceRepository::Order_date, $order_dir = 'asc');
}

View File

@ -1,22 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace\repositories;
/**
* Interface IConsultantRepository
* @package models\marketplace\repositories
*/
interface IConsultantRepository extends ICompanyServiceRepository{
}

View File

@ -1,22 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace\repositories;
/**
* Interface IPrivateCloudServiceRepository
* @package models\marketplace\repositories
*/
interface IPrivateCloudServiceRepository extends ICloudServiceRepository {
}

View File

@ -1,22 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace models\marketplace\repositories;
/**
* Interface IPublicCloudServiceRepository
* @package models\marketplace\repositories
*/
interface IPublicCloudServiceRepository extends ICloudServiceRepository {
}

View File

@ -92,4 +92,19 @@ class Api extends BaseModelEloquent implements IApi {
{
$this->active = $active;
}
public function delete ()
{
$endpoints = ApiEndpoint::where('api_id','=', $this->id)->get();
foreach($endpoints as $endpoint){
$endpoint->delete();
}
$scopes = ApiScope::where('api_id','=', $this->id)->get();
foreach($scopes as $scope){
$scope->delete();
}
return parent::delete();
}
}

View File

@ -121,16 +121,15 @@ class Client extends BaseModelEloquent implements IClient {
}
if(($parts['scheme']!=='https') && (ServerConfigurationService::getConfigValue("SSL.Enable")))
return false;
$client_authorized_uri = ClientAuthorizedUri::where('client_id', '=', $this->id)->where('uri','=',$uri)->first();
if(!is_null($client_authorized_uri)) return true;
if(isset($parts['path'])){
$aux_uri = $parts['scheme'].'://'.strtolower($parts['host']).strtolower($parts['path']);
$client_authorized_uri = ClientAuthorizedUri::where('client_id', '=', $this->id)->where('uri','=',$aux_uri)->first();
return !is_null($client_authorized_uri);
//normalize uri
$normalized_uri = $parts['scheme'].'://'.strtolower($parts['host']);
if(isset($parts['path'])) {
$normalized_uri .= strtolower($parts['path']);
}
return false;
// normalize url and remove trailing /
$normalized_uri = rtrim($normalized_uri, '/');
$client_authorized_uri = ClientAuthorizedUri::where('client_id', '=', $this->id)->where('uri','=',$normalized_uri)->first();
return !is_null($client_authorized_uri);
}
public function getApplicationName()

View File

@ -89,6 +89,6 @@ class EloquentUserRepository implements IUserRepository {
*/
public function getByToken($identifier, $token)
{
return $this->user->where('id', '=', $identifier)->where('remember_token', '=', $token)->first();
return $this->user->where('external_identifier', '=', $identifier)->where('remember_token', '=', $token)->first();
}
}

View File

@ -21,8 +21,5 @@ class RepositoriesProvider extends ServiceProvider
App::singleton('openid\repositories\IOpenIdTrustedSiteRepository', 'repositories\EloquentOpenIdTrustedSiteRepository');
App::singleton('auth\IUserRepository', 'repositories\EloquentUserRepository');
App::singleton('auth\IMemberRepository', 'repositories\EloquentMemberRepository');
App::singleton('models\marketplace\repositories\IPublicCloudServiceRepository', 'repositories\marketplace\EloquentPublicCloudServiceRepository');
App::singleton('models\marketplace\repositories\IPrivateCloudServiceRepository', 'repositories\marketplace\EloquentPrivateCloudServiceRepository');
App::singleton('models\marketplace\repositories\IConsultantRepository', 'repositories\marketplace\EloquentConsultantRepository');
}
}

View File

@ -1,96 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace repositories\marketplace;
use IEntity;
use models\marketplace\repositories\ICompanyServiceRepository;
use utils\services\ILogService;
use DB;
/**
* Class EloquentCompanyServiceRepository
* @package repositories\marketplace
*/
abstract class EloquentCompanyServiceRepository implements ICompanyServiceRepository{
/**
* @var IEntity
*/
protected $entity;
/**
* @var ILogService
*/
protected $log_service;
/**
* @param int $id
* @return IEntity
*/
public function getById($id)
{
return $this->entity->find($id);
}
/**
* @param int $page
* @param int $per_page
* @param string $status
* @param string $order_by
* @param string $order_dir
* @return \IEntity[]
*/
public function getAll($page = 1, $per_page = 1000, $status = ICompanyServiceRepository::Status_All, $order_by = ICompanyServiceRepository::Order_date, $order_dir = 'asc')
{
$fields = array('*');
$filters = array();
switch($status){
case ICompanyServiceRepository::Status_active:
array_push($filters,
array(
'name'=>'Active',
'op' => '=',
'value'=> true
)
);
break;
case ICompanyServiceRepository::Status_non_active:
array_push($filters,
array(
'name'=>'Active',
'op' => '=',
'value'=> false
)
);
break;
}
DB::getPaginator()->setCurrentPage($page);
$query = $this->entity->Filter($filters);
switch($order_by){
case ICompanyServiceRepository::Order_date:
$query = $query->orderBy('Created', $order_dir);
break;
case ICompanyServiceRepository::Order_name:
$query = $query->orderBy('Name', $order_dir);
break;
}
return $query->paginate($per_page, $fields)->toArray();
}
}

View File

@ -1,36 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace repositories\marketplace;
use models\marketplace\Consultant;
use models\marketplace\IConsultant;
use models\marketplace\repositories\IConsultantRepository;
use utils\services\ILogService;
/**
* Class EloquentConsultantRepository
* @package repositories\marketplace
*/
class EloquentConsultantRepository extends EloquentCompanyServiceRepository implements IConsultantRepository {
/**
* @param Consultant $consultant
* @param ILogService $log_service
*/
public function __construct(Consultant $consultant, ILogService $log_service){
$this->entity = $consultant;
$this->log_service = $log_service;
}
}

View File

@ -1,36 +0,0 @@
<?php
/**
* Copyright 2014 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.
**/
namespace repositories\marketplace;
use models\marketplace\PrivateCloudService;
use models\marketplace\repositories\IPrivateCloudServiceRepository;
use utils\services\ILogService;
/**
* Class EloquentPrivateCloudServiceRepository
* @package repositories\marketplace
*/
class EloquentPrivateCloudServiceRepository extends EloquentCompanyServiceRepository
implements IPrivateCloudServiceRepository {
/**
* @param PrivateCloudService $private_cloud
* @param ILogService $log_service
*/
public function __construct(PrivateCloudService $private_cloud, ILogService $log_service){
$this->entity = $private_cloud;
$this->log_service = $log_service;
}
}

View File

@ -1,41 +0,0 @@
<?php
/**
* Copyright 2015 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.
**/
namespace repositories\marketplace;
use models\marketplace\PublicCloudService;
use utils\services\ILogService;
use models\marketplace\repositories\ICloudServiceRepository;
use models\marketplace\repositories\IPublicCloudServiceRepository;
use models\marketplace\ICloudService;
use repositories\marketplace\EloquentCloudServiceRepository;
use DB;
/**
* Class EloquentPublicCloudServiceRepository
* @package repositories\marketplace
*/
class EloquentPublicCloudServiceRepository extends EloquentCompanyServiceRepository
implements IPublicCloudServiceRepository {
/**
* @param PublicCloudService $public_cloud
* @param ILogService $log_service
*/
public function __construct(PublicCloudService $public_cloud, ILogService $log_service){
$this->entity = $public_cloud;
$this->log_service = $log_service;
}
}

View File

@ -181,32 +181,10 @@ Route::group(array('prefix' => 'admin/api/v1', 'before' => 'ssl|auth'), function
//OAuth2 Protected API
Route::group(array('prefix' => 'api/v1',
'before' => 'ssl|oauth2.enabled|oauth2.rate.limiter|oauth2.cors.before|oauth2.protected.endpoint',
'after' => 'oauth2.rate.limiter.headers|oauth2.etag'), function()
'before' => 'ssl|oauth2.enabled|oauth2.protected.endpoint',
'after' => ''), function()
{
Route::group(array('prefix' => 'users'), function(){
Route::get('/me','OAuth2UserApiController@me');
});
Route::group(array('prefix' => 'marketplace'), function(){
Route::group(array('prefix' => 'public-clouds'), function(){
Route::get('','OAuth2PublicCloudApiController@getClouds');
Route::get('/{id}','OAuth2PublicCloudApiController@getCloud');
Route::get('/{id}/data-centers','OAuth2PublicCloudApiController@getCloudDataCenters');
});
Route::group(array('prefix' => 'private-clouds'), function(){
Route::get('','OAuth2PrivateCloudApiController@getClouds');
Route::get('/{id}','OAuth2PrivateCloudApiController@getCloud');
Route::get('/{id}/data-centers','OAuth2PrivateCloudApiController@getCloudDataCenters');
});
Route::group(array('prefix' => 'consultants'), function(){
Route::get('','OAuth2ConsultantsApiController@getConsultants');
Route::get('/{id}','OAuth2ConsultantsApiController@getConsultant');
Route::get('/{id}/offices','OAuth2ConsultantsApiController@getOffices');
});
});
});

View File

@ -84,7 +84,7 @@ class ApiEndpointService implements IApiEndpointService {
$this->tx_service->transaction(function () use ($name, $description, $active,$allow_cors, $route, $http_method, $api_id, $rate_limit, &$instance) {
//check that does not exists an endpoint with same http method and same route
if(ApiEndpoint::where('http_method','=',$http_method)->where('route','=',$route)->count()>0)
if(ApiEndpoint::where('http_method','=',$http_method)->where('route','=',$route)->where('api_id','=',$api_id)->count()>0)
throw new InvalidApiEndpoint(sprintf('there is already an endpoint api with route %s and http method %s',$route,$http_method));
$instance = new ApiEndpoint(
@ -127,7 +127,7 @@ class ApiEndpointService implements IApiEndpointService {
}
}
//check that does not exists an endpoint with same http method and same route
if(ApiEndpoint::where('http_method','=',$endpoint->http_method)->where('route','=',$endpoint->route)->where('id','<>',$endpoint->id)->count()>0)
if(ApiEndpoint::where('http_method', '=' , $endpoint->http_method)->where('route', '=', $endpoint->route)->where('id', '<>' ,$endpoint->id)->where('api_id','=',$endpoint->api_id)->count()>0)
throw new InvalidApiEndpoint(sprintf('there is already an endpoint api with route %s and http method %s',$endpoint->route,$endpoint->http_method));
$res = $this_var->save($endpoint);
});

View File

@ -73,7 +73,7 @@ class ApiService implements IApiService {
$this->tx_service->transaction(function () use ($name, $description, $active, $resource_server_id, &$instance) {
$count = Api::where('name','=',$name)->count();
$count = Api::where('name','=',$name)->where('resource_server_id','=',$resource_server_id)->count();
if($count>0)
throw new InvalidApi(sprintf('api name %s already exists!',$name));
@ -112,7 +112,7 @@ class ApiService implements IApiService {
if(array_key_exists($param,$params)){
if($param=='name'){
if(Api::where('name','=',$params[$param])->where('id','<>',$id)->count()>0)
if(Api::where('name','=',$params[$param])->where('id','<>',$id)->where('resource_server_id','=',$api->resource_server_id)->count()>0)
throw new InvalidApi(sprintf('api name %s already exists!',$params[$param]));
}

View File

@ -13,7 +13,7 @@ use App;
use Log;
use Exception;
use Config;
use Illuminate\Support\Facades\Cache;
/**
* Class CORSMiddleware
* @package services\oauth2
@ -25,7 +25,7 @@ class CORSMiddleware {
private $cache_service;
private $origin_service;
private $actual_request = false;
private $headers = array();
private $headers = array();
private $allowed_headers;
private $allowed_methods;
/**

View File

@ -12,6 +12,7 @@ use oauth2\exceptions\AllowedClientUriAlreadyExistsException;
use oauth2\exceptions\InvalidClientType;
use oauth2\exceptions\MissingClientAuthorizationInfo;
use oauth2\exceptions\AbsentClientException;
use oauth2\exceptions\InvalidAllowedClientUriException;
use oauth2\models\IClient;
use oauth2\OAuth2Protocol;
@ -135,9 +136,24 @@ class ClientService implements IClientService
if (is_null($client))
throw new AbsentClientException(sprintf("client id %s does not exists!",$id));
$client_uri = ClientAuthorizedUri::where('uri', '=', $uri)->where('client_id', '=', $id)->first();
if(!filter_var($uri, FILTER_VALIDATE_URL)) return false;
$parts = @parse_url($uri);
if (!$parts) {
throw new InvalidAllowedClientUriException(sprintf('uri : %s', $uri));
}
if(($parts['scheme']!=='https') && (ServerConfigurationService::getConfigValue("SSL.Enable")))
throw new InvalidAllowedClientUriException(sprintf('uri : %s', $uri));
//normalize uri
$normalized_uri = $parts['scheme'].'://'.strtolower($parts['host']);
if(isset($parts['path'])) {
$normalized_uri .= strtolower($parts['path']);
}
// normalize url and remove trailing /
$normalized_uri = rtrim($normalized_uri, '/');
$client_uri = ClientAuthorizedUri::where('uri', '=', $normalized_uri)->where('client_id', '=', $id)->first();
if (!is_null($client_uri)) {
throw new AllowedClientUriAlreadyExistsException(sprintf('uri : %s', $uri));
throw new AllowedClientUriAlreadyExistsException(sprintf('uri : %s', $normalized_uri));
}
$client_authorized_uri = new ClientAuthorizedUri;

View File

@ -1,4 +1,16 @@
<?php
/**
* Copyright 2015 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.
**/
namespace services\oauth2;
@ -9,6 +21,7 @@ use oauth2\exceptions\InvalidAccessTokenException;
use oauth2\exceptions\InvalidAuthorizationCodeException;
use oauth2\exceptions\InvalidGrantTypeException;
use oauth2\exceptions\ReplayAttackException;
use oauth2\exceptions\ExpiredAccessTokenException;
use oauth2\models\AccessToken;
use oauth2\models\IClient;
@ -35,6 +48,7 @@ use utils\services\IAuthService;
use Event;
use utils\db\ITransactionService;
/**
* Class TokenService
* Provides all Tokens related operations (create, get and revoke)
@ -42,16 +56,16 @@ use utils\db\ITransactionService;
*/
class TokenService implements ITokenService
{
const ClientAccessTokenPrefixList = '.atokens';
const ClientAuthCodePrefixList = '.acodes';
const ClientAccessTokenPrefixList = '.atokens';
const ClientAuthCodePrefixList = '.acodes';
const ClientAuthCodeQty = '.acodes.qty';
const ClientAuthCodeQtyLifetime = 86400;
const ClientAuthCodeQty = '.acodes.qty';
const ClientAuthCodeQtyLifetime = 86400;
const ClientAccessTokensQty = '.atokens.qty';
const ClientAccessTokensQty = '.atokens.qty';
const ClientAccessTokensQtyLifetime = 86400;
const ClientRefreshTokensQty = '.rtokens.qty';
const ClientRefreshTokensQty = '.rtokens.qty';
const ClientRefreshTokensQtyLifetime = 86400;
//services
@ -123,7 +137,7 @@ class TokenService implements ITokenService
'access_type' => $code->getAccessType(),
'approval_prompt' => $code->getApprovalPrompt(),
'has_previous_user_consent' => $code->getHasPreviousUserConsent()
), $code->getLifetime());
), intval($code->getLifetime()));
//stores brand new auth code hash value on a set by client id...
$this->cache_service->addMemberSet($client_id . self::ClientAuthCodePrefixList, $hashed_value);
@ -397,9 +411,7 @@ class TokenService implements ITokenService
'lifetime' => $access_token->getLifetime(),
'audience' => $access_token->getAudience(),
'from_ip' => IPHelper::getUserIp(),
'refresh_token' => $refresh_token_value,
$access_token->getLifetime()
));
'refresh_token' => $refresh_token_value), intval($access_token->getLifetime()));
}
/**
@ -437,79 +449,102 @@ class TokenService implements ITokenService
/**
* @param $value
* @param $is_hashed
* @param bool $is_hashed
* @return AccessToken
* @throws \oauth2\exceptions\InvalidAccessTokenException
* @throws \oauth2\exceptions\InvalidGrantTypeException
* @throws InvalidAccessTokenException
* @throws \Exception
*/
public function getAccessToken($value, $is_hashed = false)
{
$cache_service = $this->cache_service;
$lock_manager_service = $this->lock_manager_service;
$configuration_service = $this->configuration_service;
$this_var = $this;
//hash the given value, bc tokens values are stored hashed on DB
$hashed_value = !$is_hashed ? Hash::compute('sha256', $value):$value;
try {
if (!$this->cache_service->exists($hashed_value)) {
//check on DB...
$access_token_db = DBAccessToken::where('value', '=', $hashed_value)->first();
if (is_null($access_token_db))
throw new InvalidGrantTypeException(sprintf("Access token %s is invalid!", $value));
//lock ...
$lock_name = 'lock.get.accesstoken.' . $hashed_value;
$this->lock_manager_service->acquireLock($lock_name);
if ($access_token_db->isVoid()){
//invalid one ...
$access_token_db->delete();
throw new InvalidGrantTypeException(sprintf('Access token %s is expired!', $value));
return $this->tx_service->transaction(function () use ($this_var, $value, $is_hashed, $cache_service, $lock_manager_service, $configuration_service){
//hash the given value, bc tokens values are stored hashed on DB
$hashed_value = !$is_hashed ? Hash::compute('sha256', $value):$value;
$lock_name = '';
$access_token = null;
try {
// check cache ...
if (!$cache_service->exists($hashed_value)) {
// check on DB...
$access_token_db = DBAccessToken::where('value', '=', $hashed_value)->first();
if (is_null($access_token_db)) {
if($cache_service->exists('access.token:void:'.$hashed_value)) // check if its marked on cache as expired ...
throw new ExpiredAccessTokenException(sprintf('Access token %s is expired!', $value));
else
throw new InvalidGrantTypeException(sprintf("Access token %s is invalid!", $value));
}
// lock ...
$lock_name = 'lock.get.accesstoken.' . $hashed_value;
$lock_manager_service->acquireLock($lock_name);
if ($access_token_db->isVoid()){
// invalid one ...
// add to cache as expired ...
$cache_service->addSingleValue('access.token:void:'.$hashed_value, 'access.token:void:'.$hashed_value);
// and deleted it from db
$access_token_db->delete();
throw new ExpiredAccessTokenException(sprintf('Access token %s is expired!', $value));
}
//reload on cache
$this_var->storesDBAccessTokenOnCache($access_token_db);
//release lock
$lock_manager_service->releaseLock($lock_name);
}
$cache_values = $cache_service->getHash($hashed_value, array(
'user_id',
'client_id',
'scope',
'auth_code',
'issued',
'lifetime',
'from_ip',
'audience',
'refresh_token'
));
// reload auth code ...
$auth_code = AuthorizationCode::load(
$cache_values['auth_code'],
intval($cache_values['user_id']) == 0 ? null : intval($cache_values['user_id']),
$cache_values['client_id'],
$cache_values['scope'],
$cache_values['audience'],
null,
null,
$configuration_service->getConfigValue('OAuth2.AuthorizationCode.Lifetime'),
$cache_values['from_ip'],
$access_type = OAuth2Protocol::OAuth2Protocol_AccessType_Online,
$approval_prompt = OAuth2Protocol::OAuth2Protocol_Approval_Prompt_Auto,
$has_previous_user_consent = false,
$is_hashed = true
);
// reload access token ...
$access_token = AccessToken::load($value, $auth_code, $cache_values['issued'],$cache_values['lifetime']);
$refresh_token_value = $cache_values['refresh_token'];
if(!empty($refresh_token_value)){
$refresh_token = $this_var->getRefreshToken($refresh_token_value,true);
$access_token->setRefreshToken($refresh_token);
}
//reload on cache
$this->storesDBAccessTokenOnCache($access_token_db);
//release lock
$this->lock_manager_service->releaseLock($lock_name);
}
$cache_values = $this->cache_service->getHash($hashed_value, array(
'user_id',
'client_id',
'scope',
'auth_code',
'issued',
'lifetime',
'from_ip',
'audience',
'refresh_token'
));
// reload auth code ...
$auth_code = AuthorizationCode::load(
$cache_values['auth_code'],
intval($cache_values['user_id'])==0?null:intval($cache_values['user_id']),
$cache_values['client_id'],
$cache_values['scope'],
$cache_values['audience'],
null,
null,
$this->configuration_service->getConfigValue('OAuth2.AuthorizationCode.Lifetime'),
$cache_values['from_ip'],
$access_type = OAuth2Protocol::OAuth2Protocol_AccessType_Online,
$approval_prompt = OAuth2Protocol::OAuth2Protocol_Approval_Prompt_Auto,
$has_previous_user_consent=false,
$is_hashed = true
);
// reload access token ...
$access_token = AccessToken::load($value, $auth_code, $cache_values['issued'],$cache_values['lifetime']);
$refresh_token_value = $cache_values['refresh_token'];
if(!empty($refresh_token_value)){
$refresh_token = $this->getRefreshToken($refresh_token_value,true);
$access_token->setRefreshToken($refresh_token);
catch (UnacquiredLockException $ex1) {
throw new InvalidAccessTokenException("access token %s ", $value);
}
} catch (UnacquiredLockException $ex1) {
throw new InvalidAccessTokenException("access token %s ", $value);
}
return $access_token;
catch(ExpiredAccessTokenException $ex2){
if(!empty($lock_name))
$lock_manager_service->releaseLock($lock_name);
}
catch(\Exception $ex){
if(!empty($lock_name))
$lock_manager_service->releaseLock($lock_name);
throw $ex;
}
return $access_token;
});
}
/**

View File

@ -41,7 +41,7 @@ class UserService implements IUserService
{
try {
$repository = $this->repository;
if (!is_null($user) && $user->identifier === strval($user->external_identifier)) {
if (!is_null($user) && strval($user->identifier) === strval($user->external_identifier)) {
$this->tx_service->transaction(function () use ($proposed_username,&$user,&$repository) {
$done = false;

View File

@ -22,6 +22,6 @@ class EloquentTransactionService implements ITransactionService {
*/
public function transaction(Closure $callback)
{
DB::transaction($callback);
return DB::transaction($callback);
}
}

View File

@ -19,7 +19,6 @@ class RedisCacheService implements ICacheService {
}
public function boot(){
if(is_null($this->redis)){
$this->redis = \RedisLV4::connection();
@ -48,7 +47,7 @@ class RedisCacheService implements ICacheService {
* @return bool
*/
public function exists($key){
$res = $this->redis->exists($key);
$res = $this->redis->exists($key);
return $res>0;
}
@ -82,10 +81,12 @@ class RedisCacheService implements ICacheService {
public function incCounter($counter_name, $ttl = 0)
{
if($this->redis->setnx($counter_name,1))
$this->redis->expire($counter_name, $ttl);
if($this->redis->setnx($counter_name,1)) {
$this->redis->expire($counter_name, $ttl);
return 1;
}
else
$this->redis->incr($counter_name);
return (int)$this->redis->incr($counter_name);
}
public function incCounterIfExists($counter_name){
@ -122,7 +123,7 @@ class RedisCacheService implements ICacheService {
public function addSingleValue($key, $value, $ttl = 0){
$res = $this->redis->setnx($key , $value);
if($res>0 && $ttl>0)
if($res && $ttl>0)
$this->redis->expire($key,$ttl);
return $res;
}

View File

@ -16,6 +16,7 @@ use utils\services\UtilsServiceCatalog;
use oauth2\exceptions\InvalidOAuth2Request;
use Monolog\Logger;
use Monolog\Handler\NativeMailerHandler;
use Illuminate\Support\Facades\App;
ClassLoader::addDirectories(array(
@ -91,31 +92,37 @@ if (Config::get('database.log', false)){
App::error(function (Exception $exception, $code) {
$checkpoint_service = ServiceLocator::getInstance()->getService(UtilsServiceCatalog::CheckPointService);
Log::error($exception);
if($checkpoint_service ){
$checkpoint_service->trackException($exception);
if(!App::runningInConsole()) {
$checkpoint_service = ServiceLocator::getInstance()->getService(UtilsServiceCatalog::CheckPointService);
if ($checkpoint_service) {
$checkpoint_service->trackException($exception);
}
return View::make('404');
}
return View::make('404');
});
App::error(function (InvalidOpenIdMessageException $exception, $code) {
$checkpoint_service = ServiceLocator::getInstance()->getService(UtilsServiceCatalog::CheckPointService);
Log::error($exception);
if($checkpoint_service ){
$checkpoint_service->trackException($exception);
if(!App::runningInConsole()) {
$checkpoint_service = ServiceLocator::getInstance()->getService(UtilsServiceCatalog::CheckPointService);
if ($checkpoint_service) {
$checkpoint_service->trackException($exception);
}
return View::make('404');
}
return View::make('404');
});
App::error(function (InvalidOAuth2Request $exception, $code) {
$checkpoint_service = ServiceLocator::getInstance()->getService(UtilsServiceCatalog::CheckPointService);
Log::error($exception);
if($checkpoint_service ){
$checkpoint_service->trackException($exception);
if(!App::runningInConsole()) {
$checkpoint_service = ServiceLocator::getInstance()->getService(UtilsServiceCatalog::CheckPointService);
if ($checkpoint_service) {
$checkpoint_service->trackException($exception);
}
return View::make('404');
}
return View::make('404');
});

View File

@ -10,11 +10,15 @@ class ApiTest extends TestCase {
private $current_realm;
private $current_host;
protected function prepareForTests()
{
parent::prepareForTests();
//Route::enableFilters();
$this->current_realm = Config::get('app.url');
$parts = parse_url($this->current_realm);
$this->current_host = $parts['host'];
}
public function testGetById(){
@ -50,7 +54,7 @@ class ApiTest extends TestCase {
public function testCreate(){
$resource_server = ResourceServer::where('host','=','dev.openstackid.com')->first();
$resource_server = ResourceServer::where('host','=', $this->current_host)->first();
$data = array(
'name' => 'test-api',
@ -74,7 +78,7 @@ class ApiTest extends TestCase {
public function testDelete(){
$resource_server = ResourceServer::where('host','=','dev.openstackid.com')->first();
$resource_server = ResourceServer::where('host','=', $this->current_host)->first();
$data = array(
'name' => 'test-api',
@ -116,7 +120,7 @@ class ApiTest extends TestCase {
public function testUpdate(){
$resource_server = ResourceServer::where('host','=','dev.openstackid.com')->first();
$resource_server = ResourceServer::where('host','=',$this->current_host)->first();
$data = array(
'name' => 'test-api',
@ -173,7 +177,7 @@ class ApiTest extends TestCase {
public function testUpdateStatus(){
$resource_server = ResourceServer::where('host','=','dev.openstackid.com')->first();
$resource_server = ResourceServer::where('host','=',$this->current_host)->first();
$data = array(
'name' => 'test-api',

View File

@ -1,112 +0,0 @@
<?php
/**
* Copyright 2014 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\marketplace\repositories\ICompanyServiceRepository;
/**
* Class OAuth2ConsultantApiTest
*/
class OAuth2ConsultantApiTest extends OAuth2ProtectedApiTest {
protected function getScopes()
{
$scope = array(
sprintf('%s/consultants/read',$this->current_realm)
);
return $scope;
}
public function testGetConsultants(){
$params = array(
'page' => 1 ,
'per_page' => 10,
'status' => ICompanyServiceRepository::Status_active,
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2ConsultantsApiController@getConsultants",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$consultants = json_decode($content);
$this->assertResponseStatus(200);
}
public function testGetConsultantNotFound(){
$params = array(
'id' => 0
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2ConsultantsApiController@getConsultant",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(404);
}
public function testGetConsultantFound(){
$params = array(
'id' => 18
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2ConsultantsApiController@getConsultant",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(200);
}
public function testGetOffices(){
$params = array(
'id' => 19
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2ConsultantsApiController@getOffices",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(200);
}
}

View File

@ -1,113 +0,0 @@
<?php
/**
* Copyright 2015 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\marketplace\repositories\ICompanyServiceRepository;
/**
* Class OAuth2PrivateCloudApiTest
*/
class OAuth2PrivateCloudApiTest extends OAuth2ProtectedApiTest {
protected function getScopes()
{
$scope = array(
sprintf('%s/private-clouds/read',$this->current_realm)
);
return $scope;
}
public function testGetPrivateClouds(){
$params = array(
'page' => 1 ,
'per_page' => 10,
'status' => ICompanyServiceRepository::Status_active,
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PrivateCloudApiController@getClouds",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$clouds = json_decode($content);
$this->assertResponseStatus(200);
}
public function testGetPrivateCloudNotFound(){
$params = array(
'id' => 0
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PrivateCloudApiController@getCloud",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(404);
}
public function testGetPrivateCloudFound(){
$params = array(
'id' => 60
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PrivateCloudApiController@getCloud",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(200);
}
public function testGetDataCenterRegions(){
$params = array(
'id' => 60
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PrivateCloudApiController@getCloudDataCenters",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(200);
}
}

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright 2014 Openstack Foundation
* Copyright 2015 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
@ -11,7 +11,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use oauth2\OAuth2Protocol;
use auth\User;
use utils\services\IAuthService;

View File

@ -3,7 +3,19 @@
use auth\User;
use oauth2\OAuth2Protocol;
use utils\services\IAuthService;
use utils\services\UtilsServiceCatalog;
use Illuminate\Support\Facades\App;
use services\utils\ServerConfigurationService;
class StubServerConfigurationService extends ServerConfigurationService {
public function getConfigValue($value){
if($value === 'OAuth2.AccessToken.Lifetime' && isset( $_ENV['access.token.lifetime'])){
return intval($_ENV['access.token.lifetime']);
}
return parent::getConfigValue($value);
}
}
/**
* Class OAuth2ProtocolTest
* Test Suite for OAuth2 Protocol
@ -16,6 +28,7 @@ class OAuth2ProtocolTest extends OpenStackIDBaseTest
protected function prepareForTests()
{
parent::prepareForTests();
App::singleton(UtilsServiceCatalog::ServerConfigurationService, 'StubServerConfigurationService');
//Route::enableFilters();
$this->current_realm = Config::get('app.url');
$user = User::where('identifier','=','sebastian.marcet')->first();
@ -211,6 +224,112 @@ class OAuth2ProtocolTest extends OpenStackIDBaseTest
}
}
/** test validate token grant
* @throws Exception
*/
public function testValidateExpiredToken()
{
try {
// set token lifetime
$_ENV['access.token.lifetime'] = 1;
$client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwTlfSyQ3x.openstack.client';
$client_secret = 'ITc/6Y5N7kOtGKhg';
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowOnce);
//do authorization ...
$params = array(
'client_id' => $client_id,
'redirect_uri' => 'https://www.test.com/oauth2',
'response_type' => OAuth2Protocol::OAuth2Protocol_ResponseType_Code,
OAuth2Protocol::OAuth2Protocol_AccessType =>OAuth2Protocol::OAuth2Protocol_AccessType_Offline,
'scope' => sprintf('%s/resource-server/read', $this->current_realm),
);
$response = $this->action("POST", "OAuth2ProviderController@authorize",
$params,
array(),
array(),
array());
$status = $response->getStatusCode();
$url = $response->getTargetUrl();
$content = $response->getContent();
// get auth code ...
$comps = @parse_url($url);
$query = $comps['query'];
$output = array();
parse_str($query, $output);
//do get auth token...
$params = array(
'code' => $output['code'],
'redirect_uri' => 'https://www.test.com/oauth2',
'grant_type' => OAuth2Protocol::OAuth2Protocol_GrantType_AuthCode,
);
$response = $this->action("POST", "OAuth2ProviderController@token",
$params,
array(),
array(),
// Symfony interally prefixes headers with "HTTP", so
array("HTTP_Authorization" => " Basic " . base64_encode($client_id . ':' . $client_secret)));
$this->assertResponseStatus(200);
$content = $response->getContent();
$response = json_decode($content);
//get access token and refresh token...
$access_token = $response->access_token;
$refresh_token = $response->refresh_token;
$this->assertTrue(!empty($access_token));
$this->assertTrue(!empty($refresh_token));
sleep(2);
//do token validation ....
$params = array(
'token' => $access_token,
);
$response = $this->action("POST", "OAuth2ProviderController@introspection",
$params,
array(),
array(),
// Symfony interally prefixes headers with "HTTP", so
array("HTTP_Authorization" => " Basic " . base64_encode($client_id . ':' . $client_secret)));
$this->assertResponseStatus(400);
$content = $response->getContent();
$response = json_decode($content);
$response = $this->action("POST", "OAuth2ProviderController@introspection",
$params,
array(),
array(),
// Symfony interally prefixes headers with "HTTP", so
array("HTTP_Authorization" => " Basic " . base64_encode($client_id . ':' . $client_secret)));
$this->assertResponseStatus(400);
$content = $response->getContent();
$response = json_decode($content);
} catch (Exception $ex) {
throw $ex;
}
}
/** test refresh token grant
* @throws Exception
*/

View File

@ -1,113 +0,0 @@
<?php
/**
* Copyright 2015 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\marketplace\repositories\ICompanyServiceRepository;
/**
* Class OAuth2PublicCloudApiTest
*/
class OAuth2PublicCloudApiTest extends OAuth2ProtectedApiTest {
public function testGetPublicClouds(){
$params = array(
'page' => 1 ,
'per_page' => 10,
'status' => ICompanyServiceRepository::Status_active,
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PublicCloudApiController@getClouds",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$clouds = json_decode($content);
$this->assertResponseStatus(200);
}
public function testGetPublicCloudNotFound(){
$params = array(
'id' => 0
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PublicCloudApiController@getCloud",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(404);
}
public function testGetPublicCloudFound(){
$params = array(
'id' => 17
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PublicCloudApiController@getCloud",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(200);
}
public function testGetDataCenterRegions(){
$params = array(
'id' => 53
);
$headers = array("HTTP_Authorization" => " Bearer " .$this->access_token);
$response = $this->action("GET", "OAuth2PublicCloudApiController@getCloudDataCenters",
$params,
array(),
array(),
$headers);
$content = $response->getContent();
$res = json_decode($content);
$this->assertResponseStatus(200);
}
protected function getScopes()
{
$scope = array(
sprintf('%s/public-clouds/read',$this->current_realm)
);
return $scope;
}
}

View File

@ -24,7 +24,7 @@ class OAuth2UserServiceApiTest extends OAuth2ProtectedApiTest {
}
public function testGetInfoCORS(){
$response = $this->action("OPTION", "OAuth2UserApiController@me",
$response = $this->action("OPTIONS", "OAuth2UserApiController@me",
array(),
array(),
array(),

View File

@ -19,26 +19,40 @@ abstract class OpenStackIDBaseTest extends TestCase {
protected function prepareForTests()
{
DB::table('banned_ips')->delete();
DB::table('user_exceptions_trail')->delete();
DB::table('server_configuration')->delete();
DB::table('server_extensions')->delete();
DB::table('oauth2_client_api_scope')->delete();
DB::table('oauth2_client_authorized_uri')->delete();
DB::table('oauth2_access_token')->delete();
DB::table('oauth2_refresh_token')->delete();
DB::table('oauth2_client')->delete();
DB::table('openid_trusted_sites')->delete();
DB::table('openid_associations')->delete();
DB::table('openid_users')->delete();
DB::table('oauth2_api_endpoint_api_scope')->delete();
DB::table('oauth2_api_endpoint')->delete();
DB::table('oauth2_api_scope')->delete();
DB::table('oauth2_api')->delete();
DB::table('oauth2_resource_server')->delete();
if (Schema::hasTable('banned_ips'))
DB::table('banned_ips')->delete();
if (Schema::hasTable('user_exceptions_trail'))
DB::table('user_exceptions_trail')->delete();
if (Schema::hasTable('server_configuration'))
DB::table('server_configuration')->delete();
if (Schema::hasTable('server_extensions'))
DB::table('server_extensions')->delete();
if (Schema::hasTable('oauth2_client_api_scope'))
DB::table('oauth2_client_api_scope')->delete();
if (Schema::hasTable('oauth2_client_authorized_uri'))
DB::table('oauth2_client_authorized_uri')->delete();
if (Schema::hasTable('oauth2_access_token'))
DB::table('oauth2_access_token')->delete();
if (Schema::hasTable('oauth2_refresh_token'))
DB::table('oauth2_refresh_token')->delete();
if (Schema::hasTable('oauth2_client'))
DB::table('oauth2_client')->delete();
if (Schema::hasTable('openid_trusted_sites'))
DB::table('openid_trusted_sites')->delete();
if (Schema::hasTable('openid_associations'))
DB::table('openid_associations')->delete();
if (Schema::hasTable('openid_users'))
DB::table('openid_users')->delete();
if (Schema::hasTable('oauth2_api_endpoint_api_scope'))
DB::table('oauth2_api_endpoint_api_scope')->delete();
if (Schema::hasTable('oauth2_api_endpoint'))
DB::table('oauth2_api_endpoint')->delete();
if (Schema::hasTable('oauth2_api_scope'))
DB::table('oauth2_api_scope')->delete();
if (Schema::hasTable('oauth2_api'))
DB::table('oauth2_api')->delete();
if (Schema::hasTable('oauth2_resource_server'))
DB::table('oauth2_resource_server')->delete();
parent::prepareForTests();
}

View File

@ -9,16 +9,20 @@ class ResourceServerApiTest extends TestCase {
private $current_realm;
private $current_host;
protected function prepareForTests()
{
parent::prepareForTests();
//Route::enableFilters();
$this->current_realm = Config::get('app.url');
$parts = parse_url($this->current_realm);
$this->current_host = $parts['host'];
}
public function testGetById(){
$resource_server = ResourceServer::where('host','=','dev.openstackid.com')->first();
$resource_server = ResourceServer::where('host','=', $this->current_host)->first();
$response = $this->action("GET", "ApiResourceServerController@get",
$parameters = array('id' => $resource_server->id),
@ -169,7 +173,7 @@ class ResourceServerApiTest extends TestCase {
public function testDeleteExistingOne(){
$resource_server = ResourceServer::where('host','=','dev.openstackid.com')->first();
$resource_server = ResourceServer::where('host','=', $this->current_host)->first();
$new_id = $resource_server->id;

View File

@ -283,6 +283,10 @@
deactivate: '{{ URL::action("ApiEndpointController@deactivate",array("id"=>"@id")) }}',
add : '{{ URL::action("ApiEndpointController@create") }}'
};
var editApiMessages = {
success: '{{ Lang::get("messages.global_successfully_save_entity", array("entity" => "API")) }}'
};
</script>
{{ HTML::script('js/oauth2/profile/admin/edit-api.js') }}
@stop

View File

@ -57,12 +57,4 @@ Developer docs
:maxdepth: 2
openid
oauth2
Client API Reference
--------------------
.. toctree::
:maxdepth: 1
restapi/v1
oauth2

View File

@ -456,7 +456,15 @@ Below is a table of the fields included in the non-error case:
| userid | This field is only present if a resource owner (end-user) had approved access on the consent screen. |
| | |
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
| application_type | identifies the client type. (WEB_APPLICATION, JS_CLIENT OR SERVICE ) |
| | |
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
| allowed_return_uris | identifies the allowed return uris set for this client. |
| | |
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
| allowed_origins | This field is only present if application_type == JS_CLIENT. |
| | identifies the allowed origin uris set for this client. |
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
A response from such a request is shown below::
@ -467,9 +475,11 @@ A response from such a request is shown below::
"expires_in":3600,
"token_type":"Bearer",
"scope":"profile email",
"audience": "resource.server1.com"
"user_id": 123456
"audience": "resource.server1.com",
"user_id": 123456,
"application_type": "WEB_APPLICATION",
"allowed_return_uris": "www.test.com",
"allowed_origins": "www.test1.com",
}
Using OAuth 2.0 for Client-side Applications
@ -526,6 +536,40 @@ Be sure that OpenStackID Endpoint API that your application wants to access
it's been `CORS <http://www.w3.org/TR/cors/>`_ enabled
User API
--------
Allows to get additional info about current user (Me)
.. http:get:: api/v1/users/me
Gets additional information about the current user
**Example request**:
.. sourcecode:: http
GET /api/v1/users/me HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
{
"name":"Sebastian",
"family_name":"Marcet",
"nickname":"Sebastian Marcet",
"picture":"http:\/\/www.openstack.org\/assets\/profile-images\/IMG-20140912-WA0003.jpg",
"birthdate":"",
"gender":"Male",
"email":"sebastian@tipit.net"
}
Using OAuth 2.0 for Server to Server Applications
-------------------------------------------------

View File

@ -1,594 +0,0 @@
==================
OAuth 2.0 Rest API
==================
Schema
^^^^^^
All API access is over HTTPS, and accessed from the **https://openstackid.org/**
domain. All data is sent and received as JSON.
Parameters
^^^^^^^^^^
Many API methods take optional parameters. For GET requests, any parameters not
specified as a segment in the path can be passed as an HTTP query string
Pagination
^^^^^^^^^^
Requests that return multiple items will be paginated to 10 items by default.
You can specify further pages with the **?page** parameter. For some
resources, you can also set a custom page size up to 100 with the **?per_page**
parameter.
Rate Limiting
^^^^^^^^^^^^^
This is configured per API endpoint.
You can check the returned HTTP headers of any API request to see your current
rate limit status::
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 56
X-RateLimit-Reset: 1372700873
The headers tell you everything you need to know about your current rate limit
status :
======================= ==============================================================================
Header Name Description
======================= ==============================================================================
X-RateLimit-Limit The maximum number of requests that the consumer is permitted to make per hour.
X-RateLimit-Remaining The number of requests remaining in the current rate limit window.
X-RateLimit-Reset The number of seconds remaining until the current rate limit window resets.
======================= ==============================================================================
If your application triggers this rate limit, you'll receive an informative
response:
**Example response**:
.. sourcecode:: http
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
Connection: close
{
"message": "You have triggered an abuse detection mechanism and have been
temporarily blocked from content creation. Please retry your request again
later."
}
Conditional requests
^^^^^^^^^^^^^^^^^^^^
Most responses return an **ETag** header. You can use the values
of this headers to make subsequent requests to those resources using the
**If-None-Match** header, respectively. If the resource
has not changed, the server will return a **304 Not Modified**.
Cross Origin Resource Sharing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The API supports Cross Origin Resource Sharing (CORS) for AJAX requests from
any origin.
You can read the [CORS W3C Recommendation](http://www.w3.org/TR/cors), or
[this intro]
(http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity) from
the HTML 5 Security Guide.
JSON-P Callbacks
^^^^^^^^^^^^^^^^
You can send a **?callback** parameter to any GET call to have the results
wrapped in a JSON function. This is typically used when browsers want to
embed OpenStack content in web pages by getting around cross domain issues.
The response includes the same data output as the regular API, plus the
relevant HTTP Header information.
User API
^^^^^^^^
Allows to get additional info about current user (Me)
.. http:get:: api/v1/users/me
Gets additional information about the current user
**Example request**:
.. sourcecode:: http
GET /api/v1/users/me HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
{
"name":"Sebastian",
"family_name":"Marcet",
"nickname":"Sebastian Marcet",
"picture":"http:\/\/www.openstack.org\/assets\/profile-images\/IMG-20140912-WA0003.jpg",
"birthdate":"",
"gender":"Male",
"email":"sebastian@tipit.net"
}
MarketPlace API
^^^^^^^^^^^^^^^
Public Clouds Endpoints
-----------------------
Allows to get read only access to public clouds related data ( clouds and data
centers locations)
.. http:get:: /api/v1/marketplace/public-clouds
Get a list of public clouds
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/public-clouds HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/javascript
{
"total":20,
"per_page":10,
"current_page":1,
"last_page":2,
"from":1,
"to":10,
"data":[
{
"ID":"YYYY",
"Created":"2014-04-23 05:36:10",
"LastEdited":"2015-02-04 11:13:58",
"Name":"Next-Generation AgileCLOUD",
"Slug":"next-generation-agilecloud",
"Overview":"....",
"Call2ActionUri":"http:\/\/....",
"Active":"1",
"CompanyID":"XXX"
}
,{...}
]
}
:query page: used in conjunction with "per_page" query string parameter.
indicates the desired page number, when we want paginate
over results
:query per_page: used in conjunction with "page" query string parameter.
indicates the desired page size
:query status: (optional filter) allow us to get active, non active or all
public clouds
:query order_by: (optional) used in conjunction with query string parameter
"order_dir", point out the desired order of the result (date or name)
:query order_dir: (optional) used in conjunction with query string parameter
"order", point out the desired order direction of the result (asc or desc)
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 412: invalid parameters
:statuscode 500: server error
.. http:get:: api/v1/marketplace/public-clouds/(int:id)
Get desired public cloud point out by `id` param
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/public-clouds/123456 HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"ID":"123456",
"Created":"2014-04-23 05:36:10",
"LastEdited":"2015-02-04 11:13:58",
"Name":"test public cloud",
"Slug":"test-public-cloud",
"Overview":"lorep ip sum",
"Call2ActionUri":"http:\/\/.../",
"Active":"1",
"CompanyID":"123456"
}
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 404: entity not found
:statuscode 500: server error
.. http:get:: /api/v1/marketplace/public-clouds/(int:id)/data-centers
Get data center locations for public cloud pointed out by `id` param
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/public-clouds/123456/data-centers HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{"datacenters":[
{
"ID":"72",
"Created":"2014-05-07 15:19:39",
"LastEdited":"2014-05-07 15:19:39",
"Name":"West",
"Endpoint":"https:\/\/identity.uswest1.cloud.io.com\/v2.0",
"Color":"000000",
"locations":[
{
"ID":"109",
"Created":"2014-05-07 15:19:39",
"LastEdited":"2014-05-07 15:19:39",
"City":"Phoenix",
"State":"AZ",
"Country":"US",
"Lat":"33.45",
"Lng":"-112.07"
}
]
},...
]
}
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 404: entity not found (cloud)
:statuscode 500: server error
Private Clouds Endpoints
------------------------
Allows to get read only access to private clouds related data ( clouds and data
centers locations)
.. http:get:: /api/v1/marketplace/private-clouds
Get a list of private clouds
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/private-clouds HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/javascript
{
"total":20,
"per_page":10,
"current_page":1,
"last_page":2,
"from":1,
"to":10,
"data":[
{
"ID":"YYYY",
"Created":"2014-04-23 05:36:10",
"LastEdited":"2015-02-04 11:13:58",
"Name":"test private cloud",
"Slug":"test-private-cloud",
"Overview":"....",
"Call2ActionUri":"http:\/\/....",
"Active":"1",
"CompanyID":"XXX"
}
,{...}
]
}
:query page: used in conjunction with "per_page" query string parameter.
indicates the desired page number, when we want paginate
over results
:query per_page: used in conjunction with "page" query string parameter.
indicates the desired page size
:query status: (optional filter) allow us to get active, non active or all
public clouds
:query order_by: (optional) used in conjunction with query string parameter
"order_dir", point out the desired order of the result (date or name)
:query order_dir: (optional) used in conjunction with query string parameter
"order", point out the desired order direction of the result (asc or desc)
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 412: invalid parameters
:statuscode 500: server error
.. http:get:: /api/v1/marketplace/private-clouds/(int:id)
Get desired private cloud point out by `id` param
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/private-clouds/123456 HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"ID":"123456",
"Created":"2014-04-23 05:36:10",
"LastEdited":"2015-02-04 11:13:58",
"Name":"test private cloud",
"Slug":"test-private-cloud",
"Overview":"lorep ip sum",
"Call2ActionUri":"http:\/\/..",
"Active":"1",
"CompanyID":"123456"
}
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 404: entity not found
:statuscode 500: server error
.. http:get:: /api/v1/marketplace/private-clouds/(int:id)/data-centers
Get data center locations for private cloud pointed out by `id` param
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/private-clouds/123456/data-centers HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{"datacenters":[
{
"ID":"72",
"Created":"2014-05-07 15:19:39",
"LastEdited":"2014-05-07 15:19:39",
"Name":"West",
"Endpoint":"https:\/\/identity.uswest1.cloud.io.com\/v2.0",
"Color":"000000",
"locations":[
{
"ID":"109",
"Created":"2014-05-07 15:19:39",
"LastEdited":"2014-05-07 15:19:39",
"City":"Phoenix",
"State":"AZ",
"Country":"US",
"Lat":"33.45",
"Lng":"-112.07"
}
]
},...
]
}
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 404: entity not found (cloud)
:statuscode 500: server error
Consultants Endpoints
---------------------
Allows to get read only access to consultants related data ( consultants and
offices locations)
.. http:get:: /api/v1/marketplace/consultants
Get a list of consultants
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/consultants HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/javascript
{
"total":20,
"per_page":10,
"current_page":1,
"last_page":2,
"from":1,
"to":10,
"data":[
{
"ID":"YYYY",
"Created":"2014-04-23 05:36:10",
"LastEdited":"2015-02-04 11:13:58",
"Name":"Consultant Name",
"Slug":"consultant-name",
"Overview":"....",
"Call2ActionUri":"http:\/\/....",
"Active":"1",
"CompanyID":"XXX"
}
,{...}
]
}
:query page: used in conjunction with "per_page" query string parameter.
indicates the desired page number, when we want paginate
over results
:query per_page: used in conjunction with "page" query string parameter.
indicates the desired page size
:query status: (optional filter) allow us to get active, non active or all
public clouds
:query order_by: (optional) used in conjunction with query string parameter
"order_dir", point out the desired order of the result (date or name)
:query order_dir: (optional) used in conjunction with query string parameter
"order", point out the desired order direction of the result (asc or desc)
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 412: invalid parameters
:statuscode 500: server error
.. http:get:: /api/v1/marketplace/consultants/(int:id)
Get desired consultant point out by `id` param
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/consultants/123456 HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"ID":"123456",
"Created":"2014-04-23 05:36:10",
"LastEdited":"2015-02-04 11:13:58",
"Name":"Consultant Name",
"Slug":"consultant_name",
"Overview":"lorep ip sum",
"Call2ActionUri":"http:\/\/...",
"Active":"1",
"CompanyID":"123456"
}
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 404: entity not found
:statuscode 500: server error
.. http:get:: /api/v1/marketplace/consultants/(int:id)/offices
Get offices locations for consultant pointed out by `id` param
**Example request**:
.. sourcecode:: http
GET /api/v1/marketplace/consultants/123456/offices HTTP/1.1
Host: openstackid.org
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"offices":[
{
"ID":"45",
"Created":"2014-04-29 16:02:50",
"LastEdited":"2014-04-29 16:02:50",
"Address":null,
"Address2":null,
"State":"CA",
"ZipCode":null,
"City":"Mountain View",
"Country":"US",
"Lat":"37.39",
"Lng":"-122.08"
},...
]
}
:reqheader Authorization: OAuth 2.0 Bearer Access Token
:statuscode 200: no error
:statuscode 404: entity not found (consultant)
:statuscode 500: server error

View File

@ -171,7 +171,7 @@ $(document).ready(function() {
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
displaySuccessMessage('{{ Lang::get("messages.global_successfully_save_entity", array("entity" => "API")) }}',api_form);
displaySuccessMessage(editApiMessages.success,api_form);
},
error: function (jqXHR, textStatus, errorThrown) {
ajaxError(jqXHR, textStatus, errorThrown);

View File

@ -2,7 +2,8 @@
## Prerequisites
* LAMP environment
* LAMP/LEMP environment
* Redis
* PHP >= 5.4.0
* composer (https://getcomposer.org/)
@ -15,4 +16,8 @@ run following commands on root folder
* php artisan migrate --env=YOUR_ENVIRONMENT
* php artisan db:seed --env=YOUR_ENVIRONMENT
* phpunit --bootstrap vendor/autoload.php
* give proper rights to app/storage folder (775 and proper users)
## Permissions
Laravel may require some permissions to be configured: folders within storage and vendor require write access by the web server.