DSP Project first push, date: 29/01/2026
This commit is contained in:
59
scripts/seed_jupyterhub_client.php
Normal file
59
scripts/seed_jupyterhub_client.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
// scripts/seed_jupyterhub_client.php
|
||||
// Inserts or updates the JupyterHub OAuth client using environment values.
|
||||
|
||||
require_once __DIR__ . '/../config.php';
|
||||
|
||||
$clientId = getenv('DSP_OAUTH_CLIENT_ID');
|
||||
$clientSecret = getenv('DSP_OAUTH_CLIENT_SECRET');
|
||||
$redirectUris = getenv('DSP_OAUTH_REDIRECT_URIS') ?: (getenv('JUPYTERHUB_OAUTH_CALLBACK') ?: '');
|
||||
$allowedScopes = getenv('DSP_OAUTH_ALLOWED_SCOPES') ?: 'profile';
|
||||
|
||||
if (!$clientId || !$clientSecret || !$redirectUris) {
|
||||
fwrite(STDERR, "Missing DSP_OAUTH_CLIENT_ID, DSP_OAUTH_CLIENT_SECRET, or redirect URIs.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$clientName = getenv('DSP_OAUTH_CLIENT_NAME') ?: 'DSP JupyterHub';
|
||||
$hashedSecret = password_hash($clientSecret, PASSWORD_DEFAULT);
|
||||
|
||||
$query = <<<SQL
|
||||
INSERT INTO dsp_oauth_clients (
|
||||
client_id,
|
||||
client_name,
|
||||
client_secret_hash,
|
||||
redirect_uris,
|
||||
allowed_scopes,
|
||||
is_confidential,
|
||||
is_revoked,
|
||||
updated_at
|
||||
) VALUES (
|
||||
:client_id,
|
||||
:client_name,
|
||||
:client_secret_hash,
|
||||
:redirect_uris,
|
||||
:allowed_scopes,
|
||||
1,
|
||||
0,
|
||||
NOW()
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
client_name = VALUES(client_name),
|
||||
client_secret_hash = VALUES(client_secret_hash),
|
||||
redirect_uris = VALUES(redirect_uris),
|
||||
allowed_scopes = VALUES(allowed_scopes),
|
||||
is_confidential = 1,
|
||||
is_revoked = 0,
|
||||
updated_at = NOW();
|
||||
SQL;
|
||||
|
||||
$stmt = $pdo->prepare($query);
|
||||
$stmt->execute([
|
||||
':client_id' => $clientId,
|
||||
':client_name' => $clientName,
|
||||
':client_secret_hash' => $hashedSecret,
|
||||
':redirect_uris' => $redirectUris,
|
||||
':allowed_scopes' => $allowedScopes,
|
||||
]);
|
||||
|
||||
echo "OAuth client '{$clientId}' has been seeded.\n";
|
||||
88
scripts/trigger_workspace_sync.php
Normal file
88
scripts/trigger_workspace_sync.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* CLI utility to re-run the Jupyter workspace sync for any existing user directories.
|
||||
*
|
||||
* Usage:
|
||||
* php scripts/trigger_workspace_sync.php # scans existing workspace folders
|
||||
* php scripts/trigger_workspace_sync.php 12 18 42 # optional explicit person IDs
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../config.php';
|
||||
require_once __DIR__ . '/../classes/DataSource.php';
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
fwrite(STDERR, "This script must be executed from the command line.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$workspaceRoot = realpath(__DIR__ . '/../uploads/jupyter_workspace');
|
||||
if ($workspaceRoot === false) {
|
||||
fwrite(STDERR, "Workspace root not found. Expected at uploads/jupyter_workspace.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$dataSourceManager = new DataSource($pdo);
|
||||
|
||||
$targetPersonIds = [];
|
||||
|
||||
// Allow explicit person IDs to be passed via CLI arguments.
|
||||
foreach (array_slice($argv, 1) as $arg) {
|
||||
if (ctype_digit($arg)) {
|
||||
$targetPersonIds[] = (int) $arg;
|
||||
}
|
||||
}
|
||||
|
||||
// If no explicit IDs provided, infer from existing workspace directories.
|
||||
if (empty($targetPersonIds)) {
|
||||
$iterator = new DirectoryIterator($workspaceRoot);
|
||||
foreach ($iterator as $entry) {
|
||||
if ($entry->isDot() || !$entry->isDir()) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^user_(\d+)$/', $entry->getFilename(), $matches)) {
|
||||
$targetPersonIds[] = (int) $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$targetPersonIds = array_values(array_unique($targetPersonIds));
|
||||
sort($targetPersonIds);
|
||||
|
||||
if (empty($targetPersonIds)) {
|
||||
fwrite(STDOUT, "No user workspace directories detected; nothing to sync.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fwrite(STDOUT, "Preparing workspaces for person IDs: " . implode(', ', $targetPersonIds) . "\n");
|
||||
|
||||
$exitCode = 0;
|
||||
|
||||
foreach ($targetPersonIds as $personId) {
|
||||
try {
|
||||
$result = $dataSourceManager->prepareJupyterWorkspace($personId, $workspaceRoot);
|
||||
$syncedCount = count($result['synced'] ?? []);
|
||||
$missingCount = count($result['missing'] ?? []);
|
||||
fwrite(
|
||||
STDOUT,
|
||||
sprintf(
|
||||
"✔ person_id=%d synced=%d missing=%d dir=%s\n",
|
||||
$personId,
|
||||
$syncedCount,
|
||||
$missingCount,
|
||||
$result['workspace_dir'] ?? 'N/A'
|
||||
)
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
fwrite(
|
||||
STDERR,
|
||||
sprintf(
|
||||
"✖ person_id=%d failed: %s\n",
|
||||
$personId,
|
||||
$e->getMessage()
|
||||
)
|
||||
);
|
||||
$exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
exit($exitCode);
|
||||
Reference in New Issue
Block a user