Update: 2026-05-03 21:58:11

This commit is contained in:
Hamza-Ayed
2026-05-03 21:58:11 +03:00
parent e1d4917369
commit 089a2b76c0
10 changed files with 668 additions and 9 deletions

View File

@@ -28,10 +28,11 @@ if ($errors) {
$email = $data['email'];
$password = $data['password'];
// 2. DB Check
// 2. DB Check (Using hash for lookup since email is encrypted)
$db = Database::getInstance();
$stmt = $db->prepare("SELECT * FROM users WHERE email = ? LIMIT 1");
$stmt->execute([$email]);
$emailHash = hash('sha256', strtolower($email));
$stmt = $db->prepare("SELECT * FROM users WHERE email_hash = ? LIMIT 1");
$stmt->execute([$emailHash]);
$user = $stmt->fetch();
if (!$user || !password_verify($password, $user['password_hash'])) {
@@ -63,7 +64,7 @@ json_success([
'refresh_token' => $refreshToken,
'user' => [
'id' => $user['id'],
'name' => $user['name'],
'email' => $user['email']
'name' => (App\Core\Encryption::decrypt($user['name']) ?: $user['name']),
'email' => (App\Core\Encryption::decrypt($user['email']) ?: $user['email'])
]
], 'تم تسجيل الدخول بنجاح');

View File

@@ -0,0 +1,78 @@
<?php
/**
* Create Company Endpoint (Synchronized Schema)
*/
use App\Core\Database;
use App\Core\Encryption;
use App\Core\Validator;
use App\Middleware\AuthMiddleware;
$decoded = AuthMiddleware::check();
if ($decoded['role'] !== 'super_admin' && $decoded['role'] !== 'admin') {
json_error('Unauthorized', 403);
}
$data = input();
// 1. Validation
$errors = Validator::validate($data, [
'name' => 'required',
'tax_identification_number' => 'required'
]);
if ($errors) {
json_error('Validation Failed', 422, $errors);
}
$db = Database::getInstance();
try {
$db->beginTransaction();
// 2. Encrypt sensitive fields
$encryptedName = Encryption::encrypt($data['name']);
$encryptedNameEn = !empty($data['name_en']) ? Encryption::encrypt($data['name_en']) : null;
// Encrypt JoFotara keys if provided
$jofotaraClientId = !empty($data['jofotara_client_id']) ? Encryption::encrypt($data['jofotara_client_id']) : null;
$jofotaraSecretKey = !empty($data['jofotara_secret_key']) ? Encryption::encrypt($data['jofotara_secret_key']) : null;
// 3. Save to Database
$stmt = $db->prepare("
INSERT INTO companies (
tenant_id, name, name_en, tax_identification_number, commercial_registration_number,
city, address, contact_email, contact_phone,
jofotara_client_id_encrypted, jofotara_secret_key_encrypted,
created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$decoded['user_id'], // Using current admin as tenant_id
$encryptedName,
$encryptedNameEn,
$data['tax_identification_number'],
$data['commercial_registration_number'] ?? null,
$data['city'] ?? null,
$data['address'] ?? null,
$data['contact_email'] ?? null,
$data['contact_phone'] ?? null,
$jofotaraClientId,
$jofotaraSecretKey,
date('Y-m-d H:i:s')
]);
$companyId = $db->lastInsertId();
// 4. Pivot link
$stmt = $db->prepare("INSERT INTO user_companies (user_id, company_id, role) VALUES (?, ?, ?)");
$stmt->execute([$decoded['user_id'], $companyId, 'admin']);
$db->commit();
json_success(['id' => $companyId], 'تم إنشاء الشركة بنجاح');
} catch (\Exception $e) {
$db->rollBack();
json_error('حدث خطأ أثناء حفظ البيانات: ' . $e->getMessage(), 500);
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* List Companies Endpoint (Synchronized Schema)
*/
use App\Core\Database;
use App\Core\Encryption;
use App\Middleware\AuthMiddleware;
$decoded = AuthMiddleware::check();
$db = Database::getInstance();
// 1. Super Admin sees ALL companies
if ($decoded['role'] === 'super_admin') {
$stmt = $db->query("SELECT * FROM companies WHERE deleted_at IS NULL");
} else {
// 2. Others see only linked companies
$stmt = $db->prepare("
SELECT c.* FROM companies c
JOIN user_companies uc ON c.id = uc.company_id
WHERE uc.user_id = ? AND c.deleted_at IS NULL
");
$stmt->execute([$decoded['user_id']]);
}
$companies = $stmt->fetchAll();
// 3. Decrypt fields
foreach ($companies as &$company) {
// Decrypt Name
$decryptedName = Encryption::decrypt($company['name']);
$company['name'] = $decryptedName !== false ? $decryptedName : $company['name'];
// Decrypt Name EN
if (!empty($company['name_en'])) {
$decryptedNameEn = Encryption::decrypt($company['name_en']);
$company['name_en'] = $decryptedNameEn !== false ? $decryptedNameEn : $company['name_en'];
}
// Redact JoFotara secrets if returned to UI (or just don't return them)
unset($company['jofotara_client_id_encrypted']);
unset($company['jofotara_secret_key_encrypted']);
unset($company['certificate_password_encrypted']);
}
json_success($companies);

View File

@@ -0,0 +1,56 @@
<?php
/**
* Create User Endpoint (with Encryption)
*/
use App\Core\Database;
use App\Core\Encryption;
use App\Core\Validator;
use App\Middleware\AuthMiddleware;
// 1. Auth Check (Only super_admin or admin can create users)
$decoded = AuthMiddleware::check();
if ($decoded['role'] !== 'super_admin' && $decoded['role'] !== 'admin') {
json_error('Unauthorized', 403);
}
$data = input();
// 2. Validation
$errors = Validator::validate($data, [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'role' => 'required'
]);
if ($errors) {
json_error('Validation Failed', 422, $errors);
}
$db = Database::getInstance();
// 3. Encrypt sensitive data
$encryptedName = Encryption::encrypt($data['name']);
$encryptedEmail = Encryption::encrypt($data['email']);
$emailHash = hash('sha256', strtolower($data['email'])); // For fast lookup during login
// 4. Save to Database
try {
$stmt = $db->prepare("INSERT INTO users (name, email, email_hash, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([
$encryptedName,
$encryptedEmail,
$emailHash,
password_hash($data['password'], PASSWORD_DEFAULT),
$data['role'],
date('Y-m-d H:i:s')
]);
json_success(null, 'تم إضافة المستخدم بنجاح');
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
json_error('البريد الإلكتروني مسجل مسبقاً', 409);
}
json_error('حدث خطأ أثناء حفظ البيانات', 500);
}

View File

@@ -1,9 +1,10 @@
<?php
/**
* Users List Endpoint
* Users List Endpoint (with Decryption)
*/
use App\Core\Database;
use App\Core\Encryption;
use App\Middleware\AuthMiddleware;
// 1. Auth Check
@@ -20,4 +21,14 @@ $stmt = $db->prepare("SELECT id, name, email, role, is_active, created_at FROM u
$stmt->execute();
$users = $stmt->fetchAll();
// 4. Decrypt sensitive data for the UI
foreach ($users as &$user) {
// Try to decrypt. If it fails (e.g. data was plain text), keep original.
$decryptedName = Encryption::decrypt($user['name']);
$user['name'] = $decryptedName !== false ? $decryptedName : $user['name'];
$decryptedEmail = Encryption::decrypt($user['email']);
$user['email'] = $decryptedEmail !== false ? $decryptedEmail : $user['email'];
}
json_success($users);