implemented the GitHub calls for the repository

This commit is contained in:
stephan.kasdorf
2024-06-18 16:58:02 +02:00
parent 2572c28648
commit a3b811ec9a
20 changed files with 552 additions and 166 deletions

6
.env
View File

@@ -13,4 +13,10 @@ NIBIRU_AUTH_VIRTUAL_HOST=api.agent.auth.nibiru-framework.com
NIBIRU_AUTH_LETSENCRYPT_HOST=api.agent.auth.nibiru-framework.com
PROXY_NETWORK=nginx-proxy
GITHUB_REPOSITORY_API_URL=https://api.github.com
GITHUB_REPO_OWNER=alllinux
GITHUB_REPO_NAME=Nibiru
GITHUB_TOKEN=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
JWT_SECRET_KEY=fL/S0LGXUVawAj4h45zyyAVQPTeR4oO7upfTMOTVvUc=

View File

@@ -11,4 +11,10 @@ NIBIRU_AUTH_HOST=nibiru-auth-api
NIBIRU_AUTH_VIRTUAL_HOST=local.auth.nibiru-framework.com
PROXY_NETWORK=nginx-proxy
GITHUB_REPOSITORY_API_URL=https://api.github.com
GITHUB_REPO_OWNER=alllinux
GITHUB_REPO_NAME=Nibiru
GITHUB_TOKEN=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
JWT_SECRET_KEY=fL/S0LGXUVawAj4h45zyyAVQPTeR4oO7upfTMOTVvUc=

View File

@@ -12,9 +12,12 @@ services:
- VIRTUAL_PORT=${FPM_VIRTUAL_PORT}
- NIBIRU_AUTH_VIRTUAL_HOST=${NIBIRU_AUTH_VIRTUAL_HOST}
- NIBIRU_AUTH_HOST=${NIBIRU_AUTH_HOST}
- GITHUB_REPOSITORY_API_URL=${GITHUB_REPOSITORY_API_URL}
- GITHUB_REPO_OWNER=${GITHUB_REPO_OWNER}
- GITHUB_REPO_NAME=${GITHUB_REPO_NAME}
- TZ=${TZ}
volumes:
- ./src:/var/www/html
- ./nibiru-auth-api/src:/var/www/html
networks:
api_internal:
restart: always
@@ -34,9 +37,12 @@ services:
- NIBIRU_AUTH_VIRTUAL_HOST=${NIBIRU_AUTH_VIRTUAL_HOST}
- NIBIRU_AUTH_HOST=${NIBIRU_AUTH_HOST}
- LETSENCRYPT_HOST=${NIBIRU_AUTH_LETSENCRYPT_HOST}
- GITHUB_REPOSITORY_API_URL=${GITHUB_REPOSITORY_API_URL}
- GITHUB_REPO_OWNER=${GITHUB_REPO_OWNER}
- GITHUB_REPO_NAME=${GITHUB_REPO_NAME}
- TZ=${TZ}
volumes:
- ./src:/usr/share/nginx/html
- ./nibiru-auth-api/src:/usr/share/nginx/html
networks:
nginx-proxy:
api_internal:
@@ -57,7 +63,7 @@ services:
- NIBIRU_WEBHOOK_HOST=${NIBIRU_WEBHOOK_HOST}
- TZ=${TZ}
volumes:
- ./src:/var/www/html
- ./nibiru-webhook-receiver/src:/var/www/html
networks:
api_internal:
restart: always
@@ -77,7 +83,7 @@ services:
- LETSENCRYPT_HOST=${NIBIRU_WEHOOK_RECEIVER_LETSENCRYPT_HOST}
- TZ=${TZ}
volumes:
- ./src:/usr/share/nginx/html
- ./nibiru-webhook-receiver/src:/usr/share/nginx/html
networks:
nginx-proxy:
api_internal:

View File

@@ -183,7 +183,7 @@ paths:
properties:
name:
type: string
email:
email:
type: string
date:
type: string
@@ -195,8 +195,8 @@ paths:
properties:
sha:
type: string
url:
type: string
url:
type: string
url:
type: string
comment_count:
@@ -298,5 +298,56 @@ paths:
type: string
'404':
description: Repository not found
/repos/{owner}/{repo}/branches:
get:
operationId: listBranches
summary: List branches in a repository
description: Retrieve a list of branches in a repository.
parameters:
- name: owner
in: path
required: true
schema:
type: string
description: The owner of the repository.
- name: repo
in: path
required: true
schema:
type: string
description: The name of the repository.
- name: protected
in: query
schema:
type: boolean
description: Set to true to only return protected branches.
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: array
items:
type: object
properties:
name:
type: string
description: The name of the branch.
commit:
type: object
properties:
sha:
type: string
description: SHA of the commit.
url:
type: string
description: URL of the commit.
protected:
type: boolean
description: Indicates if the branch is protected.
'404':
description: Repository not found
components:
schemas: {}

View File

@@ -0,0 +1,80 @@
<?php
namespace NibiruAuthApi;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class AuthController
{
private $secretKey;
public function __construct()
{
$this->secretKey = getenv('JWT_SECRET_KEY'); // Use getenv to get the secret key
}
public function handle()
{
$action = $_GET['action'] ?? '';
if ($action === 'token') {
$this->generateToken();
} elseif ($action === 'validate') {
$this->validateToken();
} else {
echo json_encode(['error' => 'Invalid action']);
}
}
private function generateToken()
{
$issuedAt = time();
$expirationTime = $issuedAt + 3600;
$payload = [
'iss' => getenv('NIBIRU_AUTH_VIRTUAL_HOST'),
'aud' => getenv('NIBIRU_AUTH_VIRTUAL_HOST'),
'iat' => $issuedAt,
'nbf' => $issuedAt,
'exp' => $expirationTime,
'data' => [
'userId' => 123,
'username' => 'example_user'
]
];
$jwt = $this->encodeJwt($payload, $this->secretKey);
echo json_encode(['token' => $jwt]);
}
public function validateToken()
{
$headers = getallheaders();
$authHeader = $headers['Authorization'] ?? '';
if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches))
{
$token = $matches[1];
try {
$decoded = JWT::decode($token, new Key($this->secretKey, 'HS256'));
echo json_encode(['valid' => true, 'data' => $decoded]);
} catch (\Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token', 'message' => $e->getMessage()]);
}
} else {
http_response_code(401);
echo json_encode(['error' => 'Authorization header missing']);
}
}
private function encodeJwt($payload, $key)
{
return JWT::encode($payload, $key, 'HS256');
}
private function decodeJwt($jwt, $key)
{
return JWT::decode($jwt, new Key($key, 'HS256'));
}
}

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1,27 @@
{
"name": "nibiru/auth-api",
"description": "Authentication API for Nibiru Framework",
"type": "project",
"require": {
"guzzlehttp/guzzle": "^7.0",
"psr/http-message": "^1.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"symfony/deprecation-contracts": "^2.1",
"firebase/php-jwt": "^6.0"
},
"autoload": {
"psr-4": {
"NibiruAuthApi\\": ""
}
},
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"scripts": {
"post-update-cmd": [
"chmod -R 777 storage"
]
}
}

View File

@@ -0,0 +1,9 @@
<?php
require_once __DIR__ . '/vendor/autoload.php';
use NibiruAuthApi\AuthController;
// Initialize and handle the request
$controller = new AuthController();
$controller->handle();

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1,261 @@
<?php
namespace NibiruWebhookReceiver;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use GuzzleHttp\Client;
class WebhookController
{
private $secretKey;
private $authApiUrl;
private $githubToken;
private $repoOwner;
private $repoName;
private $client;
private $githubApiUrl;
public function __construct()
{
$this->secretKey = getenv('JWT_SECRET_KEY');
$this->authApiUrl = getenv('NIBIRU_AUTH_API_URL');
$this->githubToken = getenv('GITHUB_TOKEN');
$this->repoOwner = getenv('GITHUB_REPO_OWNER');
$this->repoName = getenv('GITHUB_REPO_NAME');
$this->githubApiUrl = getenv('GITHUB_REPOSITORY_API_URL');
$this->client = new Client();
}
/**
* @desc handle the webhook request and validate the token
* @return void
*/
public function handleWebhook()
{
$token = $this->getBearerToken();
// Debug output for token
error_log("Received Token: " . $token);
if ($token)
{
try {
$decoded = JWT::decode($token, new Key($this->secretKey, 'HS256'));
$payload = (array) $decoded;
// Token is valid, process the webhook
http_response_code(200);
echo json_encode(['message' => 'Webhook processed', 'data' => $payload]);
} catch (\Exception $e) {
// Invalid token
http_response_code(401);
echo json_encode(['error' => 'Invalid token', 'message' => $e->getMessage()]);
}
} else {
// No token provided
http_response_code(401);
echo json_encode(['error' => 'Authorization header missing']);
}
}
/**
* @desc get file content from the GitHub repository
* @return void*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function listFiles()
{
$token = $this->getBearerToken();
if ($token)
{
try {
JWT::decode($token, new Key($this->secretKey, 'HS256'));
$response = $this->client->get("{$this->githubApiUrl}/repos/{$this->repoOwner}/{$this->repoName}/contents", [
'headers' => [
'Authorization' => "Bearer {$this->githubToken}",
'Accept' => 'application/vnd.github.v3+json',
],
]);
$data = json_decode($response->getBody(), true);
http_response_code(200);
echo json_encode($data);
} catch (\Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token', 'message' => $e->getMessage()]);
}
} else {
http_response_code(401);
echo json_encode(['error' => 'Authorization header missing']);
}
}
/**
* @desc get file content from the GitHub repository
* @return void
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function getFile()
{
$token = $this->getBearerToken();
$filePath = $_GET['path'] ?? '';
if ($token)
{
try {
JWT::decode($token, new Key($this->secretKey, 'HS256'));
$response = $this->client->get("{$this->githubApiUrl}/repos/{$this->repoOwner}/{$this->repoName}/contents/{$filePath}", [
'headers' => [
'Authorization' => "Bearer {$this->githubToken}",
'Accept' => 'application/vnd.github.v3+json',
],
]);
$data = json_decode($response->getBody(), true);
http_response_code(200);
echo json_encode($data);
} catch (\Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token', 'message' => $e->getMessage()]);
}
} else {
http_response_code(401);
echo json_encode(['error' => 'Authorization header missing']);
}
}
/**
* @desc list tags from the GitHub repository
* @return void
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function listTags()
{
$token = $this->getBearerToken();
if ($token)
{
try {
JWT::decode($token, new Key($this->secretKey, 'HS256'));
$response = $this->client->get("{$this->githubApiUrl}/repos/{$this->repoOwner}/{$this->repoName}/tags", [
'headers' => [
'Authorization' => "Bearer {$this->githubToken}",
'Accept' => 'application/vnd.github.v3+json',
],
]);
$data = json_decode($response->getBody(), true);
http_response_code(200);
echo json_encode($data);
} catch (\Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token', 'message' => $e->getMessage()]);
}
} else {
http_response_code(401);
echo json_encode(['error' => 'Authorization header missing']);
}
}
/**
* @desc get authentication header
* @return string|null
*/
private function getAuthorizationHeader()
{
$headers = null;
if (isset($_SERVER['Authorization']))
{
$headers = trim($_SERVER["Authorization"]);
} elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) {
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
if (isset($requestHeaders['Authorization']))
{
$headers = trim($requestHeaders['Authorization']);
}
}
return $headers;
}
/**
* @desc Get the Bearer token from the Authorization header
* @return string|null
*/
private function getBearerToken()
{
$headers = $this->getAuthorizationHeader();
if (!empty($headers))
{
if (preg_match('/Bearer\s(\S+)/', $headers, $matches))
{
return $matches[1];
}
}
return null;
}
/**
* @desc Split API methods calls in order to handled multiple actions
* @return void
*/
public function handle()
{
$action = $_GET['action'] ?? null;
switch ($action) {
case 'webhook':
$this->handleWebhook();
break;
case 'list-files':
$this->listFiles();
break;
case 'get-file':
$this->getFile();
break;
case 'list-tags':
$this->listTags();
break;
default:
http_response_code(404);
echo "Action not found.";
break;
}
}
private function validateToken($authHeader)
{
$ch = curl_init("{$this->authApiUrl}/index.php?action=validate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: $authHeader"
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode === 200;
}
private function processPayload($payload)
{
// Add your payload processing logic here
// For example, you could log the payload or trigger some other action
$this->response(['message' => 'Webhook received'], 200);
}
private function response($data, $status)
{
header("Content-Type: application/json", true, $status);
echo json_encode($data);
exit;
}
}

View File

@@ -0,0 +1,62 @@
<?php
require __DIR__ . '/vendor/autoload.php';
use Firebase\JWT\JWT;
// Function to get the Authorization header
function getAuthorizationHeader()
{
$headers = null;
if (isset($_SERVER['Authorization']))
{
$headers = trim($_SERVER["Authorization"]);
} elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { // Nginx or fast CGI
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
// Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
if (isset($requestHeaders['Authorization']))
{
$headers = trim($requestHeaders['Authorization']);
}
}
return $headers;
}
// Function to get the Bearer token from the Authorization header
function getBearerToken()
{
$headers = getAuthorizationHeader();
// HEADER: Get the access token from the header
if (!empty($headers))
{
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
return $matches[1];
}
}
return null;
}
// Get the token from the Authorization header
$token = getBearerToken();
if ($token)
{
try {
$secretKey = getenv('JWT_SECRET_KEY'); // Ensure this is set in your environment
$decoded = JWT::decode($token, $secretKey, ['HS256']);
$payload = (array) $decoded;
// Token is valid, process the webhook
http_response_code(200);
echo json_encode(['message' => 'Webhook processed', 'data' => $payload]);
} catch (Exception $e) {
// Invalid token
http_response_code(401);
echo json_encode(['error' => 'Invalid token', 'message' => $e->getMessage()]);
}
} else {
// No token provided
http_response_code(401);
echo json_encode(['error' => 'Authorization header missing']);
}

View File

@@ -0,0 +1,27 @@
{
"name": "nibiru/webhook-receiver",
"description": "Webhook Receiver for Nibiru Framework",
"type": "project",
"require": {
"guzzlehttp/guzzle": "^7.0",
"psr/http-message": "^1.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"symfony/deprecation-contracts": "^2.1",
"firebase/php-jwt": "^6.0"
},
"autoload": {
"psr-4": {
"NibiruWebhookReceiver\\": ""
}
},
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"scripts": {
"post-update-cmd": [
"chmod -R 777 storage"
]
}
}

View File

@@ -0,0 +1,6 @@
<?php
require __DIR__ . '/vendor/autoload.php';
use NibiruWebhookReceiver\WebhookController;
$webhookController = new WebhookController();
$webhookController->handle();

View File

@@ -1,23 +0,0 @@
<?php
class AuthController {
public function login() {
// Handle login logic, validate user credentials, generate token
$username = $_POST['username'];
$password = $_POST['password'];
// Validate credentials (this is just an example, use proper validation)
if ($username === 'user' && $password === 'password') {
$token = bin2hex(random_bytes(16)); // Generate a random token
echo json_encode(['token' => $token]);
} else {
http_response_code(401);
echo json_encode(['error' => 'Invalid credentials']);
}
}
public function validateToken($token) {
// Validate the token (this is a simple example, implement proper token validation)
return strlen($token) === 32;
}
}

View File

@@ -1,39 +0,0 @@
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
class GitHubClient
{
private $client;
private $token;
public function __construct($token)
{
$this->client = new Client([
'base_uri' => 'https://api.github.com/',
'headers' => [
'Authorization' => "token $token",
'Accept' => 'application/vnd.github.v3+json',
],
]);
$this->token = $token;
}
public function getRepositoryContent($owner, $repo, $path, $ref = 'main')
{
$response = $this->client->get("repos/$owner/$repo/contents/$path", [
'query' => ['ref' => $ref]
]);
return json_decode($response->getBody(), true);
}
public function listCommits($owner, $repo, $params = [])
{
$response = $this->client->get("repos/$owner/$repo/commits", [
'query' => $params
]);
return json_decode($response->getBody(), true);
}
}

View File

@@ -1,9 +0,0 @@
<?php
require_once 'AuthController.php';
$authController = new AuthController();
$token = $_POST['token'] ?? '';
$isValid = $authController->validateToken($token);
echo json_encode(['valid' => $isValid]);

View File

@@ -1,34 +0,0 @@
<?php
class WebhookController {
public function __construct() {
$this->authServiceUrl = 'http://nibiru-auth-api:9000/validateToken.php';
}
private function validateToken($token) {
// Make a request to the auth service to validate the token
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->authServiceUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['token' => $token]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
return $result && isset($result['valid']) && $result['valid'];
}
public function handleWebhook() {
$headers = getallheaders();
$token = $headers['Authorization'] ?? '';
if (!$this->validateToken($token)) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
return;
}
// Handle the webhook logic here
}
}

View File

@@ -1,29 +0,0 @@
{
"name": "vendor_name/nibiru-framework-agent",
"description": "A project to interact with GitHub API using PHP",
"authors": [
{
"name": "Stephan Kasdorf",
"email": "stephan.kasdorf@bittomine.com"
}
],
"require": {
"php": "^8.3",
"guzzlehttp/guzzle": "^7.3"
},
"autoload": {
"psr-4": {
"": "src/"
}
},
"scripts": {
"post-install-cmd": [
"chmod -R 777 storage"
]
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
}
}

View File

@@ -1,2 +0,0 @@
<?php
phpinfo();

View File

@@ -1,21 +0,0 @@
<?php
require 'GitHubClient.php';
$token = getenv('GITHUB_TOKEN');
$client = new GitHubClient($token);
// Get the webhook payload
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
if (isset($data['commits'])) {
foreach ($data['commits'] as $commit) {
// Process each commit
echo "Commit message: " . $commit['message'] . "\n";
}
}
// Respond to GitHub
http_response_code(200);
echo json_encode(['status' => 'Webhook received']);