mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 10:18:20 +00:00
fix(github): derive API URLs from GitHub HTML hosts (#10610)
This commit is contained in:
12 files changed
+681
-46
No files matched your search
@@ -129,7 +129,7 @@ class GithubController extends Controller
|
||||
'private_key_uuid' => ['type' => 'string', 'description' => 'UUID of an existing private key for GitHub App authentication.'],
|
||||
'is_system_wide' => ['type' => 'boolean', 'description' => 'Is this app system-wide (cloud only).'],
|
||||
],
|
||||
required: ['name', 'api_url', 'html_url', 'app_id', 'installation_id', 'client_id', 'client_secret', 'private_key_uuid'],
|
||||
required: ['name', 'html_url', 'app_id', 'installation_id', 'client_id', 'client_secret', 'private_key_uuid'],
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -205,10 +205,14 @@ class GithubController extends Controller
|
||||
'is_system_wide',
|
||||
];
|
||||
|
||||
$request->merge([
|
||||
'organization' => normalizeGithubOrganization($request->input('organization')),
|
||||
]);
|
||||
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'name' => 'required|string|max:255',
|
||||
'organization' => 'nullable|string|max:255',
|
||||
'api_url' => ['required', 'string', 'url', new SafeExternalUrl],
|
||||
'organization' => ['nullable', 'string', 'max:255', 'regex:/\A[^\s\/?#]+\z/'],
|
||||
'api_url' => ['nullable', 'string', 'url', new SafeExternalUrl],
|
||||
'html_url' => ['required', 'string', 'url', new SafeExternalUrl],
|
||||
'custom_user' => 'nullable|string|max:255',
|
||||
'custom_port' => 'nullable|integer|min:1|max:65535',
|
||||
@@ -252,7 +256,9 @@ class GithubController extends Controller
|
||||
'uuid' => Str::uuid(),
|
||||
'name' => $request->input('name'),
|
||||
'organization' => $request->input('organization'),
|
||||
'api_url' => $request->input('api_url'),
|
||||
'api_url' => filled($request->input('api_url'))
|
||||
? $request->input('api_url')
|
||||
: githubApiUrlFromHtmlUrl($request->input('html_url')),
|
||||
'html_url' => $request->input('html_url'),
|
||||
'custom_user' => $request->input('custom_user', 'git'),
|
||||
'custom_port' => $request->input('custom_port', 22),
|
||||
@@ -589,13 +595,17 @@ class GithubController extends Controller
|
||||
|
||||
$payload = $request->only($allowedFields);
|
||||
|
||||
if (array_key_exists('organization', $payload)) {
|
||||
$payload['organization'] = normalizeGithubOrganization($payload['organization']);
|
||||
}
|
||||
|
||||
// Validate the request
|
||||
$rules = [];
|
||||
if (isset($payload['name'])) {
|
||||
$rules['name'] = 'string';
|
||||
}
|
||||
if (isset($payload['organization'])) {
|
||||
$rules['organization'] = 'nullable|string';
|
||||
$rules['organization'] = ['nullable', 'string', 'regex:/\A[^\s\/?#]+\z/'];
|
||||
}
|
||||
if (isset($payload['api_url'])) {
|
||||
$rules['api_url'] = ['url', new SafeExternalUrl];
|
||||
@@ -639,6 +649,13 @@ class GithubController extends Controller
|
||||
], 422);
|
||||
}
|
||||
|
||||
if (array_key_exists('organization', $payload)) {
|
||||
$payload['organization'] = normalizeGithubOrganization($payload['organization']);
|
||||
}
|
||||
if (isset($payload['html_url']) && ! filled($payload['api_url'] ?? null)) {
|
||||
$payload['api_url'] = githubApiUrlFromHtmlUrl($payload['html_url']);
|
||||
}
|
||||
|
||||
// Handle private_key_uuid -> private_key_id conversion
|
||||
if (isset($payload['private_key_uuid'])) {
|
||||
$privateKey = PrivateKey::where('team_id', $teamId)
|
||||
|
||||
@@ -9,6 +9,7 @@ use App\Rules\SafeExternalUrl;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Component;
|
||||
|
||||
class Change extends Component
|
||||
@@ -78,11 +79,13 @@ class Change extends Component
|
||||
|
||||
public string $activeTab = 'general';
|
||||
|
||||
private bool $shouldDeriveApiUrlAfterHtmlUrlUpdate = false;
|
||||
|
||||
protected function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string',
|
||||
'organization' => 'nullable|string',
|
||||
'organization' => ['nullable', 'string', 'regex:/\A[^\s\/?#]+\z/'],
|
||||
'apiUrl' => ['required', 'string', 'url', new SafeExternalUrl],
|
||||
'htmlUrl' => ['required', 'string', 'url', new SafeExternalUrl],
|
||||
'customUser' => 'required|string',
|
||||
@@ -103,6 +106,19 @@ class Change extends Component
|
||||
];
|
||||
}
|
||||
|
||||
public function updatingHtmlUrl(): void
|
||||
{
|
||||
$this->shouldDeriveApiUrlAfterHtmlUrlUpdate = blank($this->apiUrl)
|
||||
|| $this->apiUrl === githubApiUrlFromHtmlUrl($this->htmlUrl);
|
||||
}
|
||||
|
||||
public function updatedHtmlUrl(): void
|
||||
{
|
||||
if ($this->shouldDeriveApiUrlAfterHtmlUrlUpdate) {
|
||||
$this->apiUrl = githubApiUrlFromHtmlUrl($this->htmlUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
if ($this->github_app) {
|
||||
@@ -119,6 +135,11 @@ class Change extends Component
|
||||
{
|
||||
if ($toModel) {
|
||||
// Sync TO model (before save)
|
||||
$this->organization = normalizeGithubOrganization($this->organization);
|
||||
$this->apiUrl = filled($this->apiUrl)
|
||||
? $this->apiUrl
|
||||
: githubApiUrlFromHtmlUrl($this->htmlUrl);
|
||||
|
||||
$this->github_app->name = $this->name;
|
||||
$this->github_app->organization = $this->organization;
|
||||
$this->github_app->api_url = $this->apiUrl;
|
||||
@@ -294,11 +315,14 @@ class Change extends Component
|
||||
|
||||
public function getGithubAppNameUpdatePath()
|
||||
{
|
||||
if (str($this->github_app->organization)->isNotEmpty()) {
|
||||
return "{$this->github_app->html_url}/organizations/{$this->github_app->organization}/settings/apps/{$this->github_app->name}";
|
||||
$name = encodeGithubPathSegment($this->github_app->name);
|
||||
$organization = normalizeGithubOrganization($this->github_app->organization);
|
||||
|
||||
if (filled($organization)) {
|
||||
return rtrim($this->github_app->html_url, '/').'/organizations/'.encodeGithubPathSegment($organization)."/settings/apps/{$name}";
|
||||
}
|
||||
|
||||
return "{$this->github_app->html_url}/settings/apps/{$this->github_app->name}";
|
||||
return rtrim($this->github_app->html_url, '/')."/settings/apps/{$name}";
|
||||
}
|
||||
|
||||
public function updateGithubAppName()
|
||||
@@ -341,11 +365,17 @@ class Change extends Component
|
||||
$this->authorize('update', $this->github_app);
|
||||
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
$this->organization = normalizeGithubOrganization($this->organization);
|
||||
$this->apiUrl = filled($this->apiUrl)
|
||||
? $this->apiUrl
|
||||
: githubApiUrlFromHtmlUrl($this->htmlUrl);
|
||||
$this->validate();
|
||||
|
||||
$this->syncData(true);
|
||||
$this->github_app->save();
|
||||
$this->dispatch('success', 'Github App updated.');
|
||||
} catch (ValidationException $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Livewire\Source\Github;
|
||||
use App\Models\GithubApp;
|
||||
use App\Rules\SafeExternalUrl;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Component;
|
||||
|
||||
class Create extends Component
|
||||
@@ -25,19 +26,39 @@ class Create extends Component
|
||||
|
||||
public bool $is_system_wide = false;
|
||||
|
||||
private bool $shouldDeriveApiUrlAfterHtmlUrlUpdate = false;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->name = substr(generate_random_name(), 0, 30);
|
||||
}
|
||||
|
||||
public function updatingHtmlUrl(): void
|
||||
{
|
||||
$this->shouldDeriveApiUrlAfterHtmlUrlUpdate = blank($this->api_url)
|
||||
|| $this->api_url === githubApiUrlFromHtmlUrl($this->html_url);
|
||||
}
|
||||
|
||||
public function updatedHtmlUrl(): void
|
||||
{
|
||||
if ($this->shouldDeriveApiUrlAfterHtmlUrlUpdate) {
|
||||
$this->api_url = githubApiUrlFromHtmlUrl($this->html_url);
|
||||
}
|
||||
}
|
||||
|
||||
public function createGitHubApp()
|
||||
{
|
||||
try {
|
||||
$this->authorize('createAnyResource');
|
||||
|
||||
$this->organization = normalizeGithubOrganization($this->organization);
|
||||
$this->api_url = filled($this->api_url)
|
||||
? $this->api_url
|
||||
: githubApiUrlFromHtmlUrl($this->html_url);
|
||||
|
||||
$this->validate([
|
||||
'name' => 'required|string',
|
||||
'organization' => 'nullable|string',
|
||||
'organization' => ['nullable', 'string', 'regex:/\A[^\s\/?#]+\z/'],
|
||||
'api_url' => ['required', 'string', 'url', new SafeExternalUrl],
|
||||
'html_url' => ['required', 'string', 'url', new SafeExternalUrl],
|
||||
'custom_user' => 'required|string',
|
||||
@@ -60,6 +81,8 @@ class Create extends Component
|
||||
}
|
||||
|
||||
return redirectRoute($this, 'source.github.show', ['github_app_uuid' => $github_app->uuid]);
|
||||
} catch (ValidationException $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user