|
22 | 22 | use OCA\Libresign\Service\ReminderService; |
23 | 23 | use OCA\Libresign\Service\SignatureBackgroundService; |
24 | 24 | use OCA\Libresign\Service\SignatureTextService; |
| 25 | +use OCA\Libresign\Settings\Admin; |
25 | 26 | use OCP\AppFramework\Http; |
26 | 27 | use OCP\AppFramework\Http\Attribute\ApiRoute; |
27 | 28 | use OCP\AppFramework\Http\Attribute\NoCSRFRequired; |
@@ -662,4 +663,117 @@ public function reminderSave( |
662 | 663 | } |
663 | 664 | return new DataResponse($response); |
664 | 665 | } |
| 666 | + |
| 667 | + /** |
| 668 | + * Set TSA configuration values with proper sensitive data handling |
| 669 | + * |
| 670 | + * Only saves configuration if tsa_url is provided. Automatically manages |
| 671 | + * username/password fields based on authentication type. |
| 672 | + * |
| 673 | + * @param string|null $tsa_url TSA server URL (required for saving) |
| 674 | + * @param string|null $tsa_policy_oid TSA policy OID |
| 675 | + * @param string|null $tsa_auth_type Authentication type (none|basic), defaults to 'none' |
| 676 | + * @param string|null $tsa_username Username for basic authentication |
| 677 | + * @param string|null $tsa_password Password for basic authentication (stored as sensitive data) |
| 678 | + * @return DataResponse<Http::STATUS_OK, array{status: 'success'}, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{status: 'error', message: string}, array{}> |
| 679 | + * |
| 680 | + * 200: OK |
| 681 | + * 400: Validation error |
| 682 | + */ |
| 683 | + #[NoCSRFRequired] |
| 684 | + #[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/admin/tsa', requirements: ['apiVersion' => '(v1)'])] |
| 685 | + public function setTsaConfig( |
| 686 | + ?string $tsa_url = null, |
| 687 | + ?string $tsa_policy_oid = null, |
| 688 | + ?string $tsa_auth_type = null, |
| 689 | + ?string $tsa_username = null, |
| 690 | + ?string $tsa_password = null, |
| 691 | + ): DataResponse { |
| 692 | + if (empty($tsa_url)) { |
| 693 | + return $this->deleteTsaConfig(); |
| 694 | + } |
| 695 | + |
| 696 | + $trimmedUrl = trim($tsa_url); |
| 697 | + if (!filter_var($trimmedUrl, FILTER_VALIDATE_URL) |
| 698 | + || !in_array(parse_url($trimmedUrl, PHP_URL_SCHEME), ['http', 'https'])) { |
| 699 | + return new DataResponse([ |
| 700 | + 'status' => 'error', |
| 701 | + 'message' => 'Invalid URL format' |
| 702 | + ], Http::STATUS_BAD_REQUEST); |
| 703 | + } |
| 704 | + |
| 705 | + $this->appConfig->setValueString(Application::APP_ID, 'tsa_url', $trimmedUrl); |
| 706 | + |
| 707 | + if (empty($tsa_policy_oid)) { |
| 708 | + $this->appConfig->deleteKey(Application::APP_ID, 'tsa_policy_oid'); |
| 709 | + } else { |
| 710 | + $trimmedOid = trim($tsa_policy_oid); |
| 711 | + if (!preg_match('/^[0-9]+(\.[0-9]+)*$/', $trimmedOid)) { |
| 712 | + return new DataResponse([ |
| 713 | + 'status' => 'error', |
| 714 | + 'message' => 'Invalid OID format' |
| 715 | + ], Http::STATUS_BAD_REQUEST); |
| 716 | + } |
| 717 | + $this->appConfig->setValueString(Application::APP_ID, 'tsa_policy_oid', $trimmedOid); |
| 718 | + } |
| 719 | + |
| 720 | + $authType = $tsa_auth_type ?? 'none'; |
| 721 | + $this->appConfig->setValueString(Application::APP_ID, 'tsa_auth_type', $authType); |
| 722 | + |
| 723 | + if ($authType === 'basic') { |
| 724 | + $hasUsername = !empty($tsa_username); |
| 725 | + $hasPassword = !empty($tsa_password) && $tsa_password !== Admin::PASSWORD_PLACEHOLDER; |
| 726 | + |
| 727 | + if (!$hasUsername && !$hasPassword) { |
| 728 | + return new DataResponse([ |
| 729 | + 'status' => 'error', |
| 730 | + 'message' => 'Username and password are required for basic authentication' |
| 731 | + ], Http::STATUS_BAD_REQUEST); |
| 732 | + } elseif (!$hasUsername) { |
| 733 | + return new DataResponse([ |
| 734 | + 'status' => 'error', |
| 735 | + 'message' => 'Username is required' |
| 736 | + ], Http::STATUS_BAD_REQUEST); |
| 737 | + } elseif (!$hasPassword) { |
| 738 | + return new DataResponse([ |
| 739 | + 'status' => 'error', |
| 740 | + 'message' => 'Password is required' |
| 741 | + ], Http::STATUS_BAD_REQUEST); |
| 742 | + } |
| 743 | + |
| 744 | + $this->appConfig->setValueString(Application::APP_ID, 'tsa_username', trim($tsa_username)); |
| 745 | + $this->appConfig->setValueString( |
| 746 | + Application::APP_ID, |
| 747 | + key: 'tsa_password', |
| 748 | + value: $tsa_password, |
| 749 | + sensitive: true, |
| 750 | + ); |
| 751 | + } else { |
| 752 | + $this->appConfig->deleteKey(Application::APP_ID, 'tsa_username'); |
| 753 | + $this->appConfig->deleteKey(Application::APP_ID, 'tsa_password'); |
| 754 | + } |
| 755 | + |
| 756 | + return new DataResponse(['status' => 'success']); |
| 757 | + } |
| 758 | + |
| 759 | + /** |
| 760 | + * Delete TSA configuration |
| 761 | + * |
| 762 | + * Delete all TSA configuration fields from the application settings. |
| 763 | + * |
| 764 | + * @return DataResponse<Http::STATUS_OK, array{status: 'success'}, array{}> |
| 765 | + * |
| 766 | + * 200: OK |
| 767 | + */ |
| 768 | + #[NoCSRFRequired] |
| 769 | + #[ApiRoute(verb: 'DELETE', url: '/api/{apiVersion}/admin/tsa', requirements: ['apiVersion' => '(v1)'])] |
| 770 | + public function deleteTsaConfig(): DataResponse { |
| 771 | + $fields = ['tsa_url', 'tsa_policy_oid', 'tsa_auth_type', 'tsa_username', 'tsa_password']; |
| 772 | + |
| 773 | + foreach ($fields as $field) { |
| 774 | + $this->appConfig->deleteKey(Application::APP_ID, $field); |
| 775 | + } |
| 776 | + |
| 777 | + return new DataResponse(['status' => 'success']); |
| 778 | + } |
665 | 779 | } |
0 commit comments