privateKey->private_key); $algorithm = new Sha256(); $tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default())); $now = new DateTimeImmutable(); $now = $now->setTime($now->format('H'), $now->format('i')); $issuedToken = $tokenBuilder ->issuedBy($source->app_id) ->issuedAt($now) ->expiresAt($now->modify('+10 minutes')) ->getToken($algorithm, $signingKey) ->toString(); $token = Http::withHeaders([ 'Authorization' => "Bearer $issuedToken", 'Accept' => 'application/vnd.github.machine-man-preview+json' ])->post("{$source->api_url}/app/installations/{$source->installation_id}/access_tokens"); if ($token->failed()) { throw new RuntimeException("Failed to get access token for " . $source->name . " with error: " . data_get($token->json(),'message','no error message found')); } return $token->json()['token']; } function generate_github_jwt_token(GithubApp $source) { $signingKey = InMemory::plainText($source->privateKey->private_key); $algorithm = new Sha256(); $tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default())); $now = new DateTimeImmutable(); $now = $now->setTime($now->format('H'), $now->format('i')); $issuedToken = $tokenBuilder ->issuedBy($source->app_id) ->issuedAt($now->modify('-1 minute')) ->expiresAt($now->modify('+10 minutes')) ->getToken($algorithm, $signingKey) ->toString(); return $issuedToken; } function githubApi(GithubApp|GitlabApp|null $source, string $endpoint, string $method = 'get', array|null $data = null, bool $throwError = true) { if (is_null($source)) { throw new \Exception('Not implemented yet.'); } if ($source->getMorphClass() == 'App\Models\GithubApp') { if ($source->is_public) { $response = Http::github($source->api_url)->$method($endpoint); } else { $github_access_token = generate_github_installation_token($source); if ($data && ($method === 'post' || $method === 'patch' || $method === 'put')) { $response = Http::github($source->api_url, $github_access_token)->$method($endpoint, $data); } else { $response = Http::github($source->api_url, $github_access_token)->$method($endpoint); } } } $json = $response->json(); if ($response->failed() && $throwError) { ray($json); throw new \Exception("Failed to get data from {$source->name} with error:

" . $json['message'] . "

Rate Limit resets at: " . Carbon::parse((int)$response->header('X-RateLimit-Reset'))->format('Y-m-d H:i:s') . 'UTC'); } return [ 'rate_limit_remaining' => $response->header('X-RateLimit-Remaining'), 'rate_limit_reset' => $response->header('X-RateLimit-Reset'), 'data' => collect($json) ]; } function get_installation_path(GithubApp $source) { $github = GithubApp::where('uuid', $source->uuid)->first(); $name = Str::of(Str::kebab($github->name)); $installation_path = $github->html_url === 'https://github.com' ? 'apps' : 'github-apps'; return "$github->html_url/$installation_path/$name/installations/new"; } function get_permissions_path(GithubApp $source) { $github = GithubApp::where('uuid', $source->uuid)->first(); $name = Str::of(Str::kebab($github->name)); return "$github->html_url/settings/apps/$name/permissions"; }