Files
meetletacbfree/classes/registration/store.php
T

140 lines
4.4 KiB
PHP

<?php
// This file is part of Moodle - http://moodle.org/
/**
* Persist MeetLet installation identity + cached runtime authorization.
*
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbfree\registration;
defined('MOODLE_INTERNAL') || die();
/**
* Single-row registration store in meetletacbfree_license.
*/
class store {
public const TABLE = 'meetletacbfree_license';
/**
* @return \stdClass|null
*/
public static function get_record() {
global $DB;
if (!$DB->get_manager()->table_exists(self::TABLE)) {
return null;
}
$rows = $DB->get_records(self::TABLE, null, 'id ASC', '*', 0, 1);
return $rows ? reset($rows) : null;
}
/**
* @return \stdClass
*/
public static function ensure_identity(): \stdClass {
global $DB;
$row = self::get_record();
if ($row && !empty($row->installation_id) && !empty($row->private_key_pem)) {
return $row;
}
$kp = crypto::generate_installation_keypair();
$now = time();
if ($row) {
$row->installation_id = $row->installation_id ?: crypto::random_installation_id();
$row->private_key_pem = $kp['private_pem'];
$row->public_key_pem = $kp['public_pem'];
$row->timemodified = $now;
$DB->update_record(self::TABLE, $row);
return $row;
}
$rec = (object)[
'installation_id' => crypto::random_installation_id(),
'private_key_pem' => $kp['private_pem'],
'public_key_pem' => $kp['public_pem'],
'auth_json' => null,
'license_uuid' => null,
'status' => 'inactive',
'last_error' => null,
'last_validated' => 0,
'timecreated' => $now,
'timemodified' => $now,
];
$rec->id = $DB->insert_record(self::TABLE, $rec);
return $rec;
}
/**
* @param array $fields
*/
public static function update(array $fields): \stdClass {
global $DB;
$row = self::ensure_identity();
foreach ($fields as $k => $v) {
$row->{$k} = $v;
}
$row->timemodified = time();
$DB->update_record(self::TABLE, $row);
return $row;
}
/**
* @return array{payload:array,signature:string}|null
*/
public static function get_authorization(): ?array {
$row = self::get_record();
if (!$row || empty($row->auth_json)) {
return null;
}
$decoded = json_decode($row->auth_json, true);
if (!is_array($decoded) || empty($decoded['payload']) || empty($decoded['signature'])) {
return null;
}
return $decoded;
}
/**
* @return array{code:string,message:string,details?:?array,request_id?:?string,at:int}|null
*/
public static function get_last_error(): ?array {
$row = self::get_record();
if (!$row || empty($row->last_error)) {
return null;
}
$raw = (string)$row->last_error;
$decoded = json_decode($raw, true);
if (is_array($decoded) && !empty($decoded['code'])) {
return [
'code' => (string)$decoded['code'],
'message' => (string)($decoded['message'] ?? $decoded['code']),
'details' => isset($decoded['details']) && is_array($decoded['details']) ? $decoded['details'] : null,
'request_id' => isset($decoded['request_id']) ? (string)$decoded['request_id'] : null,
'at' => (int)($decoded['at'] ?? ($row->timemodified ?? 0)),
];
}
return [
'code' => 'UNKNOWN',
'message' => $raw,
'details' => null,
'request_id' => null,
'at' => (int)($row->timemodified ?? 0),
];
}
public static function rotate_identity(): \stdClass {
$kp = crypto::generate_installation_keypair();
return self::update([
'installation_id' => crypto::random_installation_id(),
'private_key_pem' => $kp['private_pem'],
'public_key_pem' => $kp['public_pem'],
'auth_json' => null,
'license_uuid' => null,
'status' => 'inactive',
'last_error' => null,
'last_validated' => 0,
]);
}
}