2023-05-24 12:26:50 +00:00
< ? php
use App\Models\GithubApp ;
2023-05-30 13:52:17 +00:00
use App\Models\GitlabApp ;
2023-07-11 09:11:51 +00:00
use Carbon\Carbon ;
2023-05-24 12:26:50 +00:00
use Illuminate\Support\Facades\Http ;
2023-08-08 09:51:36 +00:00
use Illuminate\Support\Str ;
2023-05-24 12:26:50 +00:00
use Lcobucci\JWT\Encoding\ChainedFormatter ;
use Lcobucci\JWT\Encoding\JoseEncoder ;
use Lcobucci\JWT\Signer\Key\InMemory ;
use Lcobucci\JWT\Signer\Rsa\Sha256 ;
use Lcobucci\JWT\Token\Builder ;
function generate_github_installation_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 )
-> 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 ()) {
2024-01-31 12:47:16 +00:00
throw new RuntimeException ( " Failed to get access token for " . $source -> name . " with error: " . $token -> json ()[ 'message' ]);
2023-05-24 12:26:50 +00:00
}
return $token -> json ()[ 'token' ];
}
2023-08-08 09:51:36 +00:00
2023-05-24 12:26:50 +00:00
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 ;
}
2023-05-30 13:52:17 +00:00
2023-11-14 12:26:14 +00:00
function githubApi ( GithubApp | GitlabApp | null $source , string $endpoint , string $method = 'get' , array | null $data = null , bool $throwError = true )
2023-05-30 13:52:17 +00:00
{
2023-11-14 12:26:14 +00:00
if ( is_null ( $source )) {
throw new \Exception ( 'Not implemented yet.' );
}
2023-05-30 13:52:17 +00:00
if ( $source -> getMorphClass () == 'App\Models\GithubApp' ) {
if ( $source -> is_public ) {
2023-06-13 13:01:11 +00:00
$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 );
}
2023-05-30 13:52:17 +00:00
}
}
$json = $response -> json ();
2023-06-13 13:01:11 +00:00
if ( $response -> failed () && $throwError ) {
2024-01-26 17:46:50 +00:00
ray ( $json );
2023-08-08 09:51:36 +00:00
throw new \Exception ( " Failed to get data from { $source -> name } with error:<br><br> " . $json [ 'message' ] . " <br><br>Rate Limit resets at: " . Carbon :: parse (( int ) $response -> header ( 'X-RateLimit-Reset' )) -> format ( 'Y-m-d H:i:s' ) . 'UTC' );
2023-05-30 13:52:17 +00:00
}
return [
'rate_limit_remaining' => $response -> header ( 'X-RateLimit-Remaining' ),
2023-06-28 11:37:00 +00:00
'rate_limit_reset' => $response -> header ( 'X-RateLimit-Reset' ),
2023-05-30 13:52:17 +00:00
'data' => collect ( $json )
];
}
2023-08-08 09:51:36 +00:00
2023-06-14 09:03:54 +00:00
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 " ;
}