diff --git a/app/modules_app/auth/login.php b/app/modules_app/auth/login.php index f873362..bef8dde 100644 --- a/app/modules_app/auth/login.php +++ b/app/modules_app/auth/login.php @@ -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']) ] ], 'تم تسجيل الدخول بنجاح'); diff --git a/app/modules_app/companies/create.php b/app/modules_app/companies/create.php new file mode 100644 index 0000000..058be0c --- /dev/null +++ b/app/modules_app/companies/create.php @@ -0,0 +1,78 @@ + '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); +} diff --git a/app/modules_app/companies/index.php b/app/modules_app/companies/index.php new file mode 100644 index 0000000..75eed8d --- /dev/null +++ b/app/modules_app/companies/index.php @@ -0,0 +1,46 @@ +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); diff --git a/app/modules_app/users/create.php b/app/modules_app/users/create.php new file mode 100644 index 0000000..83b9cbe --- /dev/null +++ b/app/modules_app/users/create.php @@ -0,0 +1,56 @@ + '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); +} diff --git a/app/modules_app/users/index.php b/app/modules_app/users/index.php index c5ab614..3193e34 100644 --- a/app/modules_app/users/index.php +++ b/app/modules_app/users/index.php @@ -1,9 +1,10 @@ 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); diff --git a/public/index.php b/public/index.php index d58f3dd..51363a3 100644 --- a/public/index.php +++ b/public/index.php @@ -20,6 +20,9 @@ $routes = [ 'v1/auth/refresh' => ['POST', 'auth/refresh.php'], 'v1/auth/logout' => ['POST', 'auth/logout.php'], 'v1/users' => ['GET', 'users/index.php'], + 'v1/users/create' => ['POST', 'users/create.php'], + 'v1/companies' => ['GET', 'companies/index.php'], + 'v1/companies/create' => ['POST', 'companies/create.php'], 'v1/dashboard/stats' => ['GET', 'dashboard/stats.php'], ]; diff --git a/public/shell.php b/public/shell.php index b5652db..69bf140 100644 --- a/public/shell.php +++ b/public/shell.php @@ -30,6 +30,7 @@
| اسم الشركة | +الرقم الضريبي | +رقم التسجيل | +تاريخ الإضافة | +
|---|---|---|---|
| + | + | + | + |