Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
bobicloudvision committed Apr 22, 2024
1 parent 9de70cb commit 6fa04fd
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 15 deletions.
11 changes: 4 additions & 7 deletions web/app/Http/Controllers/Api/HostingSubscriptionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Api\Request\HostingSubscriptionCreateRequest;
use App\Http\Controllers\ApiController;
use App\Models\Domain;
use App\Models\HostingSubscription;
Expand All @@ -24,21 +25,17 @@ public function index()

}

public function store(Request $request)
public function store(HostingSubscriptionCreateRequest $request)
{
$request->validate([
'customer_id' => 'required',
'hosting_plan_id' => 'required',
'domain' => 'required',
]);

$hostingSubscription = new HostingSubscription();
$hostingSubscription->customer_id = $request->customer_id;
$hostingSubscription->hosting_plan_id = $request->hosting_plan_id;
$hostingSubscription->domain = $request->domain;

// $hostingSubscription->username = $request->username;
// $hostingSubscription->password = $request->password;
// $hostingSubscription->description = $request->description;

$hostingSubscription->setup_date = Carbon::now();
$hostingSubscription->save();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class CustomerCreateRequest extends AuthorizedApiRequest
public function rules()
{
return [
'name' => 'required',
'name' => 'required|max:255',
'email' => 'required|email|unique:customers,email',
];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Http\Controllers\Api\Request;

class HostingSubscriptionCreateRequest extends AuthorizedApiRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'customer_id' => 'required|exists:customers,id',
'hosting_plan_id' => 'required|exists:hosting_plans,id',
'domain' => 'required|regex:/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i',
];
}
}
2 changes: 1 addition & 1 deletion web/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"zircote/swagger-php": "^4.8"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
"fakerphp/faker": "^1.23",
"laravel/dusk": "^8.2",
"laravel/pint": "^1.15",
"laravel/sail": "^1.18",
Expand Down
12 changes: 6 additions & 6 deletions web/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

123 changes: 123 additions & 0 deletions web/tests/Unit/SecurityTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

namespace tests\Unit;

use Faker\Factory;
use Tests\Feature\Api\ActionTestCase;

class SecurityTest extends ActionTestCase
{
public function testSecurity()
{
$callHostingSubscriptionStoreResponse = $this->callApiAuthorizedRouteAction(
'api.hosting-subscriptions.store',
[
'customer_id' => '34232432',
'hosting_plan_id'=> '4443232',
'domain' => 'broken-domain-name',
]
)->json();

$this->assertArrayHasKey('error', $callHostingSubscriptionStoreResponse);
$this->assertArrayHasKey('message', $callHostingSubscriptionStoreResponse);
$this->assertArrayHasKey('data', $callHostingSubscriptionStoreResponse);
$this->assertArrayHasKey('domain', $callHostingSubscriptionStoreResponse['data']);
$this->assertSame('The selected customer id is invalid.', $callHostingSubscriptionStoreResponse['message']);

$this->assertSame('The selected hosting plan id is invalid.', $callHostingSubscriptionStoreResponse['data']['hosting_plan_id'][0]);
$this->assertSame('The domain field format is invalid.', $callHostingSubscriptionStoreResponse['data']['domain'][0]);


// Create a customer
$faker = Factory::create();
$randomName = $faker->firstName() . ' ' . $faker->lastName();
$randomEmail = $faker->email();
$callCustomerStoreResponse = $this->callApiAuthorizedRouteAction(
'api.customers.store',
[
'name' => $randomName,
'email' => $randomEmail,
]
)->json();
$this->assertArrayHasKey('status', $callCustomerStoreResponse);
$this->assertTrue($callCustomerStoreResponse['status'] == 'ok');

$this->assertArrayHasKey('message', $callCustomerStoreResponse);
$this->assertArrayHasKey('data', $callCustomerStoreResponse);
$this->assertArrayHasKey('customer', $callCustomerStoreResponse['data']);
$this->assertArrayHasKey('id', $callCustomerStoreResponse['data']['customer']);
$this->assertIsInt($callCustomerStoreResponse['data']['customer']['id']);
$customerId = $callCustomerStoreResponse['data']['customer']['id'];

// Create a hosting subscription
$randId = rand(1000, 9999);
$callHostingPlansResponse = $this->callApiAuthorizedRouteAction('api.hosting-plans.index')->json();
$this->assertArrayHasKey('status', $callHostingPlansResponse);
$this->assertTrue($callHostingPlansResponse['status'] == 'ok');
$this->assertArrayHasKey('data', $callHostingPlansResponse);
$this->assertArrayHasKey('hostingPlans', $callHostingPlansResponse['data']);
$this->assertIsArray($callHostingPlansResponse['data']['hostingPlans']);
$this->assertNotEmpty($callHostingPlansResponse['data']['hostingPlans']);
$hostingPlanId = $callHostingPlansResponse['data']['hostingPlans'][0]['id'];
$this->assertIsInt($hostingPlanId);

$hostingSubscriptionDomain = 'phyre-unit-test-'.$randId.'.com';
$callHostingSubscriptionStoreResponse = $this->callApiAuthorizedRouteAction(
'api.hosting-subscriptions.store',
[
'customer_id' => $customerId,
'hosting_plan_id'=> $hostingPlanId,
'domain' => $hostingSubscriptionDomain,
]
)->json();

$this->assertArrayHasKey('status', $callHostingSubscriptionStoreResponse);
$this->assertTrue($callHostingSubscriptionStoreResponse['status'] == 'ok');

$hostingSubscription = $callHostingSubscriptionStoreResponse['data']['hostingSubscription'];

// Check user home dir permissions
$userHomeDir = '/home/' . $hostingSubscription['system_username'];
$this->assertDirectoryExists($userHomeDir);
$getUserHomeDirPermission = substr(sprintf('%o', fileperms($userHomeDir)), -4);
$this->assertSame('0775', $getUserHomeDirPermission);

// Check domain dir permissions
$domainDir = '/home/' . $hostingSubscription['system_username'] . '/public_html';
$this->assertDirectoryExists($domainDir);
$getDomainDirPermission = substr(sprintf('%o', fileperms($domainDir)), -4);
$this->assertSame('0775', $getDomainDirPermission);

// Check domain dir file permissions
$domainDirFile = '/home/' . $hostingSubscription['system_username'] . '/public_html/index.php';
$this->assertFileExists($domainDirFile);
$getDomainDirFilePermission = substr(sprintf('%o', fileperms($domainDirFile)), -4);
$this->assertSame('0775', $getDomainDirFilePermission);

// Create second hosting subscription
$randId = rand(1000, 9999);
$callHostingSubscriptionStoreResponse = $this->callApiAuthorizedRouteAction(
'api.hosting-subscriptions.store',
[
'customer_id' => $customerId,
'hosting_plan_id'=> $hostingPlanId,
'domain' => 'phyre-unit-test-'.$randId.'.com',
]
)->json();
$this->assertArrayHasKey('status', $callHostingSubscriptionStoreResponse);
$this->assertTrue($callHostingSubscriptionStoreResponse['status'] == 'ok');
$secondHostingSubscription = $callHostingSubscriptionStoreResponse['data']['hostingSubscription'];

// Try to open /home directory with linux user
$output = shell_exec("sudo -H -u ".$hostingSubscription['system_username']." bash -c 'ls -la /home'");
$this->assertSame($output, null);

// Try to open /home/$user with linux user
$output = shell_exec("sudo -H -u ".$hostingSubscription['system_username']." bash -c 'ls -la /home/".$hostingSubscription['system_username']."'");
$this->assertTrue(str_contains($output, 'public_html'));
$this->assertTrue(str_contains($output, $hostingSubscription['system_username']));



}
}

0 comments on commit 6fa04fd

Please sign in to comment.