mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-01 14:06:15 +00:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
fd2244d382 | |||
551f1ce40e | |||
1ce92d9361 | |||
ec6e55e30c | |||
4cda14f4b8 | |||
5e6d338bdc | |||
7312e3f515 | |||
b771db882b | |||
94977797cc | |||
c45872df55 | |||
16fae5334c | |||
7b8deddeca | |||
1bf3c94358 | |||
700cc5f44c | |||
9d13cc0756 | |||
f51d7900f0 | |||
4bd4b34d24 | |||
7c5505be16 | |||
7249cf9ed6 | |||
8282d39722 | |||
38e23a1ceb | |||
1e1204fe40 | |||
7d98986f52 | |||
2c81e324f6 | |||
422da431ec | |||
6c27215ea1 | |||
fb840204ad | |||
e07e197dd9 | |||
3a2dba4ad3 | |||
b990f9ce32 | |||
a6727ff459 | |||
170535760f | |||
648529c3bd | |||
84192b7cb7 |
38
.env.example
38
.env.example
@ -2,7 +2,7 @@ APP_NAME=Vito
|
|||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost:2080
|
APP_URL=http://vito.test
|
||||||
|
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
@ -15,14 +15,12 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
|
|
||||||
BROADCAST_DRIVER=null
|
BROADCAST_DRIVER=null
|
||||||
CACHE_DRIVER=redis
|
CACHE_DRIVER=file
|
||||||
FILESYSTEM_DRIVER=local
|
FILESYSTEM_DRIVER=local
|
||||||
QUEUE_CONNECTION=sync
|
QUEUE_CONNECTION=default
|
||||||
SESSION_DRIVER=database
|
SESSION_DRIVER=database
|
||||||
SESSION_LIFETIME=120
|
SESSION_LIFETIME=120
|
||||||
|
|
||||||
MEMCACHED_HOST=127.0.0.1
|
|
||||||
|
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=127.0.0.1
|
||||||
REDIS_PASSWORD=null
|
REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
@ -36,31 +34,5 @@ MAIL_ENCRYPTION=null
|
|||||||
MAIL_FROM_ADDRESS=null
|
MAIL_FROM_ADDRESS=null
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID=
|
SSH_PUBLIC_KEY_NAME=ssh-public.key
|
||||||
AWS_SECRET_ACCESS_KEY=
|
SSH_PRIVATE_KEY_NAME=ssh-private.pem
|
||||||
AWS_DEFAULT_REGION=us-east-1
|
|
||||||
AWS_BUCKET=
|
|
||||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
|
||||||
|
|
||||||
PUSHER_APP_ID=
|
|
||||||
PUSHER_APP_KEY=
|
|
||||||
PUSHER_APP_SECRET=
|
|
||||||
PUSHER_APP_CLUSTER=mt1
|
|
||||||
|
|
||||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
|
||||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
|
||||||
|
|
||||||
FORWARD_REDIS_PORT=2060
|
|
||||||
FORWARD_DB_PORT=2070
|
|
||||||
APP_PORT=2080
|
|
||||||
HMR_PORT=2090
|
|
||||||
|
|
||||||
SENTRY_LARAVEL_DSN=
|
|
||||||
|
|
||||||
APP_SERVICE=vito
|
|
||||||
|
|
||||||
GITHUB_CLIENT_ID=
|
|
||||||
GITHUB_CLIENT_SECRET=
|
|
||||||
|
|
||||||
ABLY_KEY=
|
|
||||||
ABLY_PUBLIC_KEY=
|
|
||||||
|
28
.env.prod
28
.env.prod
@ -14,7 +14,7 @@ DB_DATABASE=
|
|||||||
DB_USERNAME=
|
DB_USERNAME=
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
|
|
||||||
BROADCAST_DRIVER=pusher
|
BROADCAST_DRIVER=null
|
||||||
CACHE_DRIVER=file
|
CACHE_DRIVER=file
|
||||||
FILESYSTEM_DRIVER=local
|
FILESYSTEM_DRIVER=local
|
||||||
QUEUE_CONNECTION=default
|
QUEUE_CONNECTION=default
|
||||||
@ -34,31 +34,5 @@ MAIL_ENCRYPTION=null
|
|||||||
MAIL_FROM_ADDRESS=null
|
MAIL_FROM_ADDRESS=null
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID=
|
|
||||||
AWS_SECRET_ACCESS_KEY=
|
|
||||||
AWS_DEFAULT_REGION=us-east-1
|
|
||||||
AWS_BUCKET=
|
|
||||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
|
||||||
|
|
||||||
PUSHER_APP_ID=app-id
|
|
||||||
PUSHER_APP_KEY=app-key
|
|
||||||
PUSHER_APP_SECRET=app-secret
|
|
||||||
PUSHER_HOST=soketi
|
|
||||||
PUSHER_PORT=6001
|
|
||||||
PUSHER_SCHEME=http
|
|
||||||
PUSHER_APP_CLUSTER=mt1
|
|
||||||
|
|
||||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
|
||||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
|
||||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
|
||||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
|
||||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
|
||||||
|
|
||||||
SSH_PUBLIC_KEY_NAME=ssh-public.key
|
SSH_PUBLIC_KEY_NAME=ssh-public.key
|
||||||
SSH_PRIVATE_KEY_NAME=ssh-private.pem
|
SSH_PRIVATE_KEY_NAME=ssh-private.pem
|
||||||
|
|
||||||
GITHUB_CLIENT_ID=
|
|
||||||
GITHUB_CLIENT_SECRET=
|
|
||||||
|
|
||||||
ABLY_KEY=
|
|
||||||
ABLY_PUBLIC_KEY=
|
|
||||||
|
45
.env.sail
Normal file
45
.env.sail
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
APP_NAME=Vito
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=http://vito.test
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
DB_HOST=mysql
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_DATABASE=vito
|
||||||
|
DB_USERNAME=sail
|
||||||
|
DB_PASSWORD=password
|
||||||
|
|
||||||
|
BROADCAST_DRIVER=null
|
||||||
|
CACHE_DRIVER=redis
|
||||||
|
FILESYSTEM_DRIVER=local
|
||||||
|
QUEUE_CONNECTION=default
|
||||||
|
SESSION_DRIVER=database
|
||||||
|
SESSION_LIFETIME=120
|
||||||
|
|
||||||
|
REDIS_HOST=redis
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_MAILER=smtp
|
||||||
|
MAIL_HOST=mailhog
|
||||||
|
MAIL_PORT=1025
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS=null
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
SSH_PUBLIC_KEY_NAME=ssh-public.key
|
||||||
|
SSH_PRIVATE_KEY_NAME=ssh-private.pem
|
||||||
|
|
||||||
|
APP_SERVICE=vito
|
||||||
|
|
||||||
|
FORWARD_REDIS_PORT=2060
|
||||||
|
FORWARD_DB_PORT=2070
|
||||||
|
APP_PORT=2080
|
||||||
|
HMR_PORT=2090
|
16
.env.testing
16
.env.testing
@ -14,7 +14,7 @@ DB_DATABASE=vito_test
|
|||||||
DB_USERNAME=root
|
DB_USERNAME=root
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
|
|
||||||
BROADCAST_DRIVER=pusher
|
BROADCAST_DRIVER=null
|
||||||
CACHE_DRIVER=array
|
CACHE_DRIVER=array
|
||||||
FILESYSTEM_DRIVER=local
|
FILESYSTEM_DRIVER=local
|
||||||
QUEUE_CONNECTION=database
|
QUEUE_CONNECTION=database
|
||||||
@ -23,19 +23,5 @@ SESSION_LIFETIME=120
|
|||||||
|
|
||||||
MAIL_MAILER=array
|
MAIL_MAILER=array
|
||||||
|
|
||||||
PUSHER_APP_ID=app-id
|
|
||||||
PUSHER_APP_KEY=app-key
|
|
||||||
PUSHER_APP_SECRET=app-secret
|
|
||||||
PUSHER_HOST=soketi
|
|
||||||
PUSHER_PORT=6001
|
|
||||||
PUSHER_SCHEME=http
|
|
||||||
PUSHER_APP_CLUSTER=mt1
|
|
||||||
|
|
||||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
|
||||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
|
||||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
|
||||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
|
||||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
|
||||||
|
|
||||||
SSH_PUBLIC_KEY_NAME=ssh-public.key
|
SSH_PUBLIC_KEY_NAME=ssh-public.key
|
||||||
SSH_PRIVATE_KEY_NAME=ssh-private.pem
|
SSH_PRIVATE_KEY_NAME=ssh-private.pem
|
||||||
|
2
.github/workflows/code-style.yml
vendored
2
.github/workflows/code-style.yml
vendored
@ -8,7 +8,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
code-style:
|
code-style:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
|
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -8,7 +8,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
|
23
CONTRIBUTING.md
Normal file
23
CONTRIBUTING.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Contributing
|
||||||
|
Thank you for your interest in contributing! There are a couple of contribution guidelines that make it easier to apply the incoming suggestions.
|
||||||
|
|
||||||
|
If you want to contribute please start with the issues. Issues labeled with "Bug" are the higher priorities.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
1. Issues are the best place to propose a new feature.
|
||||||
|
2. If you are adding a feature that there is no issue for yet, please first open an issue and label it as "feature" and lets discuss it before you implement it.
|
||||||
|
3. Search the issues before proposing a feature to see if it is already under discussion. Referencing existing issues is a good way to increase the priority of your own.
|
||||||
|
4. We don't have an issue template yet, but the more detailed your explanation, the more quickly we'll be able to evaluate it.
|
||||||
|
5. Search for the issue that you also have. Give it a reaction (and comment, if you have something to add). We note that!
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
1. Open PRs represent issues that we're actively thinking about merging (at a pace we can manage). If we think a proposal needs more discussion, or that the existing code would require a lot of back-and-forth to merge, we might close it and suggest you make an issue.
|
||||||
|
2. All PRs should be made against the `main` branch. This can be changed in the future.
|
||||||
|
3. If you are making changes to the front-end layer, Please build the assets via `npm run build` and push it with the other changes.
|
||||||
|
4. Write tests for your code. Tests can be Unit or Feature.
|
||||||
|
5. Code refactors will be closed. For the architectural refactors open an issue first.
|
||||||
|
6. Use `./vendor/bin/pint` to style your code before opening a PR otherwise the actions will fail.
|
||||||
|
7. Typo fixes in documentation are welcome, but if it's at all debatable we might just close it.
|
||||||
|
|
||||||
|
## Misc
|
||||||
|
1. If you think we closed something incorrectly, feel free to (politely) tell us why! We're human and make mistakes.
|
14
README.md
14
README.md
@ -10,9 +10,21 @@ ## Documentation
|
|||||||
|
|
||||||
https://vitodeploy.com
|
https://vitodeploy.com
|
||||||
|
|
||||||
|
## Feedbacks
|
||||||
|
|
||||||
|
https://features.vitodeploy.com
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
https://https://features.vitodeploy.com/roadmap
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
Feel free to open a PR
|
Please read the contribution guide [Here](/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Please read the security policy [Here](/SECURITY.md)
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
11
SECURITY.md
Normal file
11
SECURITY.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 0.x | :white_check_mark: |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you see a vulnerability, please open an issue or report it directly to me (sa.vaziry@gmail.com)
|
@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Actions\Database;
|
namespace App\Actions\Service;
|
||||||
|
|
||||||
|
use App\Enums\ServiceStatus;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
@ -18,23 +19,21 @@ public function install(Server $server, array $input): Service
|
|||||||
|
|
||||||
$phpMyAdmin = $server->defaultService('phpmyadmin');
|
$phpMyAdmin = $server->defaultService('phpmyadmin');
|
||||||
if ($phpMyAdmin) {
|
if ($phpMyAdmin) {
|
||||||
if ($phpMyAdmin->status === 'ready') {
|
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'install' => __('Already installed'),
|
'allowed_ip' => __('Already installed'),
|
||||||
])->errorBag('installPHPMyAdmin');
|
]);
|
||||||
}
|
|
||||||
$phpMyAdmin->delete();
|
|
||||||
}
|
}
|
||||||
$phpMyAdmin = new Service([
|
$phpMyAdmin = new Service([
|
||||||
'server_id' => $server->id,
|
'server_id' => $server->id,
|
||||||
'type' => 'phpmyadmin',
|
'type' => 'phpmyadmin',
|
||||||
'type_data' => [
|
'type_data' => [
|
||||||
'allowed_ip' => $input['allowed_ip'],
|
'allowed_ip' => $input['allowed_ip'],
|
||||||
|
'port' => $input['port'],
|
||||||
'php' => $server->defaultService('php')->version,
|
'php' => $server->defaultService('php')->version,
|
||||||
],
|
],
|
||||||
'name' => 'phpmyadmin',
|
'name' => 'phpmyadmin',
|
||||||
'version' => '5.1.2',
|
'version' => '5.1.2',
|
||||||
'status' => 'installing',
|
'status' => ServiceStatus::INSTALLING,
|
||||||
'is_default' => 1,
|
'is_default' => 1,
|
||||||
]);
|
]);
|
||||||
$phpMyAdmin->save();
|
$phpMyAdmin->save();
|
||||||
@ -50,6 +49,12 @@ private function validate(array $input): void
|
|||||||
{
|
{
|
||||||
Validator::make($input, [
|
Validator::make($input, [
|
||||||
'allowed_ip' => 'required',
|
'allowed_ip' => 'required',
|
||||||
])->validateWithBag('installPHPMyAdmin');
|
'port' => [
|
||||||
|
'required',
|
||||||
|
'numeric',
|
||||||
|
'min:1',
|
||||||
|
'max:65535',
|
||||||
|
],
|
||||||
|
])->validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -49,11 +49,6 @@ public function create(Server $server, array $input): Site
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect php version
|
|
||||||
if ($site->type()->language() === 'php') {
|
|
||||||
$site->php_version = $input['php_version'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate type
|
// validate type
|
||||||
$this->validateType($site, $input);
|
$this->validateType($site, $input);
|
||||||
|
|
||||||
|
35
app/Actions/Site/UpdateSourceControl.php
Executable file
35
app/Actions/Site/UpdateSourceControl.php
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Site;
|
||||||
|
|
||||||
|
use App\Models\Site;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class UpdateSourceControl
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function update(Site $site, array $input): void
|
||||||
|
{
|
||||||
|
$this->validate($input);
|
||||||
|
|
||||||
|
$site->source_control_id = $input['source_control'];
|
||||||
|
$site->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function validate(array $input): void
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'source_control' => [
|
||||||
|
'required',
|
||||||
|
Rule::exists('source_controls', 'id'),
|
||||||
|
],
|
||||||
|
])->validate();
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Actions\SourceControl;
|
namespace App\Actions\SourceControl;
|
||||||
|
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
@ -16,6 +17,7 @@ public function connect(array $input): void
|
|||||||
'provider' => $input['provider'],
|
'provider' => $input['provider'],
|
||||||
'profile' => $input['name'],
|
'profile' => $input['name'],
|
||||||
'access_token' => $input['token'],
|
'access_token' => $input['token'],
|
||||||
|
'url' => Arr::has($input, 'url') ? $input['url'] : null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! $sourceControl->provider()->connect()) {
|
if (! $sourceControl->provider()->connect()) {
|
||||||
@ -44,6 +46,11 @@ private function validate(array $input): void
|
|||||||
'token' => [
|
'token' => [
|
||||||
'required',
|
'required',
|
||||||
],
|
],
|
||||||
|
'url' => [
|
||||||
|
'nullable',
|
||||||
|
'url:http,https',
|
||||||
|
'ends_with:/',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
Validator::make($input, $rules)->validate();
|
Validator::make($input, $rules)->validate();
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,15 @@ public function create(User $user, array $input): void
|
|||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'provider' => $input['provider'],
|
'provider' => $input['provider'],
|
||||||
'profile' => $input['name'],
|
'profile' => $input['name'],
|
||||||
'credentials' => [
|
|
||||||
'token' => $input['token'],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$this->validateProvider($input, $storageProvider->provider()->validationRules());
|
||||||
|
|
||||||
|
$storageProvider->credentials = $storageProvider->provider()->credentialData($input);
|
||||||
|
|
||||||
if (! $storageProvider->provider()->connect()) {
|
if (! $storageProvider->provider()->connect()) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'token' => __("Couldn't connect to the provider"),
|
'provider' => __("Couldn't connect to the provider"),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$storageProvider->save();
|
$storageProvider->save();
|
||||||
@ -44,9 +46,11 @@ private function validate(User $user, array $input): void
|
|||||||
'required',
|
'required',
|
||||||
Rule::unique('storage_providers', 'profile')->where('user_id', $user->id),
|
Rule::unique('storage_providers', 'profile')->where('user_id', $user->id),
|
||||||
],
|
],
|
||||||
'token' => [
|
|
||||||
'required',
|
|
||||||
],
|
|
||||||
])->validate();
|
])->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function validateProvider(array $input, array $rules): void
|
||||||
|
{
|
||||||
|
Validator::make($input, $rules)->validate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ public function update(User $user, array $input): void
|
|||||||
Validator::make($input, [
|
Validator::make($input, [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
|
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
|
||||||
|
'timezone' => [
|
||||||
|
'required',
|
||||||
|
Rule::in(timezone_identifiers_list()),
|
||||||
|
],
|
||||||
])->validateWithBag('updateProfileInformation');
|
])->validateWithBag('updateProfileInformation');
|
||||||
|
|
||||||
if ($input['email'] !== $user->email) {
|
if ($input['email'] !== $user->email) {
|
||||||
@ -27,6 +31,7 @@ public function update(User $user, array $input): void
|
|||||||
$user->forceFill([
|
$user->forceFill([
|
||||||
'name' => $input['name'],
|
'name' => $input['name'],
|
||||||
'email' => $input['email'],
|
'email' => $input['email'],
|
||||||
|
'timezone' => $input['timezone'],
|
||||||
])->save();
|
])->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,6 +44,7 @@ protected function updateVerifiedUser(User $user, array $input): void
|
|||||||
$user->forceFill([
|
$user->forceFill([
|
||||||
'name' => $input['name'],
|
'name' => $input['name'],
|
||||||
'email' => $input['email'],
|
'email' => $input['email'],
|
||||||
|
'timezone' => $input['timezone'],
|
||||||
])->save();
|
])->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ public function create(
|
|||||||
?int $siteId = null
|
?int $siteId = null
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
public function delete(int $id, int $siteId = null): void;
|
public function delete(int $id, ?int $siteId = null): void;
|
||||||
|
|
||||||
public function restart(int $id, int $siteId = null): void;
|
public function restart(int $id, ?int $siteId = null): void;
|
||||||
|
|
||||||
public function stop(int $id, int $siteId = null): void;
|
public function stop(int $id, ?int $siteId = null): void;
|
||||||
|
|
||||||
public function start(int $id, int $siteId = null): void;
|
public function start(int $id, ?int $siteId = null): void;
|
||||||
|
|
||||||
public function getLogs(string $logPath): string;
|
public function getLogs(string $logPath): string;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ public function credentialData(array $input): array;
|
|||||||
|
|
||||||
public function data(array $input): array;
|
public function data(array $input): array;
|
||||||
|
|
||||||
public function connect(array $credentials = null): bool;
|
public function connect(?array $credentials = null): bool;
|
||||||
|
|
||||||
public function plans(): array;
|
public function plans(): array;
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ interface SiteType
|
|||||||
{
|
{
|
||||||
public function language(): string;
|
public function language(): string;
|
||||||
|
|
||||||
|
public function supportedFeatures(): array;
|
||||||
|
|
||||||
public function createValidationRules(array $input): array;
|
public function createValidationRules(array $input): array;
|
||||||
|
|
||||||
public function createFields(array $input): array;
|
public function createFields(array $input): array;
|
||||||
|
@ -6,7 +6,7 @@ interface SourceControlProvider
|
|||||||
{
|
{
|
||||||
public function connect(): bool;
|
public function connect(): bool;
|
||||||
|
|
||||||
public function getRepo(string $repo = null): mixed;
|
public function getRepo(?string $repo = null): mixed;
|
||||||
|
|
||||||
public function fullRepoUrl(string $repo, string $key): string;
|
public function fullRepoUrl(string $repo, string $key): string;
|
||||||
|
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
interface StorageProvider
|
interface StorageProvider
|
||||||
{
|
{
|
||||||
|
public function validationRules(): array;
|
||||||
|
|
||||||
|
public function credentialData(array $input): array;
|
||||||
|
|
||||||
public function connect(): bool;
|
public function connect(): bool;
|
||||||
|
|
||||||
public function upload(Server $server, string $src, string $dest): array;
|
public function upload(Server $server, string $src, string $dest): array;
|
||||||
|
16
app/Enums/SiteFeature.php
Normal file
16
app/Enums/SiteFeature.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
use BenSampo\Enum\Enum;
|
||||||
|
|
||||||
|
final class SiteFeature extends Enum
|
||||||
|
{
|
||||||
|
const DEPLOYMENT = 'deployment';
|
||||||
|
|
||||||
|
const ENV = 'env';
|
||||||
|
|
||||||
|
const SSL = 'ssl';
|
||||||
|
|
||||||
|
const QUEUES = 'queues';
|
||||||
|
}
|
@ -11,6 +11,4 @@ final class SourceControl extends Enum
|
|||||||
const GITLAB = 'gitlab';
|
const GITLAB = 'gitlab';
|
||||||
|
|
||||||
const BITBUCKET = 'bitbucket';
|
const BITBUCKET = 'bitbucket';
|
||||||
|
|
||||||
const CUSTOM = 'custom';
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
final class StorageProvider extends Enum
|
final class StorageProvider extends Enum
|
||||||
{
|
{
|
||||||
const GOOGLE = 'google';
|
|
||||||
|
|
||||||
const DROPBOX = 'dropbox';
|
const DROPBOX = 'dropbox';
|
||||||
|
|
||||||
|
const FTP = 'ftp';
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
class SourceControlIsNotConnected extends Exception
|
class SourceControlIsNotConnected extends Exception
|
||||||
{
|
{
|
||||||
public function __construct(protected SourceControl|string $sourceControl, string $message = null)
|
public function __construct(protected SourceControl|string|null $sourceControl, ?string $message = null)
|
||||||
{
|
{
|
||||||
parent::__construct($message ?? 'Source control is not connected');
|
parent::__construct($message ?? 'Source control is not connected');
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ class SSH
|
|||||||
|
|
||||||
protected PrivateKey $privateKey;
|
protected PrivateKey $privateKey;
|
||||||
|
|
||||||
public function init(Server $server, string $asUser = null): self
|
public function init(Server $server, ?string $asUser = null): self
|
||||||
{
|
{
|
||||||
$this->connection = null;
|
$this->connection = null;
|
||||||
$this->log = null;
|
$this->log = null;
|
||||||
@ -87,7 +87,7 @@ public function connect(bool $sftp = false): void
|
|||||||
/**
|
/**
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function exec(string|array|SSHCommand $commands, string $log = '', int $siteId = null): string
|
public function exec(string|array|SSHCommand $commands, string $log = '', ?int $siteId = null): string
|
||||||
{
|
{
|
||||||
if ($log) {
|
if ($log) {
|
||||||
$this->setLog($log, $siteId);
|
$this->setLog($log, $siteId);
|
||||||
|
39
app/Http/Controllers/GitHookController.php
Normal file
39
app/Http/Controllers/GitHookController.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
|
use App\Models\GitHook;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class GitHookController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke(Request $request)
|
||||||
|
{
|
||||||
|
if (! $request->input('secret')) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var GitHook $gitHook */
|
||||||
|
$gitHook = GitHook::query()
|
||||||
|
->where('secret', $request->input('secret'))
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
foreach ($gitHook->actions as $action) {
|
||||||
|
if ($action == 'deploy') {
|
||||||
|
try {
|
||||||
|
$gitHook->site->deploy();
|
||||||
|
} catch (SourceControlIsNotConnected) {
|
||||||
|
// TODO: send notification
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::error('git-hook-exception', (array) $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
60
app/Http/Livewire/Application/AutoDeployment.php
Normal file
60
app/Http/Livewire/Application/AutoDeployment.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Application;
|
||||||
|
|
||||||
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Traits\HasToast;
|
||||||
|
use App\Traits\RefreshComponentOnBroadcast;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Livewire\Component;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class AutoDeployment extends Component
|
||||||
|
{
|
||||||
|
use HasToast;
|
||||||
|
use RefreshComponentOnBroadcast;
|
||||||
|
|
||||||
|
public Site $site;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function enable(): void
|
||||||
|
{
|
||||||
|
if (! $this->site->auto_deployment) {
|
||||||
|
try {
|
||||||
|
$this->site->enableAutoDeployment();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->toast()->success(__('Auto deployment has been enabled.'));
|
||||||
|
} catch (SourceControlIsNotConnected) {
|
||||||
|
$this->toast()->error(__('Source control is not connected. Check site\'s settings.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function disable(): void
|
||||||
|
{
|
||||||
|
if ($this->site->auto_deployment) {
|
||||||
|
try {
|
||||||
|
$this->site->disableAutoDeployment();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->toast()->success(__('Auto deployment has been disabled.'));
|
||||||
|
} catch (SourceControlIsNotConnected) {
|
||||||
|
$this->toast()->error(__('Source control is not connected. Check site\'s settings.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
return view('livewire.application.auto-deployment');
|
||||||
|
}
|
||||||
|
}
|
@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
class Deploy extends Component
|
class Deploy extends Component
|
||||||
{
|
{
|
||||||
use RefreshComponentOnBroadcast;
|
|
||||||
use HasToast;
|
use HasToast;
|
||||||
|
use RefreshComponentOnBroadcast;
|
||||||
|
|
||||||
public Site $site;
|
public Site $site;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ public function save(): void
|
|||||||
session()->flash('status', 'script-updated');
|
session()->flash('status', 'script-updated');
|
||||||
|
|
||||||
$this->emitTo(Deploy::class, '$refresh');
|
$this->emitTo(Deploy::class, '$refresh');
|
||||||
|
$this->emitTo(AutoDeployment::class, '$refresh');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(): View
|
public function render(): View
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
class DeploymentsList extends Component
|
class DeploymentsList extends Component
|
||||||
{
|
{
|
||||||
use RefreshComponentOnBroadcast;
|
|
||||||
use HasCustomPaginationView;
|
use HasCustomPaginationView;
|
||||||
|
use RefreshComponentOnBroadcast;
|
||||||
|
|
||||||
public Site $site;
|
public Site $site;
|
||||||
|
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
namespace App\Http\Livewire\Php;
|
namespace App\Http\Livewire\Php;
|
||||||
|
|
||||||
use App\Actions\PHP\InstallNewPHP;
|
use App\Actions\PHP\InstallNewPHP;
|
||||||
|
use App\Actions\PHP\InstallPHPExtension;
|
||||||
use App\Actions\PHP\UpdatePHPIni;
|
use App\Actions\PHP\UpdatePHPIni;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
use App\SSHCommands\PHP\GetPHPIniCommand;
|
use App\SSHCommands\PHP\GetPHPIniCommand;
|
||||||
use App\Traits\RefreshComponentOnBroadcast;
|
use App\Traits\RefreshComponentOnBroadcast;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@ -24,6 +26,10 @@ class InstalledVersions extends Component
|
|||||||
|
|
||||||
public string $ini = 'Loading php.ini';
|
public string $ini = 'Loading php.ini';
|
||||||
|
|
||||||
|
public ?int $extensionId = null;
|
||||||
|
|
||||||
|
public string $extension = '';
|
||||||
|
|
||||||
public function install(string $version): void
|
public function install(string $version): void
|
||||||
{
|
{
|
||||||
app(InstallNewPHP::class)->install($this->server, [
|
app(InstallNewPHP::class)->install($this->server, [
|
||||||
@ -35,6 +41,7 @@ public function install(string $version): void
|
|||||||
|
|
||||||
public function restart(int $id): void
|
public function restart(int $id): void
|
||||||
{
|
{
|
||||||
|
/** @var Service $service */
|
||||||
$service = Service::query()->findOrFail($id);
|
$service = Service::query()->findOrFail($id);
|
||||||
$service->restart();
|
$service->restart();
|
||||||
|
|
||||||
@ -43,6 +50,7 @@ public function restart(int $id): void
|
|||||||
|
|
||||||
public function uninstall(): void
|
public function uninstall(): void
|
||||||
{
|
{
|
||||||
|
/** @var Service $service */
|
||||||
$service = Service::query()->findOrFail($this->uninstallId);
|
$service = Service::query()->findOrFail($this->uninstallId);
|
||||||
$service->uninstall();
|
$service->uninstall();
|
||||||
|
|
||||||
@ -56,6 +64,7 @@ public function loadIni(int $id): void
|
|||||||
$this->iniId = $id;
|
$this->iniId = $id;
|
||||||
$this->ini = 'Loading php.ini';
|
$this->ini = 'Loading php.ini';
|
||||||
|
|
||||||
|
/** @var Service $service */
|
||||||
$service = Service::query()->findOrFail($this->iniId);
|
$service = Service::query()->findOrFail($this->iniId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -67,6 +76,7 @@ public function loadIni(int $id): void
|
|||||||
|
|
||||||
public function saveIni(): void
|
public function saveIni(): void
|
||||||
{
|
{
|
||||||
|
/** @var Service $service */
|
||||||
$service = Service::query()->findOrFail($this->iniId);
|
$service = Service::query()->findOrFail($this->iniId);
|
||||||
|
|
||||||
app(UpdatePHPIni::class)->update($service, $this->all()['ini']);
|
app(UpdatePHPIni::class)->update($service, $this->all()['ini']);
|
||||||
@ -76,10 +86,32 @@ public function saveIni(): void
|
|||||||
session()->flash('status', 'ini-updated');
|
session()->flash('status', 'ini-updated');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function installExtension(): void
|
||||||
|
{
|
||||||
|
/** @var Service $service */
|
||||||
|
$service = Service::query()->findOrFail($this->extensionId);
|
||||||
|
|
||||||
|
app(InstallPHPExtension::class)->handle($service, [
|
||||||
|
'name' => $this->extension,
|
||||||
|
]);
|
||||||
|
|
||||||
|
session()->flash('status', 'started-installation');
|
||||||
|
}
|
||||||
|
|
||||||
public function render(): View
|
public function render(): View
|
||||||
{
|
{
|
||||||
|
if ($this->extensionId) {
|
||||||
|
/** @var Service $php */
|
||||||
|
$php = Service::query()->findOrFail($this->extensionId);
|
||||||
|
$installedExtensions = $php->type_data['extensions'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
return view('livewire.php.installed-versions', [
|
return view('livewire.php.installed-versions', [
|
||||||
'phps' => $this->server->services()->where('type', 'php')->get(),
|
'phps' => $this->server->services()->where('type', 'php')->get(),
|
||||||
|
'installedExtensions' => $installedExtensions ?? [],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,13 @@ class UpdateProfileInformation extends Component
|
|||||||
|
|
||||||
public string $email;
|
public string $email;
|
||||||
|
|
||||||
|
public string $timezone;
|
||||||
|
|
||||||
public function mount(): void
|
public function mount(): void
|
||||||
{
|
{
|
||||||
$this->name = auth()->user()->name;
|
$this->name = auth()->user()->name;
|
||||||
$this->email = auth()->user()->email;
|
$this->email = auth()->user()->email;
|
||||||
|
$this->timezone = auth()->user()->timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
class LogsList extends Component
|
class LogsList extends Component
|
||||||
{
|
{
|
||||||
use RefreshComponentOnBroadcast;
|
|
||||||
use HasCustomPaginationView;
|
use HasCustomPaginationView;
|
||||||
|
use RefreshComponentOnBroadcast;
|
||||||
|
|
||||||
public ?int $count = null;
|
public ?int $count = null;
|
||||||
|
|
||||||
|
31
app/Http/Livewire/Services/InstallPHPMyAdmin.php
Normal file
31
app/Http/Livewire/Services/InstallPHPMyAdmin.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Services;
|
||||||
|
|
||||||
|
use App\Actions\Service\InstallPHPMyAdmin as InstallPHPMyAdminAction;
|
||||||
|
use App\Models\Server;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class InstallPHPMyAdmin extends Component
|
||||||
|
{
|
||||||
|
public Server $server;
|
||||||
|
|
||||||
|
public string $allowed_ip;
|
||||||
|
|
||||||
|
public string $port = '5433';
|
||||||
|
|
||||||
|
public function install(): void
|
||||||
|
{
|
||||||
|
app(InstallPHPMyAdminAction::class)->install($this->server, $this->all());
|
||||||
|
|
||||||
|
$this->dispatchBrowserEvent('started', true);
|
||||||
|
|
||||||
|
$this->emitTo(ServicesList::class, '$refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
return view('livewire.services.install-phpmyadmin');
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Livewire\Services;
|
namespace App\Http\Livewire\Services;
|
||||||
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
|
use App\Models\Service;
|
||||||
use App\Traits\RefreshComponentOnBroadcast;
|
use App\Traits\RefreshComponentOnBroadcast;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -15,6 +16,7 @@ class ServicesList extends Component
|
|||||||
|
|
||||||
public function stop(int $id): void
|
public function stop(int $id): void
|
||||||
{
|
{
|
||||||
|
/** @var Service $service */
|
||||||
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
||||||
|
|
||||||
$service->stop();
|
$service->stop();
|
||||||
@ -24,6 +26,7 @@ public function stop(int $id): void
|
|||||||
|
|
||||||
public function start(int $id): void
|
public function start(int $id): void
|
||||||
{
|
{
|
||||||
|
/** @var Service $service */
|
||||||
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
||||||
|
|
||||||
$service->start();
|
$service->start();
|
||||||
@ -33,6 +36,7 @@ public function start(int $id): void
|
|||||||
|
|
||||||
public function restart(int $id): void
|
public function restart(int $id): void
|
||||||
{
|
{
|
||||||
|
/** @var Service $service */
|
||||||
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
||||||
|
|
||||||
$service->restart();
|
$service->restart();
|
||||||
@ -40,6 +44,16 @@ public function restart(int $id): void
|
|||||||
$this->refreshComponent([]);
|
$this->refreshComponent([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function uninstall(int $id): void
|
||||||
|
{
|
||||||
|
/** @var Service $service */
|
||||||
|
$service = $this->server->services()->where('id', $id)->firstOrFail();
|
||||||
|
|
||||||
|
$service->uninstall();
|
||||||
|
|
||||||
|
$this->refreshComponent([]);
|
||||||
|
}
|
||||||
|
|
||||||
public function render(): View
|
public function render(): View
|
||||||
{
|
{
|
||||||
return view('livewire.services.services-list', [
|
return view('livewire.services.services-list', [
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Sites;
|
namespace App\Http\Livewire\Sites;
|
||||||
|
|
||||||
use App\Enums\SiteType;
|
|
||||||
use App\Exceptions\SourceControlIsNotConnected;
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
@ -16,23 +15,12 @@ class CreateSite extends Component
|
|||||||
|
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
|
||||||
public string $type = SiteType::LARAVEL;
|
public array $inputs = [
|
||||||
|
'type' => '',
|
||||||
public string $domain;
|
'web_directory' => 'public',
|
||||||
|
'source_control' => '',
|
||||||
public string $alias;
|
'php_version' => '',
|
||||||
|
];
|
||||||
public string $php_version = '';
|
|
||||||
|
|
||||||
public string $web_directory = 'public';
|
|
||||||
|
|
||||||
public string $source_control = '';
|
|
||||||
|
|
||||||
public string $repository;
|
|
||||||
|
|
||||||
public string $branch;
|
|
||||||
|
|
||||||
public bool $composer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws SourceControlIsNotConnected
|
* @throws SourceControlIsNotConnected
|
||||||
@ -41,7 +29,7 @@ public function create(): void
|
|||||||
{
|
{
|
||||||
$site = app(\App\Actions\Site\CreateSite::class)->create(
|
$site = app(\App\Actions\Site\CreateSite::class)->create(
|
||||||
$this->server,
|
$this->server,
|
||||||
$this->all()
|
$this->inputs
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->redirect(route('servers.sites.show', [
|
$this->redirect(route('servers.sites.show', [
|
||||||
|
33
app/Http/Livewire/Sites/UpdateSourceControlProvider.php
Normal file
33
app/Http/Livewire/Sites/UpdateSourceControlProvider.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Sites;
|
||||||
|
|
||||||
|
use App\Actions\Site\UpdateSourceControl;
|
||||||
|
use App\Models\Site;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class UpdateSourceControlProvider extends Component
|
||||||
|
{
|
||||||
|
public Site $site;
|
||||||
|
|
||||||
|
public $source_control = null;
|
||||||
|
|
||||||
|
public function update(): void
|
||||||
|
{
|
||||||
|
app(UpdateSourceControl::class)->update($this->site, $this->all());
|
||||||
|
|
||||||
|
$this->resetErrorBag();
|
||||||
|
|
||||||
|
session()->flash('status', 'source-control-updated');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
if (! $this->source_control) {
|
||||||
|
$this->source_control = $this->site->source_control_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('livewire.sites.update-source-control-provider');
|
||||||
|
}
|
||||||
|
}
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
class SslsList extends Component
|
class SslsList extends Component
|
||||||
{
|
{
|
||||||
use RefreshComponentOnBroadcast;
|
|
||||||
use HasToast;
|
use HasToast;
|
||||||
|
use RefreshComponentOnBroadcast;
|
||||||
|
|
||||||
public Site $site;
|
public Site $site;
|
||||||
|
|
||||||
|
@ -14,6 +14,20 @@ class ConnectProvider extends Component
|
|||||||
|
|
||||||
public string $token;
|
public string $token;
|
||||||
|
|
||||||
|
public string $host;
|
||||||
|
|
||||||
|
public string $port;
|
||||||
|
|
||||||
|
public string $path = '/';
|
||||||
|
|
||||||
|
public string $username;
|
||||||
|
|
||||||
|
public string $password;
|
||||||
|
|
||||||
|
public int $ssl = 1;
|
||||||
|
|
||||||
|
public int $passive = 0;
|
||||||
|
|
||||||
public function connect(): void
|
public function connect(): void
|
||||||
{
|
{
|
||||||
app(CreateStorageProvider::class)->create(auth()->user(), $this->all());
|
app(CreateStorageProvider::class)->create(auth()->user(), $this->all());
|
||||||
|
@ -13,7 +13,7 @@ class Initialize extends InstallationJob
|
|||||||
|
|
||||||
protected ?string $asUser;
|
protected ?string $asUser;
|
||||||
|
|
||||||
public function __construct(Server $server, string $asUser = null)
|
public function __construct(Server $server, ?string $asUser = null)
|
||||||
{
|
{
|
||||||
$this->server = $server->refresh();
|
$this->server = $server->refresh();
|
||||||
$this->asUser = $asUser;
|
$this->asUser = $asUser;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Jobs\Installation;
|
namespace App\Jobs\Installation;
|
||||||
|
|
||||||
use App\Actions\FirewallRule\CreateRule;
|
use App\Actions\FirewallRule\CreateRule;
|
||||||
|
use App\Enums\ServiceStatus;
|
||||||
use App\Jobs\Job;
|
use App\Jobs\Job;
|
||||||
use App\Models\FirewallRule;
|
use App\Models\FirewallRule;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
@ -32,6 +33,9 @@ public function handle(): void
|
|||||||
$this->downloadSource();
|
$this->downloadSource();
|
||||||
$this->setUpVHost();
|
$this->setUpVHost();
|
||||||
$this->restartPHP();
|
$this->restartPHP();
|
||||||
|
$this->service->update([
|
||||||
|
'status' => ServiceStatus::READY,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,7 +45,7 @@ private function setUpFirewall(): void
|
|||||||
{
|
{
|
||||||
$this->firewallRule = FirewallRule::query()
|
$this->firewallRule = FirewallRule::query()
|
||||||
->where('server_id', $this->service->server_id)
|
->where('server_id', $this->service->server_id)
|
||||||
->where('port', '54331')
|
->where('port', $this->service->type_data['port'])
|
||||||
->first();
|
->first();
|
||||||
if ($this->firewallRule) {
|
if ($this->firewallRule) {
|
||||||
$this->firewallRule->source = $this->service->type_data['allowed_ip'];
|
$this->firewallRule->source = $this->service->type_data['allowed_ip'];
|
||||||
@ -52,7 +56,7 @@ private function setUpFirewall(): void
|
|||||||
[
|
[
|
||||||
'type' => 'allow',
|
'type' => 'allow',
|
||||||
'protocol' => 'tcp',
|
'protocol' => 'tcp',
|
||||||
'port' => '54331',
|
'port' => $this->service->type_data['port'],
|
||||||
'source' => $this->service->type_data['allowed_ip'],
|
'source' => $this->service->type_data['allowed_ip'],
|
||||||
'mask' => '0',
|
'mask' => '0',
|
||||||
]
|
]
|
||||||
@ -78,6 +82,7 @@ private function setUpVHost(): void
|
|||||||
{
|
{
|
||||||
$vhost = File::get(resource_path('commands/webserver/nginx/phpmyadmin-vhost.conf'));
|
$vhost = File::get(resource_path('commands/webserver/nginx/phpmyadmin-vhost.conf'));
|
||||||
$vhost = Str::replace('__php_version__', $this->service->server->defaultService('php')->version, $vhost);
|
$vhost = Str::replace('__php_version__', $this->service->server->defaultService('php')->version, $vhost);
|
||||||
|
$vhost = Str::replace('__port__', $this->service->type_data['port'], $vhost);
|
||||||
$this->service->server->ssh()->exec(
|
$this->service->server->ssh()->exec(
|
||||||
new CreateNginxPHPMyAdminVHostCommand($vhost),
|
new CreateNginxPHPMyAdminVHostCommand($vhost),
|
||||||
'create-phpmyadmin-vhost'
|
'create-phpmyadmin-vhost'
|
||||||
@ -98,6 +103,9 @@ private function restartPHP(): void
|
|||||||
public function failed(Throwable $throwable): Throwable
|
public function failed(Throwable $throwable): Throwable
|
||||||
{
|
{
|
||||||
$this->firewallRule?->removeFromServer();
|
$this->firewallRule?->removeFromServer();
|
||||||
|
$this->service->update([
|
||||||
|
'status' => ServiceStatus::INSTALLATION_FAILED,
|
||||||
|
]);
|
||||||
throw $throwable;
|
throw $throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ private function removeFirewallRule(): void
|
|||||||
/** @var ?FirewallRule $rule */
|
/** @var ?FirewallRule $rule */
|
||||||
$rule = FirewallRule::query()
|
$rule = FirewallRule::query()
|
||||||
->where('server_id', $this->service->server_id)
|
->where('server_id', $this->service->server_id)
|
||||||
->where('port', '54331')
|
->where('port', $this->service->type_data['port'])
|
||||||
->first();
|
->first();
|
||||||
$rule?->removeFromServer();
|
$rule?->removeFromServer();
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
abstract class Job implements ShouldQueue, ShouldBeUnique
|
abstract class Job implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use App\Enums\DeploymentStatus;
|
use App\Enums\DeploymentStatus;
|
||||||
use App\Events\Broadcast;
|
use App\Events\Broadcast;
|
||||||
use App\Helpers\SSH;
|
|
||||||
use App\Jobs\Job;
|
use App\Jobs\Job;
|
||||||
use App\Models\Deployment;
|
use App\Models\Deployment;
|
||||||
use App\SSHCommands\System\RunScriptCommand;
|
use App\SSHCommands\System\RunScriptCommand;
|
||||||
@ -18,13 +17,11 @@ class Deploy extends Job
|
|||||||
|
|
||||||
protected string $script;
|
protected string $script;
|
||||||
|
|
||||||
protected SSH $ssh;
|
public function __construct(Deployment $deployment, string $path)
|
||||||
|
|
||||||
public function __construct(Deployment $deployment, string $path, string $script)
|
|
||||||
{
|
{
|
||||||
|
$this->script = $deployment->deploymentScript->content;
|
||||||
$this->deployment = $deployment;
|
$this->deployment = $deployment;
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
$this->script = $script;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,28 +29,31 @@ public function __construct(Deployment $deployment, string $path, string $script
|
|||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
$this->ssh = $this->deployment->site->server->ssh();
|
$ssh = $this->deployment->site->server->ssh();
|
||||||
$this->ssh->exec(
|
try {
|
||||||
|
$ssh->exec(
|
||||||
new RunScriptCommand($this->path, $this->script),
|
new RunScriptCommand($this->path, $this->script),
|
||||||
'deploy',
|
'deploy',
|
||||||
$this->deployment->site_id
|
$this->deployment->site_id
|
||||||
);
|
);
|
||||||
$this->deployment->status = DeploymentStatus::FINISHED;
|
$this->deployment->status = DeploymentStatus::FINISHED;
|
||||||
$this->deployment->log_id = $this->ssh->log->id;
|
$this->deployment->log_id = $ssh->log->id;
|
||||||
$this->deployment->save();
|
$this->deployment->save();
|
||||||
event(
|
event(
|
||||||
new Broadcast('deploy-site-finished', [
|
new Broadcast('deploy-site-finished', [
|
||||||
'deployment' => $this->deployment,
|
'deployment' => $this->deployment,
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
} catch (Throwable) {
|
||||||
|
$this->deployment->log_id = $ssh->log->id;
|
||||||
|
$this->deployment->save();
|
||||||
|
$this->failed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function failed(): void
|
public function failed(): void
|
||||||
{
|
{
|
||||||
$this->deployment->status = DeploymentStatus::FAILED;
|
$this->deployment->status = DeploymentStatus::FAILED;
|
||||||
if ($this->ssh->log) {
|
|
||||||
$this->deployment->log_id = $this->ssh->log->id;
|
|
||||||
}
|
|
||||||
$this->deployment->save();
|
$this->deployment->save();
|
||||||
event(
|
event(
|
||||||
new Broadcast('deploy-site-failed', [
|
new Broadcast('deploy-site-failed', [
|
||||||
|
@ -52,7 +52,7 @@ public function handle(): void
|
|||||||
$this->site->id
|
$this->site->id
|
||||||
);
|
);
|
||||||
|
|
||||||
if (! Str::contains($result, 'Wordpress installed!')) {
|
if (! Str::contains($result, 'Success')) {
|
||||||
throw new FailedToInstallWordpress($result);
|
throw new FailedToInstallWordpress($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ public function __construct()
|
|||||||
|
|
||||||
public function handle(Broadcast $event): void
|
public function handle(Broadcast $event): void
|
||||||
{
|
{
|
||||||
Cache::set('broadcast', [
|
Cache::put('broadcast', [
|
||||||
'type' => $event->type,
|
'type' => $event->type,
|
||||||
'data' => $event->data,
|
'data' => $event->data,
|
||||||
], now()->addMinutes(5));
|
], now()->addMinutes(5));
|
||||||
|
@ -76,7 +76,7 @@ public function getPathAttribute(): string
|
|||||||
|
|
||||||
public function getStoragePathAttribute(): string
|
public function getStoragePathAttribute(): string
|
||||||
{
|
{
|
||||||
return '/'.$this->backup->database->name.'/'.$this->name.'.zip';
|
return '/'.$this->name.'.zip';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restore(Database $database): void
|
public function restore(Database $database): void
|
||||||
|
@ -57,19 +57,19 @@ public function server(): BelongsTo
|
|||||||
/**
|
/**
|
||||||
* create database on server
|
* create database on server
|
||||||
*/
|
*/
|
||||||
public function createOnServer(): void
|
public function createOnServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new CreateOnServer($this))->onConnection('ssh');
|
dispatch(new CreateOnServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* delete database from server
|
* delete database from server
|
||||||
*/
|
*/
|
||||||
public function deleteFromServer(): void
|
public function deleteFromServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
$this->status = DatabaseStatus::DELETING;
|
$this->status = DatabaseStatus::DELETING;
|
||||||
$this->save();
|
$this->save();
|
||||||
dispatch(new DeleteFromServer($this))->onConnection('ssh');
|
dispatch(new DeleteFromServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function backups(): HasMany
|
public function backups(): HasMany
|
||||||
|
@ -54,17 +54,17 @@ public function scopeHasDatabase(Builder $query, string $databaseName): Builder
|
|||||||
return $query->where('databases', 'like', "%\"$databaseName\"%");
|
return $query->where('databases', 'like', "%\"$databaseName\"%");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createOnServer(): void
|
public function createOnServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new CreateOnServer($this))->onConnection('ssh');
|
dispatch(new CreateOnServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteFromServer(): void
|
public function deleteFromServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
$this->status = DatabaseStatus::DELETING;
|
$this->status = DatabaseStatus::DELETING;
|
||||||
$this->save();
|
$this->save();
|
||||||
|
|
||||||
dispatch(new DeleteFromServer($this))->onConnection('ssh');
|
dispatch(new DeleteFromServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function linkNewDatabase(string $name): void
|
public function linkNewDatabase(string $name): void
|
||||||
@ -79,14 +79,14 @@ public function linkNewDatabase(string $name): void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function linkUser(): void
|
public function linkUser(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new LinkUser($this))->onConnection('ssh');
|
dispatch(new LinkUser($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unlinkUser(): void
|
public function unlinkUser(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new UnlinkUser($this))->onConnection('ssh');
|
dispatch(new UnlinkUser($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFullUserAttribute(): string
|
public function getFullUserAttribute(): string
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Exceptions\FailedToDeployGitHook;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@ -22,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
class GitHook extends AbstractModel
|
class GitHook extends AbstractModel
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'site_id',
|
'site_id',
|
||||||
'source_control_id',
|
'source_control_id',
|
||||||
@ -55,9 +57,6 @@ public function scopeHasEvent(Builder $query, string $event): Builder
|
|||||||
return $query->where('events', 'like', "%\"{$event}\"%");
|
return $query->where('events', 'like', "%\"{$event}\"%");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws FailedToDeployGitHook
|
|
||||||
*/
|
|
||||||
public function deployHook(): void
|
public function deployHook(): void
|
||||||
{
|
{
|
||||||
$this->update(
|
$this->update(
|
||||||
|
@ -233,7 +233,7 @@ public function install(): void
|
|||||||
// $this->team->notify(new ServerInstallationStarted($this));
|
// $this->team->notify(new ServerInstallationStarted($this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ssh(string $user = null): \App\Helpers\SSH|SSHFake
|
public function ssh(?string $user = null): \App\Helpers\SSH|SSHFake
|
||||||
{
|
{
|
||||||
return SSH::init($this, $user);
|
return SSH::init($this, $user);
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ public function provider(): \App\Contracts\ServerProvider
|
|||||||
return new $providerClass($this);
|
return new $providerClass($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function webserver(string $version = null): ?Service
|
public function webserver(?string $version = null): ?Service
|
||||||
{
|
{
|
||||||
if (! $version) {
|
if (! $version) {
|
||||||
return $this->defaultService('webserver');
|
return $this->defaultService('webserver');
|
||||||
@ -272,7 +272,7 @@ public function webserver(string $version = null): ?Service
|
|||||||
return $this->service('webserver', $version);
|
return $this->service('webserver', $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function database(string $version = null): ?Service
|
public function database(?string $version = null): ?Service
|
||||||
{
|
{
|
||||||
if (! $version) {
|
if (! $version) {
|
||||||
return $this->defaultService('database');
|
return $this->defaultService('database');
|
||||||
@ -281,7 +281,7 @@ public function database(string $version = null): ?Service
|
|||||||
return $this->service('database', $version);
|
return $this->service('database', $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function firewall(string $version = null): ?Service
|
public function firewall(?string $version = null): ?Service
|
||||||
{
|
{
|
||||||
if (! $version) {
|
if (! $version) {
|
||||||
return $this->defaultService('firewall');
|
return $this->defaultService('firewall');
|
||||||
@ -290,7 +290,7 @@ public function firewall(string $version = null): ?Service
|
|||||||
return $this->service('firewall', $version);
|
return $this->service('firewall', $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processManager(string $version = null): ?Service
|
public function processManager(?string $version = null): ?Service
|
||||||
{
|
{
|
||||||
if (! $version) {
|
if (! $version) {
|
||||||
return $this->defaultService('process_manager');
|
return $this->defaultService('process_manager');
|
||||||
@ -299,7 +299,7 @@ public function processManager(string $version = null): ?Service
|
|||||||
return $this->service('process_manager', $version);
|
return $this->service('process_manager', $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function php(string $version = null): ?Service
|
public function php(?string $version = null): ?Service
|
||||||
{
|
{
|
||||||
if (! $version) {
|
if (! $version) {
|
||||||
return $this->defaultService('php');
|
return $this->defaultService('php');
|
||||||
|
@ -76,7 +76,7 @@ public function uninstaller(): mixed
|
|||||||
return new $uninstaller($this);
|
return new $uninstaller($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUnitAttribute($value): string
|
public function getUnitAttribute($value): ?string
|
||||||
{
|
{
|
||||||
if ($value) {
|
if ($value) {
|
||||||
return $value;
|
return $value;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
use App\Enums\DeploymentStatus;
|
use App\Enums\DeploymentStatus;
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteStatus;
|
||||||
use App\Enums\SslStatus;
|
use App\Enums\SslStatus;
|
||||||
use App\Exceptions\FailedToDeployGitHook;
|
use App\Events\Broadcast;
|
||||||
use App\Exceptions\SourceControlIsNotConnected;
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
use App\Jobs\Site\ChangePHPVersion;
|
use App\Jobs\Site\ChangePHPVersion;
|
||||||
use App\Jobs\Site\Deploy;
|
use App\Jobs\Site\Deploy;
|
||||||
@ -19,7 +19,8 @@
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,13 +267,7 @@ public function deploy(): Deployment
|
|||||||
}
|
}
|
||||||
$deployment->save();
|
$deployment->save();
|
||||||
|
|
||||||
dispatch(
|
dispatch(new Deploy($deployment, $this->path))->onConnection('ssh');
|
||||||
new Deploy(
|
|
||||||
$deployment,
|
|
||||||
$this->path,
|
|
||||||
$this->deployment_script_text
|
|
||||||
)
|
|
||||||
)->onConnection('ssh');
|
|
||||||
|
|
||||||
return $deployment;
|
return $deployment;
|
||||||
}
|
}
|
||||||
@ -347,22 +342,16 @@ public function getWebDirectoryPathAttribute(): string
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws SourceControlIsNotConnected
|
* @throws SourceControlIsNotConnected
|
||||||
* @throws ValidationException
|
|
||||||
* @throws FailedToDeployGitHook
|
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function enableAutoDeployment(): void
|
public function enableAutoDeployment(): void
|
||||||
{
|
{
|
||||||
if ($this->gitHook) {
|
if ($this->gitHook) {
|
||||||
throw ValidationException::withMessages([
|
return;
|
||||||
'auto_deployment' => __('Auto deployment already enabled'),
|
|
||||||
])->errorBag('auto_deployment');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->sourceControl()) {
|
if (! $this->sourceControl()) {
|
||||||
throw ValidationException::withMessages([
|
throw new SourceControlIsNotConnected($this->source_control);
|
||||||
'auto_deployment' => __('Your application does not use any source controls'),
|
|
||||||
])->errorBag('auto_deployment');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -370,7 +359,7 @@ public function enableAutoDeployment(): void
|
|||||||
$gitHook = new GitHook([
|
$gitHook = new GitHook([
|
||||||
'site_id' => $this->id,
|
'site_id' => $this->id,
|
||||||
'source_control_id' => $this->sourceControl()->id,
|
'source_control_id' => $this->sourceControl()->id,
|
||||||
'secret' => generate_uid(),
|
'secret' => Str::uuid()->toString(),
|
||||||
'actions' => ['deploy'],
|
'actions' => ['deploy'],
|
||||||
'events' => ['push'],
|
'events' => ['push'],
|
||||||
]);
|
]);
|
||||||
@ -405,4 +394,49 @@ public function getSshKeyNameAttribute(): string
|
|||||||
{
|
{
|
||||||
return str('site_'.$this->id)->toString();
|
return str('site_'.$this->id)->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function installationFinished(): void
|
||||||
|
{
|
||||||
|
$this->update([
|
||||||
|
'status' => SiteStatus::READY,
|
||||||
|
'progress' => 100,
|
||||||
|
]);
|
||||||
|
event(
|
||||||
|
new Broadcast('install-site-finished', [
|
||||||
|
'site' => $this,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
/** @todo notify */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function installationFailed(Throwable $e): void
|
||||||
|
{
|
||||||
|
$this->update([
|
||||||
|
'status' => SiteStatus::INSTALLATION_FAILED,
|
||||||
|
]);
|
||||||
|
event(
|
||||||
|
new Broadcast('install-site-failed', [
|
||||||
|
'site' => $this,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
/** @todo notify */
|
||||||
|
Log::error('install-site-error', [
|
||||||
|
'error' => (string) $e,
|
||||||
|
]);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasFeature(string $feature): bool
|
||||||
|
{
|
||||||
|
return in_array($feature, $this->type()->supportedFeatures());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isReady(): bool
|
||||||
|
{
|
||||||
|
return $this->status === SiteStatus::READY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public function provider(): SourceControlProvider
|
|||||||
return new $providerClass($this);
|
return new $providerClass($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRepo(string $repo = null): ?array
|
public function getRepo(?string $repo = null): ?array
|
||||||
{
|
{
|
||||||
return $this->provider()->getRepo($repo);
|
return $this->provider()->getRepo($repo);
|
||||||
}
|
}
|
||||||
|
40
app/SSHCommands/Storage/DownloadFromFTPCommand.php
Normal file
40
app/SSHCommands/Storage/DownloadFromFTPCommand.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\SSHCommands\Storage;
|
||||||
|
|
||||||
|
use App\SSHCommands\Command;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class DownloadFromFTPCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected string $src,
|
||||||
|
protected string $dest,
|
||||||
|
protected string $host,
|
||||||
|
protected string $port,
|
||||||
|
protected string $username,
|
||||||
|
protected string $password,
|
||||||
|
protected bool $ssl,
|
||||||
|
protected bool $passive,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file(): string
|
||||||
|
{
|
||||||
|
return File::get(resource_path('commands/storage/download-from-ftp.sh'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function content(): string
|
||||||
|
{
|
||||||
|
return str($this->file())
|
||||||
|
->replace('__src__', $this->src)
|
||||||
|
->replace('__dest__', $this->dest)
|
||||||
|
->replace('__host__', $this->host)
|
||||||
|
->replace('__port__', $this->port)
|
||||||
|
->replace('__username__', $this->username)
|
||||||
|
->replace('__password__', $this->password)
|
||||||
|
->replace('__ssl__', $this->ssl ? 's' : '')
|
||||||
|
->replace('__passive__', $this->passive ? '--ftp-pasv' : '')
|
||||||
|
->toString();
|
||||||
|
}
|
||||||
|
}
|
40
app/SSHCommands/Storage/UploadToFTPCommand.php
Normal file
40
app/SSHCommands/Storage/UploadToFTPCommand.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\SSHCommands\Storage;
|
||||||
|
|
||||||
|
use App\SSHCommands\Command;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class UploadToFTPCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected string $src,
|
||||||
|
protected string $dest,
|
||||||
|
protected string $host,
|
||||||
|
protected string $port,
|
||||||
|
protected string $username,
|
||||||
|
protected string $password,
|
||||||
|
protected bool $ssl,
|
||||||
|
protected bool $passive,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file(): string
|
||||||
|
{
|
||||||
|
return File::get(resource_path('commands/storage/upload-to-ftp.sh'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function content(): string
|
||||||
|
{
|
||||||
|
return str($this->file())
|
||||||
|
->replace('__src__', $this->src)
|
||||||
|
->replace('__dest__', $this->dest)
|
||||||
|
->replace('__host__', $this->host)
|
||||||
|
->replace('__port__', $this->port)
|
||||||
|
->replace('__username__', $this->username)
|
||||||
|
->replace('__password__', $this->password)
|
||||||
|
->replace('__ssl__', $this->ssl ? 's' : '')
|
||||||
|
->replace('__passive__', $this->passive ? '--ftp-pasv' : '')
|
||||||
|
->toString();
|
||||||
|
}
|
||||||
|
}
|
@ -63,7 +63,7 @@ public function data(array $input): array
|
|||||||
/**
|
/**
|
||||||
* @throws CouldNotConnectToProvider
|
* @throws CouldNotConnectToProvider
|
||||||
*/
|
*/
|
||||||
public function connect(array $credentials = null): bool
|
public function connect(?array $credentials = null): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->connectToEc2ClientTest($credentials);
|
$this->connectToEc2ClientTest($credentials);
|
||||||
|
@ -10,7 +10,7 @@ abstract class AbstractProvider implements ServerProvider
|
|||||||
{
|
{
|
||||||
protected ?Server $server;
|
protected ?Server $server;
|
||||||
|
|
||||||
public function __construct(Server $server = null)
|
public function __construct(?Server $server = null)
|
||||||
{
|
{
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public function data(array $input): array
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function connect(array $credentials = null): bool
|
public function connect(?array $credentials = null): bool
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public function data(array $input): array
|
|||||||
/**
|
/**
|
||||||
* @throws CouldNotConnectToProvider
|
* @throws CouldNotConnectToProvider
|
||||||
*/
|
*/
|
||||||
public function connect(array $credentials = null): bool
|
public function connect(?array $credentials = null): bool
|
||||||
{
|
{
|
||||||
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account');
|
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account');
|
||||||
if (! $connect->ok()) {
|
if (! $connect->ok()) {
|
||||||
|
@ -45,7 +45,7 @@ public function data(array $input): array
|
|||||||
/**
|
/**
|
||||||
* @throws CouldNotConnectToProvider
|
* @throws CouldNotConnectToProvider
|
||||||
*/
|
*/
|
||||||
public function connect(array $credentials = null): bool
|
public function connect(?array $credentials = null): bool
|
||||||
{
|
{
|
||||||
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/servers');
|
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/servers');
|
||||||
if (! $connect->ok()) {
|
if (! $connect->ok()) {
|
||||||
|
@ -57,7 +57,7 @@ public function data(array $input): array
|
|||||||
/**
|
/**
|
||||||
* @throws CouldNotConnectToProvider
|
* @throws CouldNotConnectToProvider
|
||||||
*/
|
*/
|
||||||
public function connect(array $credentials = null): bool
|
public function connect(?array $credentials = null): bool
|
||||||
{
|
{
|
||||||
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account');
|
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account');
|
||||||
if (! $connect->ok()) {
|
if (! $connect->ok()) {
|
||||||
|
@ -59,7 +59,7 @@ public function data(array $input): array
|
|||||||
/**
|
/**
|
||||||
* @throws CouldNotConnectToProvider
|
* @throws CouldNotConnectToProvider
|
||||||
*/
|
*/
|
||||||
public function connect(array $credentials = null): bool
|
public function connect(?array $credentials = null): bool
|
||||||
{
|
{
|
||||||
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account');
|
$connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account');
|
||||||
if (! $connect->ok()) {
|
if (! $connect->ok()) {
|
||||||
|
@ -16,7 +16,7 @@ public function __construct(Server $server)
|
|||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function progress(int $percentage, string $step = null): Closure
|
protected function progress(int $percentage, ?string $step = null): Closure
|
||||||
{
|
{
|
||||||
return function () use ($percentage, $step) {
|
return function () use ($percentage, $step) {
|
||||||
$this->server->progress = $percentage;
|
$this->server->progress = $percentage;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\ServerTypes;
|
namespace App\ServerTypes;
|
||||||
|
|
||||||
|
use App\Enums\ServerStatus;
|
||||||
use App\Events\Broadcast;
|
use App\Events\Broadcast;
|
||||||
use App\Jobs\Installation\Initialize;
|
use App\Jobs\Installation\Initialize;
|
||||||
use App\Jobs\Installation\InstallCertbot;
|
use App\Jobs\Installation\InstallCertbot;
|
||||||
@ -79,7 +80,7 @@ public function install(): void
|
|||||||
|
|
||||||
$jobs[] = function () {
|
$jobs[] = function () {
|
||||||
$this->server->update([
|
$this->server->update([
|
||||||
'status' => 'ready',
|
'status' => ServerStatus::READY,
|
||||||
'progress' => 100,
|
'progress' => 100,
|
||||||
]);
|
]);
|
||||||
event(
|
event(
|
||||||
|
@ -47,7 +47,7 @@ public function create(
|
|||||||
/**
|
/**
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function delete(int $id, int $siteId = null): void
|
public function delete(int $id, ?int $siteId = null): void
|
||||||
{
|
{
|
||||||
$this->service->server->ssh()->exec(
|
$this->service->server->ssh()->exec(
|
||||||
new DeleteWorkerCommand($id),
|
new DeleteWorkerCommand($id),
|
||||||
@ -59,7 +59,7 @@ public function delete(int $id, int $siteId = null): void
|
|||||||
/**
|
/**
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function restart(int $id, int $siteId = null): void
|
public function restart(int $id, ?int $siteId = null): void
|
||||||
{
|
{
|
||||||
$this->service->server->ssh()->exec(
|
$this->service->server->ssh()->exec(
|
||||||
new RestartWorkerCommand($id),
|
new RestartWorkerCommand($id),
|
||||||
@ -71,7 +71,7 @@ public function restart(int $id, int $siteId = null): void
|
|||||||
/**
|
/**
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function stop(int $id, int $siteId = null): void
|
public function stop(int $id, ?int $siteId = null): void
|
||||||
{
|
{
|
||||||
$this->service->server->ssh()->exec(
|
$this->service->server->ssh()->exec(
|
||||||
new StopWorkerCommand($id),
|
new StopWorkerCommand($id),
|
||||||
@ -83,7 +83,7 @@ public function stop(int $id, int $siteId = null): void
|
|||||||
/**
|
/**
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function start(int $id, int $siteId = null): void
|
public function start(int $id, ?int $siteId = null): void
|
||||||
{
|
{
|
||||||
$this->service->server->ssh()->exec(
|
$this->service->server->ssh()->exec(
|
||||||
new StartWorkerCommand($id),
|
new StartWorkerCommand($id),
|
||||||
|
@ -2,14 +2,12 @@
|
|||||||
|
|
||||||
namespace App\SiteTypes;
|
namespace App\SiteTypes;
|
||||||
|
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteFeature;
|
||||||
use App\Events\Broadcast;
|
|
||||||
use App\Jobs\Site\CloneRepository;
|
use App\Jobs\Site\CloneRepository;
|
||||||
use App\Jobs\Site\ComposerInstall;
|
use App\Jobs\Site\ComposerInstall;
|
||||||
use App\Jobs\Site\CreateVHost;
|
use App\Jobs\Site\CreateVHost;
|
||||||
use App\Jobs\Site\DeployKey;
|
use App\Jobs\Site\DeployKey;
|
||||||
use Illuminate\Support\Facades\Bus;
|
use Illuminate\Support\Facades\Bus;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@ -20,12 +18,22 @@ public function language(): string
|
|||||||
return 'php';
|
return 'php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function supportedFeatures(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
SiteFeature::DEPLOYMENT,
|
||||||
|
SiteFeature::ENV,
|
||||||
|
SiteFeature::SSL,
|
||||||
|
SiteFeature::QUEUES,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function createValidationRules(array $input): array
|
public function createValidationRules(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'php_version' => [
|
'php_version' => [
|
||||||
'required',
|
'required',
|
||||||
'in:'.implode(',', $this->site->server->installedPHPVersions()),
|
Rule::in($this->site->server->installedPHPVersions()),
|
||||||
],
|
],
|
||||||
'source_control' => [
|
'source_control' => [
|
||||||
'required',
|
'required',
|
||||||
@ -53,7 +61,8 @@ public function createFields(array $input): array
|
|||||||
public function data(array $input): array
|
public function data(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'composer' => (bool) $input['composer'],
|
'composer' => isset($input['composer']) && $input['composer'],
|
||||||
|
'php_version' => $input['php_version'] ?? '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,33 +85,12 @@ function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$chain[] = function () {
|
$chain[] = function () {
|
||||||
$this->site->update([
|
$this->site->installationFinished();
|
||||||
'status' => SiteStatus::READY,
|
|
||||||
'progress' => 100,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-finished', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Bus::chain($chain)
|
Bus::chain($chain)
|
||||||
->catch(function (Throwable $e) {
|
->catch(function (Throwable $e) {
|
||||||
$this->site->update([
|
$this->site->installationFailed($e);
|
||||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-failed', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
Log::error('install-site-error', [
|
|
||||||
'error' => (string) $e,
|
|
||||||
]);
|
|
||||||
throw $e;
|
|
||||||
})
|
})
|
||||||
->onConnection('ssh-long')
|
->onConnection('ssh-long')
|
||||||
->dispatch();
|
->dispatch();
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
namespace App\SiteTypes;
|
namespace App\SiteTypes;
|
||||||
|
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteFeature;
|
||||||
use App\Events\Broadcast;
|
|
||||||
use App\Jobs\Site\CreateVHost;
|
use App\Jobs\Site\CreateVHost;
|
||||||
use App\Jobs\Site\InstallWordpress;
|
use App\Jobs\Site\InstallWordpress;
|
||||||
|
use App\Models\Database;
|
||||||
|
use App\Models\DatabaseUser;
|
||||||
use App\SSHCommands\Wordpress\UpdateWordpressCommand;
|
use App\SSHCommands\Wordpress\UpdateWordpressCommand;
|
||||||
|
use Closure;
|
||||||
use Illuminate\Support\Facades\Bus;
|
use Illuminate\Support\Facades\Bus;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Validation\Rule;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class Wordpress extends AbstractSiteType
|
class Wordpress extends AbstractSiteType
|
||||||
@ -18,94 +20,100 @@ public function language(): string
|
|||||||
return 'php';
|
return 'php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function supportedFeatures(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
SiteFeature::SSL,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function createValidationRules(array $input): array
|
public function createValidationRules(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'php_version' => [
|
||||||
|
'required',
|
||||||
|
Rule::in($this->site->server->installedPHPVersions()),
|
||||||
|
],
|
||||||
'title' => 'required',
|
'title' => 'required',
|
||||||
'username' => 'required',
|
'username' => 'required',
|
||||||
'password' => 'required',
|
'password' => 'required',
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'database' => 'required',
|
'database' => [
|
||||||
'database_user' => 'required',
|
'required',
|
||||||
|
Rule::unique('databases', 'name')->where(function ($query) {
|
||||||
|
return $query->where('server_id', $this->site->server_id);
|
||||||
|
}),
|
||||||
|
function (string $attribute, mixed $value, Closure $fail) {
|
||||||
|
if (! $this->site->server->database()) {
|
||||||
|
$fail(__('Database is not installed'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'database_user' => [
|
||||||
|
'required',
|
||||||
|
Rule::unique('database_users', 'username')->where(function ($query) {
|
||||||
|
return $query->where('server_id', $this->site->server_id);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
'database_password' => 'required',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createFields(array $input): array
|
public function createFields(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'web_directory' => $input['web_directory'] ?? '',
|
'web_directory' => '',
|
||||||
|
'php_version' => $input['php_version'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function data(array $input): array
|
public function data(array $input): array
|
||||||
{
|
{
|
||||||
$data = $this->site->type_data;
|
return [
|
||||||
$data['url'] = $this->site->url;
|
'url' => $this->site->url,
|
||||||
if (isset($input['title']) && $input['title']) {
|
'title' => $input['title'],
|
||||||
$data['title'] = $input['title'];
|
'username' => $input['username'],
|
||||||
}
|
'email' => $input['email'],
|
||||||
if (isset($input['username']) && $input['username']) {
|
'password' => $input['password'],
|
||||||
$data['username'] = $input['username'];
|
'database' => $input['database'],
|
||||||
}
|
'database_user' => $input['database_user'],
|
||||||
if (isset($input['email']) && $input['email']) {
|
'database_password' => $input['database_password'],
|
||||||
$data['email'] = $input['email'];
|
];
|
||||||
}
|
|
||||||
if (isset($input['password']) && $input['password']) {
|
|
||||||
$data['password'] = $input['password'];
|
|
||||||
}
|
|
||||||
if (isset($input['database']) && $input['database']) {
|
|
||||||
$data['database'] = $input['database'];
|
|
||||||
}
|
|
||||||
if (isset($input['database_user']) && $input['database_user']) {
|
|
||||||
$data['database_user'] = $input['database_user'];
|
|
||||||
}
|
|
||||||
if (isset($input['url']) && $input['url']) {
|
|
||||||
$data['url'] = $input['url'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function install(): void
|
public function install(): void
|
||||||
{
|
{
|
||||||
$chain = [
|
$chain = [
|
||||||
new CreateVHost($this->site),
|
new CreateVHost($this->site),
|
||||||
$this->progress(30),
|
$this->progress(15),
|
||||||
|
function () {
|
||||||
|
/** @var Database $database */
|
||||||
|
$database = $this->site->server->databases()->create([
|
||||||
|
'name' => $this->site->type_data['database'],
|
||||||
|
]);
|
||||||
|
$database->createOnServer('sync');
|
||||||
|
/** @var DatabaseUser $databaseUser */
|
||||||
|
$databaseUser = $this->site->server->databaseUsers()->create([
|
||||||
|
'username' => $this->site->type_data['database_user'],
|
||||||
|
'password' => $this->site->type_data['database_password'],
|
||||||
|
'databases' => [$this->site->type_data['database']],
|
||||||
|
]);
|
||||||
|
$databaseUser->createOnServer('sync');
|
||||||
|
$databaseUser->unlinkUser('sync');
|
||||||
|
$databaseUser->linkUser('sync');
|
||||||
|
},
|
||||||
|
$this->progress(50),
|
||||||
new InstallWordpress($this->site),
|
new InstallWordpress($this->site),
|
||||||
$this->progress(65),
|
$this->progress(75),
|
||||||
function () {
|
function () {
|
||||||
$this->site->php()?->restart();
|
$this->site->php()?->restart();
|
||||||
|
$this->site->installationFinished();
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
$chain[] = function () {
|
|
||||||
$this->site->update([
|
|
||||||
'status' => SiteStatus::READY,
|
|
||||||
'progress' => 100,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-finished', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
};
|
|
||||||
|
|
||||||
Bus::chain($chain)
|
Bus::chain($chain)
|
||||||
->catch(function (Throwable $e) {
|
->catch(function (Throwable $e) {
|
||||||
$this->site->update([
|
$this->site->installationFailed($e);
|
||||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-failed', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
Log::error('install-site-error', [
|
|
||||||
'error' => (string) $e,
|
|
||||||
]);
|
|
||||||
throw $e;
|
|
||||||
})
|
})
|
||||||
->onConnection('ssh-long')
|
->onConnection('ssh-long')
|
||||||
->dispatch();
|
->dispatch();
|
||||||
@ -139,32 +147,13 @@ function () {
|
|||||||
'update-wordpress',
|
'update-wordpress',
|
||||||
$this->site->id
|
$this->site->id
|
||||||
);
|
);
|
||||||
$this->site->update([
|
$this->site->installationFinished();
|
||||||
'status' => SiteStatus::READY,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-finished', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
Bus::chain($chain)
|
Bus::chain($chain)
|
||||||
->catch(function (Throwable $e) {
|
->catch(function (Throwable $e) {
|
||||||
$this->site->update([
|
$this->site->installationFailed($e);
|
||||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-failed', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
Log::error('install-site-error', [
|
|
||||||
'error' => (string) $e,
|
|
||||||
]);
|
|
||||||
throw $e;
|
|
||||||
})
|
})
|
||||||
->onConnection('ssh')
|
->onConnection('ssh')
|
||||||
->dispatch();
|
->dispatch();
|
||||||
|
@ -24,7 +24,7 @@ public function connect(): bool
|
|||||||
/**
|
/**
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function getRepo(string $repo = null): mixed
|
public function getRepo(?string $repo = null): mixed
|
||||||
{
|
{
|
||||||
$res = Http::withToken($this->sourceControl->access_token)
|
$res = Http::withToken($this->sourceControl->access_token)
|
||||||
->get($this->apiUrl."/repositories/$repo");
|
->get($this->apiUrl."/repositories/$repo");
|
||||||
@ -46,7 +46,7 @@ public function deployHook(string $repo, array $events, string $secret): array
|
|||||||
{
|
{
|
||||||
$response = Http::withToken($this->sourceControl->access_token)->post($this->apiUrl."/repositories/$repo/hooks", [
|
$response = Http::withToken($this->sourceControl->access_token)->post($this->apiUrl."/repositories/$repo/hooks", [
|
||||||
'description' => 'deploy',
|
'description' => 'deploy',
|
||||||
'url' => url('/git-hooks?secret='.$secret),
|
'url' => url('/api/git-hooks?secret='.$secret),
|
||||||
'events' => [
|
'events' => [
|
||||||
'repo:'.implode(',', $events),
|
'repo:'.implode(',', $events),
|
||||||
],
|
],
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\SourceControlProviders;
|
|
||||||
|
|
||||||
class Custom extends AbstractSourceControlProvider
|
|
||||||
{
|
|
||||||
public function connect(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRepo(string $repo = null): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fullRepoUrl(string $repo, string $key): string
|
|
||||||
{
|
|
||||||
return $repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deployHook(string $repo, array $events, string $secret): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroyHook(string $repo, string $hookId): void
|
|
||||||
{
|
|
||||||
// TODO: Implement destroyHook() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLastCommit(string $repo, string $branch): ?array
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deployKey(string $title, string $repo, string $key): void
|
|
||||||
{
|
|
||||||
// TODO: Implement deployKey() method.
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,7 +25,7 @@ public function connect(): bool
|
|||||||
/**
|
/**
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function getRepo(string $repo = null): mixed
|
public function getRepo(?string $repo = null): mixed
|
||||||
{
|
{
|
||||||
if ($repo) {
|
if ($repo) {
|
||||||
$url = $this->apiUrl.'/repos/'.$repo;
|
$url = $this->apiUrl.'/repos/'.$repo;
|
||||||
@ -59,7 +59,7 @@ public function deployHook(string $repo, array $events, string $secret): array
|
|||||||
'name' => 'web',
|
'name' => 'web',
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
'config' => [
|
'config' => [
|
||||||
'url' => url('/git-hooks?secret='.$secret),
|
'url' => url('/api/git-hooks?secret='.$secret),
|
||||||
'content_type' => 'json',
|
'content_type' => 'json',
|
||||||
],
|
],
|
||||||
'active' => true,
|
'active' => true,
|
||||||
|
@ -10,12 +10,14 @@
|
|||||||
|
|
||||||
class Gitlab extends AbstractSourceControlProvider
|
class Gitlab extends AbstractSourceControlProvider
|
||||||
{
|
{
|
||||||
protected string $apiUrl = 'https://gitlab.com/api/v4';
|
protected string $defaultApiHost = 'https://gitlab.com/';
|
||||||
|
|
||||||
|
protected string $apiVersion = 'api/v4';
|
||||||
|
|
||||||
public function connect(): bool
|
public function connect(): bool
|
||||||
{
|
{
|
||||||
$res = Http::withToken($this->sourceControl->access_token)
|
$res = Http::withToken($this->sourceControl->access_token)
|
||||||
->get($this->apiUrl.'/projects');
|
->get($this->getApiUrl().'/projects');
|
||||||
|
|
||||||
return $res->successful();
|
return $res->successful();
|
||||||
}
|
}
|
||||||
@ -23,11 +25,11 @@ public function connect(): bool
|
|||||||
/**
|
/**
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function getRepo(string $repo = null): mixed
|
public function getRepo(?string $repo = null): mixed
|
||||||
{
|
{
|
||||||
$repository = $repo ? urlencode($repo) : null;
|
$repository = $repo ? urlencode($repo) : null;
|
||||||
$res = Http::withToken($this->sourceControl->access_token)
|
$res = Http::withToken($this->sourceControl->access_token)
|
||||||
->get($this->apiUrl.'/projects/'.$repository.'/repository/commits');
|
->get($this->getApiUrl().'/projects/'.$repository.'/repository/commits');
|
||||||
|
|
||||||
$this->handleResponseErrors($res, $repo);
|
$this->handleResponseErrors($res, $repo);
|
||||||
|
|
||||||
@ -36,7 +38,9 @@ public function getRepo(string $repo = null): mixed
|
|||||||
|
|
||||||
public function fullRepoUrl(string $repo, string $key): string
|
public function fullRepoUrl(string $repo, string $key): string
|
||||||
{
|
{
|
||||||
return sprintf('git@gitlab.com-%s:%s.git', $key, $repo);
|
$host = parse_url($this->getApiUrl())['host'];
|
||||||
|
|
||||||
|
return sprintf('git@%s-%s:%s.git', $host, $key, $repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,10 +50,10 @@ public function deployHook(string $repo, array $events, string $secret): array
|
|||||||
{
|
{
|
||||||
$repository = urlencode($repo);
|
$repository = urlencode($repo);
|
||||||
$response = Http::withToken($this->sourceControl->access_token)->post(
|
$response = Http::withToken($this->sourceControl->access_token)->post(
|
||||||
$this->apiUrl.'/projects/'.$repository.'/hooks',
|
$this->getApiUrl().'/projects/'.$repository.'/hooks',
|
||||||
[
|
[
|
||||||
'description' => 'deploy',
|
'description' => 'deploy',
|
||||||
'url' => url('/git-hooks?secret='.$secret),
|
'url' => url('/api/git-hooks?secret='.$secret),
|
||||||
'push_events' => in_array('push', $events),
|
'push_events' => in_array('push', $events),
|
||||||
'issues_events' => false,
|
'issues_events' => false,
|
||||||
'job_events' => false,
|
'job_events' => false,
|
||||||
@ -81,7 +85,7 @@ public function destroyHook(string $repo, string $hookId): void
|
|||||||
{
|
{
|
||||||
$repository = urlencode($repo);
|
$repository = urlencode($repo);
|
||||||
$response = Http::withToken($this->sourceControl->access_token)->delete(
|
$response = Http::withToken($this->sourceControl->access_token)->delete(
|
||||||
$this->apiUrl.'/projects/'.$repository.'/hooks/'.$hookId
|
$this->getApiUrl().'/projects/'.$repository.'/hooks/'.$hookId
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($response->status() != 204) {
|
if ($response->status() != 204) {
|
||||||
@ -96,7 +100,7 @@ public function getLastCommit(string $repo, string $branch): ?array
|
|||||||
{
|
{
|
||||||
$repository = urlencode($repo);
|
$repository = urlencode($repo);
|
||||||
$res = Http::withToken($this->sourceControl->access_token)
|
$res = Http::withToken($this->sourceControl->access_token)
|
||||||
->get($this->apiUrl.'/projects/'.$repository.'/repository/commits?ref_name='.$branch);
|
->get($this->getApiUrl().'/projects/'.$repository.'/repository/commits?ref_name='.$branch);
|
||||||
|
|
||||||
$this->handleResponseErrors($res, $repo);
|
$this->handleResponseErrors($res, $repo);
|
||||||
|
|
||||||
@ -123,7 +127,7 @@ public function deployKey(string $title, string $repo, string $key): void
|
|||||||
{
|
{
|
||||||
$repository = urlencode($repo);
|
$repository = urlencode($repo);
|
||||||
$response = Http::withToken($this->sourceControl->access_token)->post(
|
$response = Http::withToken($this->sourceControl->access_token)->post(
|
||||||
$this->apiUrl.'/projects/'.$repository.'/deploy_keys',
|
$this->getApiUrl().'/projects/'.$repository.'/deploy_keys',
|
||||||
[
|
[
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'key' => $key,
|
'key' => $key,
|
||||||
@ -135,4 +139,13 @@ public function deployKey(string $title, string $repo, string $key): void
|
|||||||
throw new FailedToDeployGitKey(json_decode($response->body())->message);
|
throw new FailedToDeployGitKey(json_decode($response->body())->message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getApiUrl(): string
|
||||||
|
{
|
||||||
|
$host = $this->sourceControl->url === null
|
||||||
|
? $this->defaultApiHost
|
||||||
|
: $this->sourceControl->url;
|
||||||
|
|
||||||
|
return $host.$this->apiVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,20 @@ class Dropbox extends AbstractStorageProvider
|
|||||||
{
|
{
|
||||||
protected string $apiUrl = 'https://api.dropboxapi.com/2';
|
protected string $apiUrl = 'https://api.dropboxapi.com/2';
|
||||||
|
|
||||||
|
public function validationRules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'token' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function credentialData(array $input): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'token' => $input['token'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function connect(): bool
|
public function connect(): bool
|
||||||
{
|
{
|
||||||
$res = Http::withToken($this->storageProvider->credentials['token'])
|
$res = Http::withToken($this->storageProvider->credentials['token'])
|
||||||
|
129
app/StorageProviders/FTP.php
Normal file
129
app/StorageProviders/FTP.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\StorageProviders;
|
||||||
|
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\SSHCommands\Storage\DownloadFromFTPCommand;
|
||||||
|
use App\SSHCommands\Storage\UploadToFTPCommand;
|
||||||
|
use FTP\Connection;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class FTP extends AbstractStorageProvider
|
||||||
|
{
|
||||||
|
public function validationRules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'host' => 'required',
|
||||||
|
'port' => 'required|numeric',
|
||||||
|
'path' => 'required',
|
||||||
|
'username' => 'required',
|
||||||
|
'password' => 'required',
|
||||||
|
'ssl' => 'required',
|
||||||
|
'passive' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function credentialData(array $input): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'host' => $input['host'],
|
||||||
|
'port' => $input['port'],
|
||||||
|
'path' => $input['path'],
|
||||||
|
'username' => $input['username'],
|
||||||
|
'password' => $input['password'],
|
||||||
|
'ssl' => (bool) $input['ssl'],
|
||||||
|
'passive' => (bool) $input['passive'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect(): bool
|
||||||
|
{
|
||||||
|
$connection = $this->connection();
|
||||||
|
|
||||||
|
$isConnected = $connection && $this->login($connection);
|
||||||
|
|
||||||
|
if ($isConnected) {
|
||||||
|
ftp_close($connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $isConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function upload(Server $server, string $src, string $dest): array
|
||||||
|
{
|
||||||
|
$server->ssh()->exec(
|
||||||
|
new UploadToFTPCommand(
|
||||||
|
$src,
|
||||||
|
$this->storageProvider->credentials['path'].'/'.$dest,
|
||||||
|
$this->storageProvider->credentials['host'],
|
||||||
|
$this->storageProvider->credentials['port'],
|
||||||
|
$this->storageProvider->credentials['username'],
|
||||||
|
$this->storageProvider->credentials['password'],
|
||||||
|
$this->storageProvider->credentials['ssl'],
|
||||||
|
$this->storageProvider->credentials['passive'],
|
||||||
|
),
|
||||||
|
'upload-to-ftp'
|
||||||
|
);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'size' => null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function download(Server $server, string $src, string $dest): void
|
||||||
|
{
|
||||||
|
$server->ssh()->exec(
|
||||||
|
new DownloadFromFTPCommand(
|
||||||
|
$this->storageProvider->credentials['path'].'/'.$src,
|
||||||
|
$dest,
|
||||||
|
$this->storageProvider->credentials['host'],
|
||||||
|
$this->storageProvider->credentials['port'],
|
||||||
|
$this->storageProvider->credentials['username'],
|
||||||
|
$this->storageProvider->credentials['password'],
|
||||||
|
$this->storageProvider->credentials['ssl'],
|
||||||
|
$this->storageProvider->credentials['passive'],
|
||||||
|
),
|
||||||
|
'download-from-ftp'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(array $paths): void
|
||||||
|
{
|
||||||
|
$connection = $this->connection();
|
||||||
|
|
||||||
|
if ($connection && $this->login($connection)) {
|
||||||
|
if ($this->storageProvider->credentials['passive']) {
|
||||||
|
ftp_pasv($connection, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
ftp_delete($connection, $this->storageProvider->credentials['path'].'/'.$path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ftp_close($connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function connection(): bool|Connection
|
||||||
|
{
|
||||||
|
$credentials = $this->storageProvider->credentials;
|
||||||
|
if ($credentials['ssl']) {
|
||||||
|
return ftp_ssl_connect($credentials['host'], $credentials['port'], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ftp_connect($credentials['host'], $credentials['port'], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function login(Connection $connection): bool
|
||||||
|
{
|
||||||
|
$credentials = $this->storageProvider->credentials;
|
||||||
|
|
||||||
|
return ftp_login($connection, $credentials['username'], $credentials['password']);
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ class SSHFake
|
|||||||
|
|
||||||
protected string $output = '';
|
protected string $output = '';
|
||||||
|
|
||||||
public function init(Server $server, string $asUser = null): self
|
public function init(Server $server, ?string $asUser = null): self
|
||||||
{
|
{
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ public function assertExecuted(array|string $commands): void
|
|||||||
PHPUnit::assertTrue(true, $allExecuted);
|
PHPUnit::assertTrue(true, $allExecuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exec(string|array|SSHCommand $commands, string $log = '', int $siteId = null): string
|
public function exec(string|array|SSHCommand $commands, string $log = '', ?int $siteId = null): string
|
||||||
{
|
{
|
||||||
if (! is_array($commands)) {
|
if (! is_array($commands)) {
|
||||||
$commands = [$commands];
|
$commands = [$commands];
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
"laravel/tinker": "^2.8",
|
"laravel/tinker": "^2.8",
|
||||||
"livewire/livewire": "^2.12",
|
"livewire/livewire": "^2.12",
|
||||||
"phpseclib/phpseclib": "~3.0",
|
"phpseclib/phpseclib": "~3.0",
|
||||||
"pusher/pusher-php-server": "^7.2"
|
"opcodesio/log-viewer": "^2.5",
|
||||||
|
"ext-ftp": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
@ -24,7 +25,6 @@
|
|||||||
"laravel/sail": "^1.18",
|
"laravel/sail": "^1.18",
|
||||||
"mockery/mockery": "^1.4.4",
|
"mockery/mockery": "^1.4.4",
|
||||||
"nunomaduro/collision": "^7.0",
|
"nunomaduro/collision": "^7.0",
|
||||||
"opcodesio/log-viewer": "^2.5",
|
|
||||||
"phpunit/phpunit": "^10.0",
|
"phpunit/phpunit": "^10.0",
|
||||||
"spatie/laravel-ignition": "^2.0"
|
"spatie/laravel-ignition": "^2.0"
|
||||||
},
|
},
|
||||||
|
2336
composer.lock
generated
2336
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -25,19 +25,20 @@
|
|||||||
use App\ServiceHandlers\Webserver\Nginx;
|
use App\ServiceHandlers\Webserver\Nginx;
|
||||||
use App\SiteTypes\Laravel;
|
use App\SiteTypes\Laravel;
|
||||||
use App\SiteTypes\PHPSite;
|
use App\SiteTypes\PHPSite;
|
||||||
|
use App\SiteTypes\Wordpress;
|
||||||
use App\SourceControlProviders\Bitbucket;
|
use App\SourceControlProviders\Bitbucket;
|
||||||
use App\SourceControlProviders\Custom;
|
|
||||||
use App\SourceControlProviders\Github;
|
use App\SourceControlProviders\Github;
|
||||||
use App\SourceControlProviders\Gitlab;
|
use App\SourceControlProviders\Gitlab;
|
||||||
use App\StorageProviders\Dropbox;
|
use App\StorageProviders\Dropbox;
|
||||||
|
use App\StorageProviders\FTP;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
/*
|
/*
|
||||||
* SSH
|
* SSH
|
||||||
*/
|
*/
|
||||||
'ssh_user' => env('SSH_USER', 'vito'),
|
'ssh_user' => env('SSH_USER', 'vito'),
|
||||||
'ssh_public_key_name' => env('SSH_PUBLIC_KEY_NAME'),
|
'ssh_public_key_name' => env('SSH_PUBLIC_KEY_NAME', 'ssh-public.key'),
|
||||||
'ssh_private_key_name' => env('SSH_PRIVATE_KEY_NAME'),
|
'ssh_private_key_name' => env('SSH_PRIVATE_KEY_NAME', 'ssh-private.pem'),
|
||||||
'logs_disk' => env('SERVER_LOGS_DISK', 'server-logs-local'),
|
'logs_disk' => env('SERVER_LOGS_DISK', 'server-logs-local'),
|
||||||
'key_pairs_disk' => env('KEY_PAIRS_DISK', 'key-pairs-local'),
|
'key_pairs_disk' => env('KEY_PAIRS_DISK', 'key-pairs-local'),
|
||||||
|
|
||||||
@ -262,12 +263,12 @@
|
|||||||
'site_types' => [
|
'site_types' => [
|
||||||
\App\Enums\SiteType::PHP,
|
\App\Enums\SiteType::PHP,
|
||||||
\App\Enums\SiteType::LARAVEL,
|
\App\Enums\SiteType::LARAVEL,
|
||||||
// \App\Enums\SiteType::WORDPRESS,
|
\App\Enums\SiteType::WORDPRESS,
|
||||||
],
|
],
|
||||||
'site_types_class' => [
|
'site_types_class' => [
|
||||||
\App\Enums\SiteType::PHP => PHPSite::class,
|
\App\Enums\SiteType::PHP => PHPSite::class,
|
||||||
\App\Enums\SiteType::LARAVEL => Laravel::class,
|
\App\Enums\SiteType::LARAVEL => Laravel::class,
|
||||||
// \App\Enums\SiteType::WORDPRESS => Wordpress::class,
|
\App\Enums\SiteType::WORDPRESS => Wordpress::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -283,7 +284,6 @@
|
|||||||
'github' => Github::class,
|
'github' => Github::class,
|
||||||
'gitlab' => Gitlab::class,
|
'gitlab' => Gitlab::class,
|
||||||
'bitbucket' => Bitbucket::class,
|
'bitbucket' => Bitbucket::class,
|
||||||
'custom' => Custom::class,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -291,11 +291,12 @@
|
|||||||
*/
|
*/
|
||||||
'php_extensions' => [
|
'php_extensions' => [
|
||||||
'imagick',
|
'imagick',
|
||||||
'geoip',
|
|
||||||
'exif',
|
'exif',
|
||||||
'gmagick',
|
'gmagick',
|
||||||
'gmp',
|
'gmp',
|
||||||
'intl',
|
'intl',
|
||||||
|
'sqlite3',
|
||||||
|
'opcache',
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -323,7 +324,6 @@
|
|||||||
'https' => 443,
|
'https' => 443,
|
||||||
'mysql' => 3306,
|
'mysql' => 3306,
|
||||||
'ftp' => 21,
|
'ftp' => 21,
|
||||||
'phpmyadmin' => 54331,
|
|
||||||
'tcp' => '',
|
'tcp' => '',
|
||||||
'udp' => '',
|
'udp' => '',
|
||||||
],
|
],
|
||||||
@ -355,8 +355,10 @@
|
|||||||
*/
|
*/
|
||||||
'storage_providers' => [
|
'storage_providers' => [
|
||||||
'dropbox',
|
'dropbox',
|
||||||
|
'ftp',
|
||||||
],
|
],
|
||||||
'storage_providers_class' => [
|
'storage_providers_class' => [
|
||||||
'dropbox' => Dropbox::class,
|
'dropbox' => Dropbox::class,
|
||||||
|
'ftp' => FTP::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
217
config/log-viewer.php
Normal file
217
config/log-viewer.php
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Opcodes\LogViewer\Level;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer can be disabled, so it's no longer accessible via browser.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'enabled' => env('LOG_VIEWER_ENABLED', true),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer Domain
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| You may change the domain where Log Viewer should be active.
|
||||||
|
| If the domain is empty, all domains will be valid.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'route_domain' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer Route
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer will be available under this URL.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'route_path' => 'log-viewer',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Back to system URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| When set, displays a link to easily get back to this URL.
|
||||||
|
| Set to `null` to hide this link.
|
||||||
|
|
|
||||||
|
| Optional label to display for the above URL.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'back_to_system_url' => config('app.url', null),
|
||||||
|
|
||||||
|
'back_to_system_label' => null, // Displayed by default: "Back to {{ app.name }}"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer time zone.
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| The time zone in which to display the times in the UI. Defaults to
|
||||||
|
| the application's timezone defined in config/app.php.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'timezone' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer route middleware.
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Optional middleware to use when loading the initial Log Viewer page.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => [
|
||||||
|
'web',
|
||||||
|
\Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,
|
||||||
|
'auth',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer API middleware.
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Optional middleware to use on every API request. The same API is also
|
||||||
|
| used from within the Log Viewer user interface.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'api_middleware' => [
|
||||||
|
\Opcodes\LogViewer\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
|
||||||
|
\Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer Remote hosts.
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Viewer supports viewing Laravel logs from remote hosts. They must
|
||||||
|
| be running Log Viewer as well. Below you can define the hosts you
|
||||||
|
| would like to show in this Log Viewer instance.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'hosts' => [
|
||||||
|
'local' => [
|
||||||
|
'name' => ucfirst(env('APP_ENV', 'local')),
|
||||||
|
],
|
||||||
|
|
||||||
|
// 'staging' => [
|
||||||
|
// 'name' => 'Staging',
|
||||||
|
// 'host' => 'https://staging.example.com/log-viewer',
|
||||||
|
// 'auth' => [ // Example of HTTP Basic auth
|
||||||
|
// 'username' => 'username',
|
||||||
|
// 'password' => 'password',
|
||||||
|
// ],
|
||||||
|
// ],
|
||||||
|
//
|
||||||
|
// 'production' => [
|
||||||
|
// 'name' => 'Production',
|
||||||
|
// 'host' => 'https://example.com/log-viewer',
|
||||||
|
// 'auth' => [ // Example of Bearer token auth
|
||||||
|
// 'token' => env('LOG_VIEWER_PRODUCTION_TOKEN'),
|
||||||
|
// ],
|
||||||
|
// 'headers' => [
|
||||||
|
// 'X-Foo' => 'Bar',
|
||||||
|
// ],
|
||||||
|
// ],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Include file patterns
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'include_files' => [
|
||||||
|
'*.log',
|
||||||
|
'**/*.log',
|
||||||
|
// '/absolute/paths/supported',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Exclude file patterns.
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| This will take precedence over included files.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'exclude_files' => [
|
||||||
|
// 'my_secret.log'
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Shorter stack trace filters.
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Lines containing any of these strings will be excluded from the full log.
|
||||||
|
| This setting is only active when the function is enabled via the user interface.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'shorter_stack_trace_excludes' => [
|
||||||
|
'/vendor/symfony/',
|
||||||
|
'/vendor/laravel/framework/',
|
||||||
|
'/vendor/barryvdh/laravel-debugbar/',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log matching patterns
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Regexes for matching log files
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'patterns' => [
|
||||||
|
'laravel' => [
|
||||||
|
'log_matching_regex' => '/^\[(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.?(\d{6}([\+-]\d\d:\d\d)?)?)\].*/',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This pattern, used for processing Laravel logs, returns these results:
|
||||||
|
* $matches[0] - the full log line being tested.
|
||||||
|
* $matches[1] - full timestamp between the square brackets (includes microseconds and timezone offset)
|
||||||
|
* $matches[2] - timestamp microseconds, if available
|
||||||
|
* $matches[3] - timestamp timezone offset, if available
|
||||||
|
* $matches[4] - contents between timestamp and the severity level
|
||||||
|
* $matches[5] - environment (local, production, etc)
|
||||||
|
* $matches[6] - log severity (info, debug, error, etc)
|
||||||
|
* $matches[7] - the log text, the rest of the text.
|
||||||
|
*/
|
||||||
|
'log_parsing_regex' => '/^\[(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.?(\d{6}([\+-]\d\d:\d\d)?)?)\](.*?(\w+)\.|.*?)('
|
||||||
|
.implode('|', array_filter(Level::caseValues()))
|
||||||
|
.')?: (.*?)( in [\/].*?:[0-9]+)?$/is',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cache driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cache driver to use for storing the log indices. Indices are used to speed up
|
||||||
|
| log navigation. Defaults to your application's default cache driver.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'cache_driver' => env('LOG_VIEWER_CACHE_DRIVER', null),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Chunk size when scanning log files lazily
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| The size in MB of files to scan before updating the progress bar when searching across all files.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'lazy_scan_chunk_size_in_mb' => 50,
|
||||||
|
];
|
@ -13,7 +13,7 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'default' => env('QUEUE_CONNECTION', 'sync'),
|
'default' => env('QUEUE_CONNECTION', 'default'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -139,85 +139,125 @@
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
'images' => [
|
'images' => [
|
||||||
'us-east-1' => [
|
'af-south-1' => [
|
||||||
'ubuntu_18' => 'ami-0279c3b3186e54acd',
|
'ubuntu_20' => 'ami-03684d4c2541e5333',
|
||||||
'ubuntu_20' => 'ami-083654bd07b5da81d',
|
'ubuntu_22' => 'ami-05759acc7d8973892',
|
||||||
],
|
|
||||||
'us-east-2' => [
|
|
||||||
'ubuntu_18' => 'ami-020db2c14939a8efb',
|
|
||||||
'ubuntu_20' => 'ami-0629230e074c580f2',
|
|
||||||
],
|
|
||||||
'us-west-1' => [
|
|
||||||
'ubuntu_18' => 'ami-083f68207d3376798',
|
|
||||||
'ubuntu_20' => 'ami-053ac55bdcfe96e85',
|
|
||||||
],
|
|
||||||
'us-west-2' => [
|
|
||||||
'ubuntu_18' => 'ami-09889d8d54f9e0a0e',
|
|
||||||
'ubuntu_20' => 'ami-036d46416a34a611c',
|
|
||||||
],
|
],
|
||||||
'ap-east-1' => [
|
'ap-east-1' => [
|
||||||
'ubuntu_18' => 'ami-032c0a4bd39a5772c',
|
'ubuntu_20' => 'ami-0b19a97bf326b4931',
|
||||||
'ubuntu_20' => 'ami-0a9c1cc3697104990',
|
'ubuntu_22' => 'ami-03490b1b7425e5fe3',
|
||||||
],
|
|
||||||
'ap-south-1' => [
|
|
||||||
'ubuntu_18' => 'ami-00782a7608c7fc226',
|
|
||||||
'ubuntu_20' => 'ami-0567e0d2b4b2169ae',
|
|
||||||
],
|
],
|
||||||
'ap-northeast-1' => [
|
'ap-northeast-1' => [
|
||||||
'ubuntu_18' => 'ami-085e9421f80dbe728',
|
'ubuntu_20' => 'ami-0e25df74d27e028e6',
|
||||||
'ubuntu_20' => 'ami-036d0684fc96830ca',
|
'ubuntu_22' => 'ami-09a81b370b76de6a2',
|
||||||
],
|
],
|
||||||
'ap-northeast-2' => [
|
'ap-northeast-2' => [
|
||||||
'ubuntu_18' => 'ami-0252a84eb1d66c2a0',
|
'ubuntu_20' => 'ami-003a709e1e4ce3729',
|
||||||
'ubuntu_20' => 'ami-0f8b8babb98cc66d0',
|
'ubuntu_22' => 'ami-086cae3329a3f7d75',
|
||||||
|
],
|
||||||
|
'ap-northeast-3' => [
|
||||||
|
'ubuntu_20' => 'ami-06c1367bd83de7d47',
|
||||||
|
'ubuntu_22' => 'ami-0690c54203f5f67da',
|
||||||
|
],
|
||||||
|
'ap-south-1' => [
|
||||||
|
'ubuntu_20' => 'ami-0b88997c830e88c76',
|
||||||
|
'ubuntu_22' => 'ami-0287a05f0ef0e9d9a',
|
||||||
|
],
|
||||||
|
'ap-south-2' => [
|
||||||
|
'ubuntu_20' => 'ami-049e2ae605332dba6',
|
||||||
|
'ubuntu_22' => 'ami-06fe902e167e67d33',
|
||||||
],
|
],
|
||||||
'ap-southeast-1' => [
|
'ap-southeast-1' => [
|
||||||
'ubuntu_18' => 'ami-0907c2c44ea451f84',
|
'ubuntu_20' => 'ami-0a6461ddb52e9db63',
|
||||||
'ubuntu_20' => 'ami-0fed77069cd5a6d6c',
|
'ubuntu_22' => 'ami-078c1149d8ad719a7',
|
||||||
],
|
],
|
||||||
'ap-southeast-2' => [
|
'ap-southeast-2' => [
|
||||||
'ubuntu_18' => 'ami-00abf0511a7f4cee5',
|
'ubuntu_20' => 'ami-0a9fb81cc3289919c',
|
||||||
'ubuntu_20' => 'ami-0bf8b986de7e3c7ce',
|
'ubuntu_22' => 'ami-0df4b2961410d4cff',
|
||||||
|
],
|
||||||
|
'ap-southeast-3' => [
|
||||||
|
'ubuntu_20' => 'ami-05ee5bed682a3fff0',
|
||||||
|
'ubuntu_22' => 'ami-0fb6d1fdeeea10488',
|
||||||
|
],
|
||||||
|
'ap-southeast-4' => [
|
||||||
|
'ubuntu_20' => 'ami-02f9759882b112414',
|
||||||
|
'ubuntu_22' => 'ami-043a030d3eeabec75',
|
||||||
],
|
],
|
||||||
'ca-central-1' => [
|
'ca-central-1' => [
|
||||||
'ubuntu_18' => 'ami-0e471deaa43652c4a',
|
'ubuntu_20' => 'ami-0daaea212e620de87',
|
||||||
'ubuntu_20' => 'ami-0bb84e7329f4fa1f7',
|
'ubuntu_22' => 'ami-06873c81b882339ac',
|
||||||
|
],
|
||||||
|
'cn-north-1' => [
|
||||||
|
'ubuntu_20' => 'ami-0c8bcac1fe3389a72',
|
||||||
|
'ubuntu_22' => 'ami-0728a1a4cc9e07753',
|
||||||
|
],
|
||||||
|
'cn-northwest-1' => [
|
||||||
|
'ubuntu_20' => 'ami-0415bfb3ea62e17c0',
|
||||||
|
'ubuntu_22' => 'ami-05529cf859783e600',
|
||||||
],
|
],
|
||||||
'eu-central-1' => [
|
'eu-central-1' => [
|
||||||
'ubuntu_18' => 'ami-00d5e377dd7fad751',
|
'ubuntu_20' => 'ami-0b369586722023326',
|
||||||
'ubuntu_20' => 'ami-0a49b025fffbbdac6',
|
'ubuntu_22' => 'ami-06dd92ecc74fdfb36',
|
||||||
],
|
],
|
||||||
'eu-west-1' => [
|
'eu-central-2' => [
|
||||||
'ubuntu_18' => 'ami-095b735dce49535b5',
|
'ubuntu_20' => 'ami-070c78d5ed65f11c8',
|
||||||
'ubuntu_20' => 'ami-08edbb0e85d6a0a07',
|
'ubuntu_22' => 'ami-07cf963e6321c9e6a',
|
||||||
],
|
|
||||||
'eu-west-2' => [
|
|
||||||
'ubuntu_18' => 'ami-008485ca60c91a0f3',
|
|
||||||
'ubuntu_20' => 'ami-0fdf70ed5c34c5f52',
|
|
||||||
],
|
|
||||||
'eu-west-3' => [
|
|
||||||
'ubuntu_18' => 'ami-0df7d9cc2767d16cd',
|
|
||||||
'ubuntu_20' => 'ami-06d79c60d7454e2af',
|
|
||||||
],
|
|
||||||
'eu-south-1' => [
|
|
||||||
'ubuntu_18' => 'ami-09f165dd6bd167be5',
|
|
||||||
'ubuntu_20' => 'ami-0f8ce9c417115413d',
|
|
||||||
],
|
],
|
||||||
'eu-north-1' => [
|
'eu-north-1' => [
|
||||||
'ubuntu_18' => 'ami-038904f9024f34a0c',
|
'ubuntu_20' => 'ami-0c5863072fc83557e',
|
||||||
'ubuntu_20' => 'ami-0bd9c26722573e69b',
|
'ubuntu_22' => 'ami-0fe8bec493a81c7da',
|
||||||
|
],
|
||||||
|
'eu-south-1' => [
|
||||||
|
'ubuntu_20' => 'ami-0966ff128f1497260',
|
||||||
|
'ubuntu_22' => 'ami-0b03947fd0ce0eed2',
|
||||||
|
],
|
||||||
|
'eu-south-2' => [
|
||||||
|
'ubuntu_20' => 'ami-087296a5b46cb95ce',
|
||||||
|
'ubuntu_22' => 'ami-03486abd2962c176f',
|
||||||
|
],
|
||||||
|
'eu-west-1' => [
|
||||||
|
'ubuntu_20' => 'ami-0e3e7f215a53e2a86',
|
||||||
|
'ubuntu_22' => 'ami-0694d931cee176e7d',
|
||||||
|
],
|
||||||
|
'eu-west-2' => [
|
||||||
|
'ubuntu_20' => 'ami-0b22eee5ba6bb6772',
|
||||||
|
'ubuntu_22' => 'ami-0505148b3591e4c07',
|
||||||
|
],
|
||||||
|
'eu-west-3' => [
|
||||||
|
'ubuntu_20' => 'ami-0f14fa1f9c69f4111',
|
||||||
|
'ubuntu_22' => 'ami-00983e8a26e4c9bd9',
|
||||||
|
],
|
||||||
|
'il-central-1' => [
|
||||||
|
'ubuntu_20' => 'ami-0703881563bf5fab7',
|
||||||
|
'ubuntu_22' => 'ami-03869c813f5a2e20c',
|
||||||
|
],
|
||||||
|
'me-central-1' => [
|
||||||
|
'ubuntu_20' => 'ami-04a5bde3b044c7c21',
|
||||||
|
'ubuntu_22' => 'ami-02168d82d5c12118f',
|
||||||
],
|
],
|
||||||
'me-south-1' => [
|
'me-south-1' => [
|
||||||
'ubuntu_18' => 'ami-0ef669c57b73af73b',
|
'ubuntu_20' => 'ami-0165b692f5714e330',
|
||||||
'ubuntu_20' => 'ami-0b4946d7420c44be4',
|
'ubuntu_22' => 'ami-0f8d2a6080634ee69',
|
||||||
],
|
],
|
||||||
'sa-east-1' => [
|
'sa-east-1' => [
|
||||||
'ubuntu_18' => 'ami-0ed2b3edeb28afa59',
|
'ubuntu_20' => 'ami-095ca107fb46b81e6',
|
||||||
'ubuntu_20' => 'ami-0e66f5495b4efdd0f',
|
'ubuntu_22' => 'ami-0b6c2d49148000cd5',
|
||||||
],
|
],
|
||||||
'af-south-1' => [
|
'us-east-1' => [
|
||||||
'ubuntu_18' => 'ami-0191bb2cf509687ee',
|
'ubuntu_20' => 'ami-0fe0238291c8e3f07',
|
||||||
'ubuntu_20' => 'ami-0ff86122fd4ad7208',
|
'ubuntu_22' => 'ami-0fc5d935ebf8bc3bc',
|
||||||
|
],
|
||||||
|
'us-east-2' => [
|
||||||
|
'ubuntu_20' => 'ami-0b6968e5c7117349a',
|
||||||
|
'ubuntu_22' => 'ami-0e83be366243f524a',
|
||||||
|
],
|
||||||
|
'us-west-1' => [
|
||||||
|
'ubuntu_20' => 'ami-092efbcc9a2d2be8a',
|
||||||
|
'ubuntu_22' => 'ami-0cbd40f694b804622',
|
||||||
|
],
|
||||||
|
'us-west-2' => [
|
||||||
|
'ubuntu_20' => 'ami-0a55cdf919d10eac9',
|
||||||
|
'ubuntu_22' => 'ami-0efcece6bed30fd98',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
29
database/factories/GitHookFactory.php
Normal file
29
database/factories/GitHookFactory.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\GitHook;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Models\SourceControl;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
class GitHookFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = GitHook::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'secret' => $this->faker->word(),
|
||||||
|
'events' => $this->faker->words(),
|
||||||
|
'actions' => $this->faker->words(),
|
||||||
|
'hook_id' => $this->faker->word(),
|
||||||
|
'hook_response' => $this->faker->words(),
|
||||||
|
'created_at' => Carbon::now(),
|
||||||
|
'updated_at' => Carbon::now(),
|
||||||
|
'site_id' => Site::factory(),
|
||||||
|
'source_control_id' => SourceControl::factory(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -13,8 +13,34 @@ class SourceControlFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'provider' => $this->faker->randomElement(\App\Enums\SourceControl::getValues()),
|
|
||||||
'access_token' => Str::random(10),
|
'access_token' => Str::random(10),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function gitlab(): Factory
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'provider' => \App\Enums\SourceControl::GITLAB,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function github(): Factory
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'provider' => \App\Enums\SourceControl::GITHUB,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bitbucket(): Factory
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'provider' => \App\Enums\SourceControl::BITBUCKET,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
app:
|
vito:
|
||||||
build:
|
build:
|
||||||
context: ./docker/8.1
|
context: ./docker/8.1
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
36
package-lock.json
generated
36
package-lock.json
generated
@ -10,10 +10,10 @@
|
|||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"alpinejs": "^3.4.2",
|
"alpinejs": "^3.4.2",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^1.1.2",
|
"axios": "^1.6.0",
|
||||||
"laravel-echo": "^1.15.0",
|
"laravel-echo": "^1.15.0",
|
||||||
"laravel-vite-plugin": "^0.7.2",
|
"laravel-vite-plugin": "^0.7.2",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.31",
|
||||||
"pusher-js": "^4.3.1",
|
"pusher-js": "^4.3.1",
|
||||||
"tailwindcss": "^3.1.0",
|
"tailwindcss": "^3.1.0",
|
||||||
"toastr": "^2.1.4",
|
"toastr": "^2.1.4",
|
||||||
@ -596,9 +596,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.3.5",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
|
||||||
"integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==",
|
"integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.0",
|
||||||
@ -1380,9 +1380,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.21",
|
"version": "8.4.31",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||||
"integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
|
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1392,10 +1392,14 @@
|
|||||||
{
|
{
|
||||||
"type": "tidelift",
|
"type": "tidelift",
|
||||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.4",
|
"nanoid": "^3.3.6",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
},
|
},
|
||||||
@ -2284,9 +2288,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "1.3.5",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
|
||||||
"integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==",
|
"integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.0",
|
||||||
@ -2852,12 +2856,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "8.4.21",
|
"version": "8.4.31",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||||
"integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
|
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"nanoid": "^3.3.4",
|
"nanoid": "^3.3.6",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"alpinejs": "^3.4.2",
|
"alpinejs": "^3.4.2",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^1.1.2",
|
"axios": "^1.6.0",
|
||||||
"laravel-echo": "^1.15.0",
|
"laravel-echo": "^1.15.0",
|
||||||
"laravel-vite-plugin": "^0.7.2",
|
"laravel-vite-plugin": "^0.7.2",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.31",
|
||||||
"pusher-js": "^4.3.1",
|
"pusher-js": "^4.3.1",
|
||||||
"tailwindcss": "^3.1.0",
|
"tailwindcss": "^3.1.0",
|
||||||
"toastr": "^2.1.4",
|
"toastr": "^2.1.4",
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
<testsuite name="Feature">
|
<testsuite name="Feature">
|
||||||
<directory suffix="Test.php">./tests/Feature</directory>
|
<directory suffix="Test.php">./tests/Feature</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
|
<testsuite name="Unit">
|
||||||
|
<directory suffix="Test.php">./tests/Unit</directory>
|
||||||
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
<coverage/>
|
<coverage/>
|
||||||
<php>
|
<php>
|
||||||
|
1
public/build/assets/app-328222da.css
Normal file
1
public/build/assets/app-328222da.css
Normal file
File diff suppressed because one or more lines are too long
24
public/build/assets/app-9aa488bb.js
Normal file
24
public/build/assets/app-9aa488bb.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"resources/css/app.css": {
|
"resources/css/app.css": {
|
||||||
"file": "assets/app-bdf134de.css",
|
"file": "assets/app-328222da.css",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/css/app.css"
|
"src": "resources/css/app.css"
|
||||||
},
|
},
|
||||||
"resources/js/app.js": {
|
"resources/js/app.js": {
|
||||||
"file": "assets/app-fa1f93fa.js",
|
"file": "assets/app-9aa488bb.js",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/js/app.js"
|
"src": "resources/js/app.js"
|
||||||
}
|
}
|
||||||
|
43
public/static/images/phpmyadmin.svg
Normal file
43
public/static/images/phpmyadmin.svg
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="3890" height="2168" id="svg2">
|
||||||
|
<metadata id="metadata8">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||||
|
<dc:title/>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs id="defs6"/>
|
||||||
|
<g id="g5" style="fill:#cccccc">
|
||||||
|
<path d="m 2889.39,6.3480122 -2.04,-4.07 c -1.01,-1.01 -2.03,-2.04 -4.06,-2.04 l -4.08,1.03 c -2.03,2.03 -3.05,3.05 -3.05,5.08 L 2789.64,1572.695 l 13.24,-2.035 83.46,-1523.70199 99.75,163.88 -1.02,0 c 75.32,221.88 106.87,458.02 94.66,708.41003 l 6.11,9.16 98.73,175.05996 6.1,6.11 c 151.66,133.336 321.63,222.907 509.94,268.707 l 45.8,74.309 6.11,2.031 1.02,-2.031 -866.19,-1416.82599 2.04,-29.52" id="path14"/>
|
||||||
|
<path d="m 2858.86,559.02801 c 106.87,218.84 145.54,549.62999 117.05,992.39199 l 416.29,-50.894 z" id="path18"/>
|
||||||
|
<path d="m 3807.48,1520.881 c 42.74,-5.086 70.22,-14.246 82.44,-27.476 l -2178.16,265.656 -1.02,0 c 1.02,90.586 41.73,161.836 121.12,212.723 21.37,15.269 43.77,26.465 64.12,33.59 19.34,-22.387 40.72,-38.676 66.17,-53.946 l 1.01,0 c 228,-138.422 566.94,-159.8 1014.78,-65.136 l 5.09,1.011 c 48.86,10.18 97.71,22.399 143.52,36.645 13.22,2.035 24.42,-2.035 33.58,-10.18 16.29,-12.215 36.65,-21.375 64.13,-27.476 l 0,-1.02 c 72.27,-128.25 169.97,-222.906 292.12,-284.996 84.48,-41.727 182.19,-69.215 291.1,-79.395" id="path20"/>
|
||||||
|
<path d="M 2761.15,1560.585 2860.89,31.798012 C 2716.36,589.56801 2484.29,1110.698 2165.71,1594.167 l 595.44,-33.582" id="path22"/>
|
||||||
|
<path d="m 2200.32,329.008 -4.07,-2.04 -4.07,1.02 -2.04,5.08 -82.44,1323.18799 12.21,-1.019 82.45,-1322.169 -2.04,-4.06" id="path24"/>
|
||||||
|
<path d="m 2084.29,1627.756 0,0 87.53,-1290.608 -461.08,1330.308 373.55,-39.7" id="path26"/>
|
||||||
|
</g>
|
||||||
|
<g id="g13" style="fill:none;stroke:#cccccc;stroke-width:12;stroke-linecap:round;stroke-linejoin:round">
|
||||||
|
<path d="m 2102.61,2057.9534 c -115.02,54.9606 -198.48,64.1207 -251.41,30.5387 -52.93,-35.6247 -134.36,-27.4847 -244.28,24.4219" id="path34"/>
|
||||||
|
<path d="m 2372.33,2066.093 c -21.37,-7.125 -44.78,-12.211 -69.21,-14.25 -49.87,-4.066 -109.93,15.27 -180.16,57.0042 -70.23,42.746 -154.71,59.0351 -255.48,49.8711" id="path36"/>
|
||||||
|
<path d="m 3000.34,1962.273 c -484.5,-99.742 -833.61,-76.336 -1047.35,71.25" id="path38"/>
|
||||||
|
<path d="m 3305.69,2010.117 c -21.38,-8.145 -44.79,-13.235 -69.22,-14.254 -49.87,-4.067 -109.92,15.269 -180.15,57.004 -70.23,41.7262 -154.71,58.0114 -255.48,49.8708" id="path40"/>
|
||||||
|
<path d="m 2655.29,341.21801 c -49.88,-30.54 -101.78,-22.39 -155.73,25.44 -46.82,-47.83 -95.67,-55.98 -146.57,-25.44" id="path42" style="stroke-width:29"/>
|
||||||
|
<path d="m 2542.31,170.21801 c -50.89,-30.53 -100.76,-18.32 -151.66,36.64 -49.88,-54.96 -100.76,-67.17 -151.66,-36.64" id="path44" style="stroke-width:29"/>
|
||||||
|
</g>
|
||||||
|
<g style="fill:#6c78af" id="g33">
|
||||||
|
<path d="m 56.770404,1763.8603 134.914516,0 c 40.53785,0 70.3051,11.5406 89.30315,34.6149 18.99058,23.0812 25.15303,55.2422 18.48477,96.4878 -2.73388,16.9207 -7.61168,32.4501 -14.63698,46.5933 -7.02825,14.1442 -16.30891,27.067 -27.84598,38.7573 -13.71822,14.0684 -29.07355,24.148 -46.07783,30.2307 -17.00335,6.0818 -38.74881,9.1232 -65.23042,9.1232 l -60.093245,0 -14.951878,92.5154 -70.16450702,0 56.29840402,-348.3226 z m 61.252276,55.1047 -23.613063,146.1033 42.675303,0 c 28.28742,0 49.25184,-5.7744 62.90101,-17.3383 13.63797,-11.5649 22.6337,-30.807 26.98842,-57.7355 4.19709,-25.968 1.75658,-44.2941 -7.2996,-54.9935 -9.06329,-10.6883 -26.92099,-16.036 -53.57751,-16.036 l -48.07456,0" id="path66"/>
|
||||||
|
<path d="m 378.24196,1671.3451 69.63516,0 -14.95189,92.5152 61.94982,0 c 38.98987,0 66.01185,7.3901 81.07593,22.1571 15.06891,14.7762 19.95224,38.5804 14.64264,71.4329 l -26.22037,162.2172 -70.68973,0 24.9538,-154.3893 c 2.84147,-17.5516 1.46456,-29.4876 -4.12427,-35.815 -5.58913,-6.3193 -17.28356,-9.4871 -35.06873,-9.4871 l -55.57891,0 -32.27423,199.6914 -69.64729,0 56.29807,-348.3224" id="path68"/>
|
||||||
|
<path d="m 666.43774,1763.8603 134.9135,0 c 40.54695,0 70.30511,11.5406 89.30319,34.6149 18.99454,23.0812 25.15404,55.2422 18.4898,96.4878 -2.7339,16.9207 -7.61577,32.4501 -14.63297,46.5933 -7.03329,14.1442 -16.32202,27.067 -27.85103,38.7573 -13.72229,14.0684 -29.07657,24.148 -46.08084,30.2307 -17.00032,6.0818 -38.74478,9.1232 -65.23548,9.1232 l -60.08435,0 -14.95188,92.5154 -70.16093,0 56.29099,-348.3226 z m 61.26036,55.1047 -23.61306,146.1033 42.6753,0 c 28.28641,0 49.2478,-5.7744 62.88888,-17.3383 13.641,-11.5649 22.64179,-30.807 26.99549,-57.7355 4.19406,-25.968 1.7576,-44.2941 -7.30364,-54.9935 -9.06329,-10.6883 -26.92099,-16.036 -53.56841,-16.036 l -48.07456,0" id="path70"/>
|
||||||
|
</g>
|
||||||
|
<g style="fill:#f89c0e" id="g65">
|
||||||
|
<path d="m 1027.7488,1597.3243 134.9473,0 59.2813,323.8687 163.9729,-323.8687 134.4328,0 -68.203,422.055 -90.0955,0 60.5624,-328.7447 -165.335,328.7447 -97.63,0 -62.0922,-332.1897 -44.4691,332.1897 -93.58345,0 68.21155,-422.055" id="path72"/>
|
||||||
|
<path d="m 1682.3349,1951.0787 68.129,0 39.0484,-241.6556 84.6928,0 -48.7474,301.634 c -6.6176,41.0085 -21.4426,71.3829 -44.4508,91.1237 -23.0089,19.7312 -54.9295,29.6038 -95.7507,29.6038 l -166.0776,0 10.1515,-62.7878 151.4988,0 c 16.2574,0 29.3646,-3.7991 39.3223,-11.39 9.9443,-7.6043 16.0994,-18.6108 18.427,-33.0342 l 0.8443,-5.1933 -74.9653,0 c -47.9513,0 -80.6531,-9.1406 -98.0934,-27.4219 -17.4525,-18.2801 -22.7167,-48.7649 -15.8297,-91.453 l 30.891,-191.0813 83.7372,0 -29.8633,184.7645 c -3.7745,23.3729 -2.642,38.6968 3.4343,45.9753 6.0641,7.2784 20.5937,10.9158 43.6016,10.9158" id="path74"/>
|
||||||
|
<path d="m 2102.3044,1597.3243 97.5197,0 118.1874,422.055 -102.2734,0 -23.907,-100.4601 -189.9554,0 -55.1868,100.4601 -97.5321,0 253.1476,-422.055 z m 31.6507,83.8058 -90.1808,162.444 130.2183,0 -40.0375,-162.444" id="path76"/>
|
||||||
|
<path d="m 2637.3031,2019.3793 -162.6964,0 c -49.1642,0 -85.2663,-13.9786 -108.3193,-41.9409 -23.0404,-27.9573 -30.5053,-66.9321 -22.4309,-116.9135 3.316,-20.4913 9.2287,-39.3092 17.7509,-56.4463 8.5217,-17.1419 19.771,-32.7965 33.7592,-46.9712 16.6286,-17.0415 35.3095,-29.2498 56.0305,-36.6239 20.7209,-7.3752 47.0449,-11.0604 78.9594,-11.0604 l 72.6621,0 18.1132,-112.0988 84.3865,0 -68.2152,422.055 z m -73.6376,-66.4629 28.5697,-176.7241 -51.2224,0 c -34.3524,0 -59.8397,6.9489 -76.4874,20.8321 -16.6223,13.8929 -27.5723,37.0269 -32.8017,69.397 -5.0795,31.4221 -2.0777,53.6898 9.0062,66.8122 11.0837,13.1222 32.7053,19.6828 64.8648,19.6828 l 58.0708,0" id="path78"/>
|
||||||
|
<path d="m 2761.0228,1709.4231 325.2334,0 c 47.155,0 79.7016,8.9067 97.6259,26.6992 17.9129,17.8022 23.6511,46.7028 17.1903,86.702 l -31.7718,196.555 -85.3299,0 30.0434,-185.9259 c 3.6903,-22.7947 2.5585,-37.8305 -3.3836,-45.1151 -5.966,-7.2785 -20.0182,-10.9208 -42.1807,-10.9208 l -47.5103,0 -39.1073,241.9618 -86.604,0 39.1073,-241.9618 -98.9777,0 -39.1073,241.9618 -85.3298,0 50.1021,-309.9562" id="path80"/>
|
||||||
|
<path d="m 3389.6515,1674.2008 -88.8214,0 12.4228,-76.8765 88.8214,0 -12.4228,76.8765 z m -55.7924,345.1785 -88.8215,0 50.0899,-309.9562 88.8214,0 -50.0898,309.9562" id="path82"/>
|
||||||
|
<path d="m 3457.2112,1709.4231 159.3518,0 c 48.1596,0 81.1348,8.7634 98.9115,26.2691 17.7775,17.5156 23.3935,46.5596 16.8359,87.1321 l -31.7597,196.555 -84.705,0 30.1524,-186.5005 c 3.7421,-23.1817 2.4511,-38.2189 -3.8732,-45.1102 -6.325,-6.9 -20.6913,-10.3511 -43.0866,-10.3511 l -68.1168,0 -39.1072,241.9618 -84.6928,0 50.0897,-309.9562" id="path84"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.6 KiB |
2
public/vendor/log-viewer/app.css
vendored
2
public/vendor/log-viewer/app.css
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/log-viewer/app.js
vendored
2
public/vendor/log-viewer/app.js
vendored
File diff suppressed because one or more lines are too long
4
public/vendor/log-viewer/mix-manifest.json
vendored
4
public/vendor/log-viewer/mix-manifest.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"/app.js": "/app.js?id=2ca3fa12f273bd645611f1acf3d81355",
|
"/app.js": "/app.js?id=5f574f36f456b103dffcfa21d5612785",
|
||||||
"/app.css": "/app.css?id=93151d8b186ef7758df8582425ff8082",
|
"/app.css": "/app.css?id=b701a4344131bb2c00e9f0b1ef1ab3c1",
|
||||||
"/img/log-viewer-128.png": "/img/log-viewer-128.png?id=d576c6d2e16074d3f064e60fe4f35166",
|
"/img/log-viewer-128.png": "/img/log-viewer-128.png?id=d576c6d2e16074d3f064e60fe4f35166",
|
||||||
"/img/log-viewer-32.png": "/img/log-viewer-32.png?id=f8ec67d10f996aa8baf00df3b61eea6d",
|
"/img/log-viewer-32.png": "/img/log-viewer-32.png?id=f8ec67d10f996aa8baf00df3b61eea6d",
|
||||||
"/img/log-viewer-64.png": "/img/log-viewer-64.png?id=8902d596fc883ca9eb8105bb683568c6"
|
"/img/log-viewer-64.png": "/img/log-viewer-64.png?id=8902d596fc883ca9eb8105bb683568c6"
|
||||||
|
1
resources/commands/storage/download-from-ftp.sh
Normal file
1
resources/commands/storage/download-from-ftp.sh
Normal file
@ -0,0 +1 @@
|
|||||||
|
curl __passive__ -u "__username__:__password__" ftp__ssl__://__host__:__port__/__src__ -o "__dest__"
|
1
resources/commands/storage/upload-to-ftp.sh
Normal file
1
resources/commands/storage/upload-to-ftp.sh
Normal file
@ -0,0 +1 @@
|
|||||||
|
curl __passive__ -T "__src__" -u "__username__:__password__" ftp__ssl__://__host__:__port__/__dest__
|
@ -2,6 +2,4 @@ if ! cd __path__; then
|
|||||||
echo 'VITO_SSH_ERROR' && exit 1
|
echo 'VITO_SSH_ERROR' && exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! __script__; then
|
__script__
|
||||||
echo 'VITO_SSH_ERROR' && exit 1
|
|
||||||
fi
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
server {
|
server {
|
||||||
listen 54331;
|
listen __port__;
|
||||||
server_name _;
|
server_name _;
|
||||||
root /home/vito/phpmyadmin;
|
root /home/vito/phpmyadmin;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user