Add names to API tokens.

This commit is contained in:
2026-05-18 22:22:14 +02:00
parent 30cbb0e1c7
commit 995eca4111
6 changed files with 25 additions and 14 deletions

View File

@@ -30,14 +30,15 @@ class API_apitoken extends API
$api_token = bin2hex(random_bytes(64 / 2)); $api_token = bin2hex(random_bytes(64 / 2));
$api_token_hash = password_hash($api_token, PASSWORD_BCRYPT, ["cost" => 12]); $api_token_hash = password_hash($api_token, PASSWORD_BCRYPT, ["cost" => 12]);
$api_token_expiration_timestamp = strtotime('+1 year'); $api_token_expiration_timestamp = strtotime('+1 year');
$query = "INSERT INTO system_api_tokens (api_token_uuid, user_uuid, api_token, api_token_expiration_timestamp, api_token_created_timestamp) VALUES (UUID(), ?, ?, ?, ?)"; $api_token_name = $this->data['api_token_name'] ?? null;
$query = "INSERT INTO system_api_tokens (api_token_uuid, user_uuid, api_token, api_token_name, api_token_expiration_timestamp, api_token_created_timestamp) VALUES (UUID(), ?, ?, ?, ?, ?)";
$stmt = $this->prepareStatement($query); $stmt = $this->prepareStatement($query);
$stmt->bind_param('ssii', $this->data['user_uuid'], $api_token_hash, $api_token_expiration_timestamp, time()); $created_timestamp = time();
$stmt->bind_param('sssii', $this->data['user_uuid'], $api_token_hash, $api_token_name, $api_token_expiration_timestamp, $created_timestamp);
$this->executeStatement($stmt); $this->executeStatement($stmt);

View File

@@ -37,9 +37,14 @@ if ($API_apitoken->request_method === 'GET') {
# Creates a new API Token. First check if the uuid is correct and then check the permission # Creates a new API Token. First check if the uuid is correct and then check the permission
# After that create a new token, retrieve the newly created api_token and give a response. # After that create a new token, retrieve the newly created api_token and give a response.
$requiredFields = [ $requiredFields = [
'user_uuid' => ['type' => 'uuid'], 'user_uuid' => ['type' => 'uuid']
]; ];
$API_apitoken->validateData($requiredFields);
$optionalFields = [
'api_token_name' => ['type' => 'string']
];
$API_apitoken->validateData($requiredFields, $optionalFields);
# First retrieve the user_uuid from the post and lookup the user # First retrieve the user_uuid from the post and lookup the user
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_users.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_users.php';
@@ -48,8 +53,6 @@ if ($API_apitoken->request_method === 'GET') {
$_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $API_apitoken->data['user_uuid']]]]; $_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $API_apitoken->data['user_uuid']]]];
$user_data = $API_users->getUser()[0]; $user_data = $API_users->getUser()[0];
$API_apitoken->validateData($requiredFields);
if ($API_apitoken->getUserUuid() === $API_apitoken->data['user_uuid']) { if ($API_apitoken->getUserUuid() === $API_apitoken->data['user_uuid']) {
$API_apitoken->checkPermissions('user-apitoken-self', 'RW'); $API_apitoken->checkPermissions('user-apitoken-self', 'RW');
@@ -57,6 +60,7 @@ if ($API_apitoken->request_method === 'GET') {
if ($user_data['user_email'] === 'superuser') { if ($user_data['user_email'] === 'superuser') {
$API_apitoken->apiOutput(401, ['error' => 'You are not authorized to access this resource.']); $API_apitoken->apiOutput(401, ['error' => 'You are not authorized to access this resource.']);
} }
$API_apitoken->checkPermissions('user-apitoken-others', 'RW'); $API_apitoken->checkPermissions('user-apitoken-others', 'RW');
} }

View File

@@ -242,7 +242,7 @@ return [
'api_token' => 'API token', 'api_token' => 'API token',
'api_tokens' => 'API tokens', 'api_tokens' => 'API tokens',
'api_token_copy_new' => 'This token is visible only once. Make sure to copy and save it now if you plan to use it later.', 'api_token_copy_new' => 'This token is visible only once. Make sure to copy and save it now if you plan to use it later.',
'generate_new_api_token' => 'Generate new API token', 'generate_new_api_token' => 'Generate',
'inserve_url' => 'Inserve URL', 'inserve_url' => 'Inserve URL',
'inserve_source' => 'Inserve Configuration', 'inserve_source' => 'Inserve Configuration',
'test_connection' => 'Test Connection', 'test_connection' => 'Test Connection',

View File

@@ -242,7 +242,7 @@ return [
'api_token' => 'API token', 'api_token' => 'API token',
'api_tokens' => 'API tokens', 'api_tokens' => 'API tokens',
'api_token_copy_new' => 'Deze token is alleen nu zichtbaar, kopieer hem nu als je hem later wilt gebruiken.', 'api_token_copy_new' => 'Deze token is alleen nu zichtbaar, kopieer hem nu als je hem later wilt gebruiken.',
'generate_new_api_token' => 'Genereer API token', 'generate_new_api_token' => 'Genereer',
'inserve_url' => 'Inserve URL', 'inserve_url' => 'Inserve URL',
'inserve_source' => 'Inserve Configuratie', 'inserve_source' => 'Inserve Configuratie',
'test_connection' => 'Test Connectie', 'test_connection' => 'Test Connectie',

View File

@@ -275,9 +275,12 @@ if ($user_data) { ?>
<form method="POST" action="/api/v1/user/apitoken/"> <form method="POST" action="/api/v1/user/apitoken/">
<input type="hidden" name="user_uuid" value="<?php echo $user_uuid ?>"> <input type="hidden" name="user_uuid" value="<?php echo $user_uuid ?>">
<input type="hidden" name="_return" value="/userprofile/"> <input type="hidden" name="_return" value="/userprofile/">
<button type="submit" href="#" class="btn btn-primary"> <div class="input-group mb-3">
<input type="text" name="api_token_name" class="form-control" placeholder="API Token name..." aria-label="API Token name..." aria-describedby="button-addon2">
<button type="submit" href="#" class="btn btn-success">
<i class="fa-solid fa-plus"></i> <?php echo __('generate_new_api_token') ?> <i class="fa-solid fa-plus"></i> <?php echo __('generate_new_api_token') ?>
</button> </button>
</div>
</form> </form>
<?php } ?> <?php } ?>
</div> </div>
@@ -286,6 +289,7 @@ if ($user_data) { ?>
<thead> <thead>
<tr> <tr>
<th>Token id</th> <th>Token id</th>
<th>Token Name</th>
<th>Expiration</th> <th>Expiration</th>
<th>Created</th> <th>Created</th>
<th>Last used</th> <th>Last used</th>
@@ -300,11 +304,12 @@ if ($user_data) { ?>
<div class="text-truncate" style="max-width: 200px;" id="<?php echo $token_data['api_token_uuid'] ?>" data-copy-data="<?php echo $token_data['api_token_uuid']; ?>"> <div class="text-truncate" style="max-width: 200px;" id="<?php echo $token_data['api_token_uuid'] ?>" data-copy-data="<?php echo $token_data['api_token_uuid']; ?>">
<?php echo $token_data['api_token_uuid']; ?> <?php echo $token_data['api_token_uuid']; ?>
</div> </div>
<button type="button" class="btn btn-sm btn-outline-secondary" data-copy-target="<?php echo $token_data['api_token_uuid'] ?>" title="Copy Token"> <button type="button" class="btn btn-sm btn-outline-secondary" data-copy-target="<?php echo $token_data['api_token_uuid'] ?>" title="Copy ID">
<i class="fa-solid fa-copy"></i> <i class="fa-solid fa-copy"></i>
</button> </button>
</div> </div>
</td> </td>
<td><?php echo $token_data['api_token_name'] ?></td>
<td><?php showTime($token_data['api_token_expiration_timestamp']) ?></td> <td><?php showTime($token_data['api_token_expiration_timestamp']) ?></td>
<td><?php showTime($token_data['api_token_created_timestamp']) ?></td> <td><?php showTime($token_data['api_token_created_timestamp']) ?></td>
<td><?php showTime($token_data['api_token_last_used_timestamp']) ?></td> <td><?php showTime($token_data['api_token_last_used_timestamp']) ?></td>

1
sql-update-1.2.2.sql Normal file
View File

@@ -0,0 +1 @@
ALTER TABLE `system_api_tokens` ADD COLUMN `api_token_name` CHAR(64) NOT NULL AFTER `api_token`;