diff --git a/README.md b/README.md index bcd8f8b..c7376b6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Zitadel PHP API +# Zitadel PHP API version 1.3.3 With this library you can easily communicate between your PHP projects and Zitadel over a serviceUser. The wrapper is based on the [Zitadel API](https://zitadel.com/docs/apis/introduction/). @@ -53,7 +53,7 @@ try { } ``` -**Add user avatar** +**Add user avatar with path** ```php use ZitadelPhpApi\User\Avatar; @@ -65,7 +65,7 @@ $settings = [ // Add avatar $avatar = new Avatar($settings); -$avatar->setUserId('313871513763708931'); +$avatar->setUserId('319154205375856643'); $avatar->setImagePath('avatar_500x500.png'); try { $avatar->add(); @@ -74,6 +74,38 @@ try { } ``` +**Add user avatar with form** +```html +
+ + + +
+``` +And the php Code: +```php +use ZitadelPhpApi\User\Avatar; + +$settings = [ + "domain" => "", + "serviceUserToken" => "", + "userToken" => "" +]; + +// Add avatar +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // Add avatar + $avatar = new Avatar($settings); + $avatar->setUserId('319154205375856643'); + $avatar->setImagePath($_FILES['file']['tmp_name']); + try { + $avatar->add(); + } catch (Exception $e) { + echo $e->getMessage(); + } +} +``` + **Remove user avatar** ```php use ZitadelPhpApi\User\Avatar; @@ -101,4 +133,4 @@ try { ## License -Zitadel PHP API is released under the Apache 2.0 License. \ No newline at end of file +Zitadel PHP API is released under the Apache 2.0 License. diff --git a/docs/classes/ZitadelPhpApi-Settings-PasswordComplexity.html b/docs/classes/ZitadelPhpApi-Settings-PasswordComplexity.html index eb761cc..314f471 100644 --- a/docs/classes/ZitadelPhpApi-Settings-PasswordComplexity.html +++ b/docs/classes/ZitadelPhpApi-Settings-PasswordComplexity.html @@ -172,6 +172,12 @@

 : string|null +
+ $rawPasswordSettings + +  : bool +
+
$requiresLowercase @@ -230,6 +236,13 @@

Get the minimum length of the password
+
+ getRawPasswoerdSettings() + +  : string +
+
Returns the raw password settings as a JSON string.
+
getResourceOwnerType() @@ -363,6 +376,42 @@

+ +
+

+ $rawPasswordSettings + + + + +

+ + + + + + private + bool + $rawPasswordSettings + + + + + + + +
+
+

+ getRawPasswoerdSettings() + + +

+ + +

Returns the raw password settings as a JSON string.

+ + + public + getRawPasswoerdSettings() : string + +
+
+ + + + + + + +
+
Return values
+ string + — +

The raw password settings as a JSON string.

+
+ +
+
@@ -735,7 +827,7 @@

@@ -778,7 +870,7 @@

@@ -821,7 +913,7 @@

@@ -864,7 +956,7 @@

@@ -907,7 +999,7 @@

@@ -959,7 +1051,7 @@

@@ -1107,6 +1199,7 @@

Parameters

-
Add the avatar to the user. Needs the userToken
+
Add the avatar to the user. Needs the `userToken` +! The user token must have the scope 'urn:zitadel:iam:org:project:id:zitadel:aud'
remove()  : void
-
Remove the user's avatar.
+
Remove the user's avatar with the `serviceUserToken`.
setImagePath() @@ -453,11 +454,12 @@

-

Add the avatar to the user. Needs the userToken

+

Add the avatar to the user. Needs the `userToken` +! The user token must have the scope 'urn:zitadel:iam:org:project:id:zitadel:aud'

public @@ -505,11 +507,11 @@

-

Remove the user's avatar.

+

Remove the user's avatar with the `serviceUserToken`.

public diff --git a/docs/js/searchIndex.js b/docs/js/searchIndex.js index 0b53645..d96d0fb 100644 --- a/docs/js/searchIndex.js +++ b/docs/js/searchIndex.js @@ -750,6 +750,11 @@ Search.appendIndex( "name": "getResourceOwnerType", "summary": "Returns\u0020the\u0020resource\u0020owner\u0020type.", "url": "classes/ZitadelPhpApi-Settings-PasswordComplexity.html#method_getResourceOwnerType" + }, { + "fqsen": "\\ZitadelPhpApi\\Settings\\PasswordComplexity\u003A\u003AgetRawPasswoerdSettings\u0028\u0029", + "name": "getRawPasswoerdSettings", + "summary": "Returns\u0020the\u0020raw\u0020password\u0020settings\u0020as\u0020a\u0020JSON\u0020string.", + "url": "classes/ZitadelPhpApi-Settings-PasswordComplexity.html#method_getRawPasswoerdSettings" }, { "fqsen": "\\ZitadelPhpApi\\Settings\\PasswordComplexity\u003A\u003AsendRequest\u0028\u0029", "name": "sendRequest", @@ -770,6 +775,11 @@ Search.appendIndex( "name": "minLength", "summary": "", "url": "classes/ZitadelPhpApi-Settings-PasswordComplexity.html#property_minLength" + }, { + "fqsen": "\\ZitadelPhpApi\\Settings\\PasswordComplexity\u003A\u003A\u0024rawPasswordSettings", + "name": "rawPasswordSettings", + "summary": "", + "url": "classes/ZitadelPhpApi-Settings-PasswordComplexity.html#property_rawPasswordSettings" }, { "fqsen": "\\ZitadelPhpApi\\Settings\\PasswordComplexity\u003A\u003A\u0024resourceOwnerType", "name": "resourceOwnerType", @@ -853,12 +863,12 @@ Search.appendIndex( }, { "fqsen": "\\ZitadelPhpApi\\User\\Avatar\u003A\u003Aadd\u0028\u0029", "name": "add", - "summary": "Add\u0020the\u0020avatar\u0020to\u0020the\u0020user.\u0020Needs\u0020the\u0020userToken", + "summary": "Add\u0020the\u0020avatar\u0020to\u0020the\u0020user.\u0020Needs\u0020the\u0020\u0060userToken\u0060\n\u0021\u0020The\u0020user\u0020token\u0020must\u0020have\u0020the\u0020scope\u0020\u0027urn\u003Azitadel\u003Aiam\u003Aorg\u003Aproject\u003Aid\u003Azitadel\u003Aaud\u0027", "url": "classes/ZitadelPhpApi-User-Avatar.html#method_add" }, { "fqsen": "\\ZitadelPhpApi\\User\\Avatar\u003A\u003Aremove\u0028\u0029", "name": "remove", - "summary": "Remove\u0020the\u0020user\u0027s\u0020avatar.", + "summary": "Remove\u0020the\u0020user\u0027s\u0020avatar\u0020with\u0020the\u0020\u0060serviceUserToken\u0060.", "url": "classes/ZitadelPhpApi-User-Avatar.html#method_remove" }, { "fqsen": "\\ZitadelPhpApi\\User\\Avatar\u003A\u003A\u0024settings", diff --git a/src/Session/Create.php b/src/Session/Create.php index 87d3cf3..686541d 100644 --- a/src/Session/Create.php +++ b/src/Session/Create.php @@ -12,7 +12,7 @@ */ class Create { - private array $settings; + protected array $settings; private string $sessionId; private string $sessionToken; private string $smsCode; diff --git a/src/Session/Get.php b/src/Session/Get.php index 1df74a6..e3c7d93 100644 --- a/src/Session/Get.php +++ b/src/Session/Get.php @@ -11,7 +11,7 @@ */ class Get { - private array $settings; + protected array $settings; private string $sessionId; private string $sessionToken; private string $creationDate; diff --git a/src/Session/Terminate.php b/src/Session/Terminate.php index d4dae03..ed30a09 100644 --- a/src/Session/Terminate.php +++ b/src/Session/Terminate.php @@ -9,7 +9,7 @@ */ class Terminate { - private array $settings; + protected array $settings; private string $sessionId; private string $sessionToken; diff --git a/src/Session/Update.php b/src/Session/Update.php index f4baa80..e828a22 100644 --- a/src/Session/Update.php +++ b/src/Session/Update.php @@ -12,7 +12,7 @@ */ class Update { - private array $settings; + protected array $settings; private string $sessionId; private string $smsCode; private string $emailCode; diff --git a/src/Settings/ActiveIDP.php b/src/Settings/ActiveIDP.php index 23a1fdf..166d89c 100644 --- a/src/Settings/ActiveIDP.php +++ b/src/Settings/ActiveIDP.php @@ -6,7 +6,7 @@ class ActiveIDP { - private array $settings; + protected array $settings; private ?string $orgId = null; private array $identityProviders; @@ -28,6 +28,7 @@ public function get(): array public function sendRequest(): void { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/settings/login/idps?ctx.orgId=" . $this->orgId, diff --git a/src/Settings/BasicInformation.php b/src/Settings/BasicInformation.php index 3c5465b..49b8881 100644 --- a/src/Settings/BasicInformation.php +++ b/src/Settings/BasicInformation.php @@ -6,7 +6,7 @@ class BasicInformation { - private array $settings; + protected array $settings; private string $defaultOrgId; private string $defaultLanguage; private array $supportedLanguages; @@ -34,6 +34,7 @@ public function getSupportedLanguages(): array public function sendRequest(): void { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/settings", diff --git a/src/Settings/LoginSettings.php b/src/Settings/LoginSettings.php index 6cecef7..0eba5a7 100644 --- a/src/Settings/LoginSettings.php +++ b/src/Settings/LoginSettings.php @@ -9,7 +9,7 @@ */ class LoginSettings { - private array $settings; + protected array $settings; private ?string $orgId = null; private bool $allowUsernamePassword; private bool $allowRegister; @@ -145,6 +145,7 @@ public function forceMfaLocalOnly(): bool public function sendRequest(): void { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/settings/login?ctx.orgId=" . $this->orgId, diff --git a/src/Settings/PasswordComplexity.php b/src/Settings/PasswordComplexity.php index bcd3620..6f0587a 100644 --- a/src/Settings/PasswordComplexity.php +++ b/src/Settings/PasswordComplexity.php @@ -9,9 +9,10 @@ */ class PasswordComplexity { - private array $settings; + protected array $settings; private ?string $orgId = null; private ?int $minLength; + private array $rawPasswordSettings; private bool $requiresUppercase; private bool $requiresLowercase; private bool $requiresNumber; @@ -99,6 +100,16 @@ public function getResourceOwnerType(): string return $this->resourceOwnerType; } + /** + * Returns the raw password settings as a JSON string. + * + * @return array The raw password settings as a JSON string. + */ + public function getRawPasswordSettings(): array + { + return $this->rawPasswordSettings; + } + /** * Send a GET request to the ZITADEL API to retrieve the current password complexity settings. * @@ -108,6 +119,7 @@ public function getResourceOwnerType(): string public function sendRequest(): void { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/settings/password/complexity?ctx.orgId=" . $this->orgId, @@ -132,6 +144,7 @@ public function sendRequest(): void throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); } else { $response = $response->settings; + $this->rawPasswordSettings = (array) $response ?? []; $this->minLength = $response->minLength ?? null; $this->requiresUppercase = $response->requiresUppercase ?? ""; $this->requiresLowercase = $response->requiresLowercase ?? ""; diff --git a/src/User/Account.php b/src/User/Account.php index 79157b1..2ace3f0 100644 --- a/src/User/Account.php +++ b/src/User/Account.php @@ -9,7 +9,7 @@ */ class Account { - private array $settings; + protected array $settings; private int $userid; private string $action; @@ -94,8 +94,8 @@ public function unlock(): void private function request(): void { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); - curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/$this->action", CURLOPT_RETURNTRANSFER => true, diff --git a/src/User/Avatar.php b/src/User/Avatar.php index a5a3094..7041099 100644 --- a/src/User/Avatar.php +++ b/src/User/Avatar.php @@ -9,7 +9,7 @@ */ class Avatar { - private array $settings; + protected array $settings; private int $userid; private String $boundary; private String $postData; @@ -73,7 +73,8 @@ public function setImagePath(string $avatar): void } /** - * Add the avatar to the user. Needs the userToken + * Add the avatar to the user. Needs the `userToken` + * ! The user token must have the scope 'urn:zitadel:iam:org:project:id:zitadel:aud' * * @throws Exception If there's an error * @return void @@ -81,14 +82,15 @@ public function setImagePath(string $avatar): void public function add() { $token = $this->settings["userToken"]; - $curl = curl_init(); + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/assets/v1/users/me/avatar", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_FOLLOWLOCATION => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $this->postData, @@ -98,7 +100,7 @@ public function add() "Authorization: Bearer $token" ), )); - + $response = json_decode(curl_exec($curl)); curl_close($curl); @@ -108,7 +110,7 @@ public function add() } /** - * Remove the user's avatar. + * Remove the user's avatar with the `serviceUserToken`. * * @return void * @throws Exception If an error occurs during the request to remove the avatar from the server. @@ -116,8 +118,8 @@ public function add() public function remove() { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); - curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/$this->userid/avatar", CURLOPT_RETURNTRANSFER => true, diff --git a/src/User/Create.php b/src/User/Create.php index 6963a61..4803118 100644 --- a/src/User/Create.php +++ b/src/User/Create.php @@ -9,7 +9,7 @@ */ class Create { - private array $settings; + protected array $settings; private array $request; /** @@ -128,7 +128,9 @@ public function setGender(string $gender): void public function setEmail(string $email, bool $isVerified = false): void { $this->request["email"]["email"] = $email; - $this->request["email"]["isVerified"] = $isVerified; + if($isVerified) { + $this->request["email"]["isVerified"] = $isVerified; + } } /** @@ -141,7 +143,9 @@ public function setEmail(string $email, bool $isVerified = false): void public function setPhone(string $phone, bool $isVerified = false): void { $this->request["phone"]["phone"] = $phone; - $this->request["phone"]["isVerified"] = $isVerified; + if($isVerified) { + $this->request["phone"]["isVerified"] = $isVerified; + } } /** @@ -192,12 +196,13 @@ public function addIDPLink(int $idpId, string $userId, string $userName): void /** * Create the new user and sends the data to Zitadel * - * @return void + * @return string zitadel_user_id * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails */ public function create() { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/human", @@ -221,5 +226,7 @@ public function create() if (isset($response->code)) { throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); } + + return $response->userId; } } diff --git a/src/User/Delete.php b/src/User/Delete.php index 4148ae7..8e57278 100644 --- a/src/User/Delete.php +++ b/src/User/Delete.php @@ -12,7 +12,7 @@ */ class Delete { - private array $settings; + protected array $settings; private int $userid; /** @@ -45,6 +45,7 @@ public function setUserId(int $userid) public function delete() { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid", diff --git a/src/User/Edit.php b/src/User/Edit.php index 22c68a4..c0a4285 100644 --- a/src/User/Edit.php +++ b/src/User/Edit.php @@ -10,7 +10,7 @@ */ class Edit { - private array $settings; + protected array $settings; private int $userid; private array $request; @@ -106,6 +106,17 @@ public function setGender(string $gender) $this->request["profile"]["gender"] = "GENDER_UNSPECIFIED"; } } + + /** + * Change the email address + * + * @param $email string Email + * @return void + */ + public function setEmail(string $email) + { + $this->request["email"]["email"] = $email; + } /** * Change the user data and sends the data to Zitadel @@ -116,6 +127,7 @@ public function setGender(string $gender) public function edit() { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/human/$this->userid", diff --git a/src/User/Email.php b/src/User/Email.php index 3ca9a5b..16a811e 100644 --- a/src/User/Email.php +++ b/src/User/Email.php @@ -9,7 +9,7 @@ */ class Email { - private array $settings; + protected array $settings; private int $userid; private string $returnedVerificationCode; @@ -78,7 +78,7 @@ public function changeEmail(string $email) $response = json_decode(curl_exec($curl)); curl_close($curl); - + if (isset($response->code)) { throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); } else { @@ -94,8 +94,9 @@ public function changeEmail(string $email) */ public function resendVerificationCode() { - $curl = curl_init(); $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/email/resend", CURLOPT_RETURNTRANSFER => true, @@ -124,6 +125,41 @@ public function resendVerificationCode() } } + /** + * Get a new Verification code + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function sendVerificationCode() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/email/send", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{}', + CURLOPT_HTTPHEADER => array( + "Content-Type: application/json", + "Accept: application/json", + "Authorization: Bearer $token" + ), + )); + + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code)) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } + } + /** * Verifies an email address with a verification code * @@ -133,8 +169,8 @@ public function resendVerificationCode() public function verify(string $verifyCode): bool { $token = $this->settings["serviceUserToken"]; - $curl = curl_init(); + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/email/verify", CURLOPT_RETURNTRANSFER => true, diff --git a/src/User/Get.php b/src/User/Get.php index f5fecd4..adedecf 100644 --- a/src/User/Get.php +++ b/src/User/Get.php @@ -9,7 +9,7 @@ */ class Get { - private array $settings; + protected array $settings; private int $userid; private string $userState; private string $userName; @@ -33,7 +33,7 @@ class Get * * @param $settings array The settings array */ - public function __construct(array $settings) + public function __construct(array $settings = []) { $this->settings = $settings; } @@ -218,6 +218,7 @@ public function getRawUserData(): string public function fetch() { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid", diff --git a/src/User/Grants.php b/src/User/Grants.php new file mode 100644 index 0000000..3918ad5 --- /dev/null +++ b/src/User/Grants.php @@ -0,0 +1,239 @@ +settings = $settings; + } + + /** + * Set the user id of the user + * + * @param $userid int The user id of the user + * @return void + */ + public function setUserId(int $userid) + { + $this->userid = $userid; + } + + /** + * Set the grant id of the users project + * + * @param $grantId string + * @return void + */ + public function setGrantId(string $grantId) + { + $this->grantId = $grantId; + } + + /** + * Set the project id for the request + * + * @param $projectId string + * @return void + */ + public function setProjectId(string $projectId) + { + $this->request["projectId"] = $projectId; + } + + /** + * Set the project grant id for the request + * Is needed if the user grant is for a granted project and the organization is not the owner of the project. + * + * @param $projectGrantId string + * @return void + */ + public function setProjectGrantId(string $projectGrantId) + { + $this->request["projectGrantId"] = $projectGrantId; + } + + /** + * Set the grant role + * + * @param $role string + * @return void + */ + public function setRoleKey(string $role) + { + $this->request["roleKeys"][] = $role; + } + + /** + * remove the grant role + * + * @param $role string + * @return void + */ + public function removeRoleKey(string $role) + { + $this->removeRoleKeys[] = $role; + } + + /** + * Set given roels to user in Zitadel + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function grantRoles() + { + $roleKeyArray = []; + + // get all roles + $this->getGrantsByUserId(); + + // remove roles + foreach ($this->activeRoleKeys as $roleKey) { + if (!in_array($roleKey, $this->removeRoleKeys)) { + $roleKeyArray[] = $roleKey; + } + } + + // add new to existing roleKeys + $this->request["roleKeys"] = array_unique(array_merge($roleKeyArray, $this->request["roleKeys"] ?? [])); + + // set roles for user + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/$this->userid/grants", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => json_encode($this->request), + CURLOPT_HTTPHEADER => array( + "Accept: application/json", + "Authorization: Bearer $token" + ) + )); + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code) && $response->code != 6) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } + if (isset($response->code) && $response->code == 6) { + $this->updateGrantById(); + } + } + + /** + * Set given roels to user in Zitadel + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function getGrantsByUserId() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/grants/_search", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ + "queries": [ + { + "userIdQuery": { + "userId": "' . $this->userid . '" + } + } + ] + }', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + "Accept: application/json", + "Authorization: Bearer $token" + ) + )); + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code)) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } else { + if (isset($response->result)) { + foreach ($response->result as $grant) { + if ($grant->projectId == $this->request["projectId"]) { + $this->grantId = $grant->id; + + if (isset($grant->roleKeys)) { + $this->activeRoleKeys = $grant->roleKeys; + } + } + } + } + } + } + + /** + * Set given roels to user in Zitadel + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function updateGrantById() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/$this->userid/grants/$this->grantId", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'PUT', + CURLOPT_POSTFIELDS => json_encode($this->request), + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + "Accept: application/json", + "Authorization: Bearer $token" + ) + )); + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code) && $response->code != 9) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } + } +} diff --git a/src/User/IDP.php b/src/User/IDP.php index df9ed4b..f98de7f 100644 --- a/src/User/IDP.php +++ b/src/User/IDP.php @@ -9,7 +9,7 @@ */ class IDP { - private array $settings; + protected array $settings; private int $userid; private string $idpId; private string $idpToken; @@ -212,6 +212,7 @@ public function getIdpProfile(): string public function startFlow() { $token = $this->settings["userToken"]; + $curl = curl_init(); $request = array( "idpId" => $this->idpId, @@ -256,6 +257,7 @@ public function startFlow() public function fetchIdpData() { $token = $this->settings["userToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/idp_intents/$this->idpIntentId", @@ -302,6 +304,7 @@ public function fetchIdpData() public function linkIdpToUser() { $token = $this->settings["serviceUserToken"]; + $request = array( "idpLink" => array( "idpId" => $this->idpId, diff --git a/src/User/Metadata.php b/src/User/Metadata.php new file mode 100644 index 0000000..125f402 --- /dev/null +++ b/src/User/Metadata.php @@ -0,0 +1,237 @@ +settings = $settings; + } + + /** + * Set the user id of the user + * + * @param $userid int The user id of the user + * @return void + */ + public function setUserId(int $userid) + { + $this->userid = $userid; + } + + /** + * Returns the user metadata + * + * @return array + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function getMetaData() : array + { + return $this->metadata; + } + + /** + * Add Metadata to the user Profile (optional). The value will be automatically Base64 encoded. + * + * @param $key string Key + * @param $value string Value + * @return void + */ + public function addMetaData(string $key, string $value): void + { + $this->set_request["metadata"][] = [ + "key" => $key, + "value" => base64_encode($value) + ]; + } + + /** + * Add Metadata Key for deletion + * + * @param $key string Key + * @return void + */ + public function queryMetaDataKey(string $key): void + { + // API v2 + // $this->delete_request["metadata"][] = [ + // "key" => $key + // ]; + + $this->delete_request["keys"][] = $key; + } + + /** + * Add pagination to metadata list + * + * @param $offset int + * @param $limit int + * @param $asc bool + * @return void + */ + public function setPagination(int $offset = 0, int $limit = 0, bool $asc = false): void + { + if($limit > 0){ + // $this->list_request["pagination"] = [ + // "offset" => $offset, + // "limit" => $limit, + // "asc" => $asc + // ]; + $this->list_request["query"] = [ + "offset" => $offset, + "limit" => $limit, + "asc" => $asc + ]; + } + } + + /** + * Add filter to metadata list + * + * @param $key string + * @param $offset string + * @return void + */ + public function setFilters(string $key, string $method = "TEXT_QUERY_METHOD_EQUALS"): void + { + // $this->list_request["filters"][] = [ + // "keyFilter" => [ + // "key" => $key, + // "method" => $method, + // ] + // ]; + $this->list_request["queries"][] = [ + "keyQuery" => [ + "key" => $key, + "method" => $method, + ] + ]; + } + + /** + * Requests the user metadata from Zitadel + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function requestMetaData() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + // CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/metadata", + CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/$this->userid/metadata/_search", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => (isset($this->list_request)) ? json_encode($this->list_request) : "{}", + CURLOPT_HTTPHEADER => array( + "Accept: application/json", + "Authorization: Bearer $token" + ) + )); + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code)) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + }else{ + // $this->metadata = $response->metadata; + $this->metadata = $response->result ?? []; + } + } + + /** + * Set & Change the user metadata in Zitadel + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function setMetaData() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + // CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/metadata", + CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/$this->userid/metadata/_bulk", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => json_encode($this->set_request), + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + "Authorization: Bearer $token" + ) + )); + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code)) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } + } + + /** + * Delete the user metadata from Zitadel + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function deleteMetaData() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + // CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/metadata", + CURLOPT_URL => $this->settings["domain"] . "/management/v1/users/$this->userid/metadata/_bulk", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'DELETE', + CURLOPT_POSTFIELDS => json_encode($this->delete_request), + CURLOPT_HTTPHEADER => array( + "Accept: application/json", + "Authorization: Bearer $token" + ) + )); + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code)) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } + } +} \ No newline at end of file diff --git a/src/User/Password.php b/src/User/Password.php index d2f11ec..bd1fb2f 100644 --- a/src/User/Password.php +++ b/src/User/Password.php @@ -9,7 +9,7 @@ */ class Password { - private array $settings; + protected array $settings; private int $userid; private array $request; private string $verifyCode; @@ -90,6 +90,7 @@ public function getVerifyCode(): string public function change(): bool { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/password", @@ -127,6 +128,7 @@ public function change(): bool public function requestVerifyCode() { $token = $this->settings["serviceUserToken"]; + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/password_reset", @@ -156,4 +158,44 @@ public function requestVerifyCode() $this->verifyCode = $response->verificationCode; } } + + /** + * Request reset link for password reset + * + * @return void + * @throws Exception Returns an exception with an error code and a message if the communication with Zitadel fails + */ + public function sendResetLink() + { + $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); + curl_setopt_array($curl, array( + CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/password_reset", + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => "{ + \"sendLink\": { + \"notificationType\": \"NOTIFICATION_TYPE_Unspecified\" + } + }", + CURLOPT_HTTPHEADER => array( + "Content-Type: application/json", + "Accept: application/json", + "Authorization: Bearer $token" + ), + )); + + $response = json_decode(curl_exec($curl)); + curl_close($curl); + + if (isset($response->code)) { + throw new Exception("Error-Code: " . $response->code . " Message: " . $response->message); + } + } } diff --git a/src/User/Phone.php b/src/User/Phone.php index e01dd50..bd90448 100644 --- a/src/User/Phone.php +++ b/src/User/Phone.php @@ -9,7 +9,7 @@ */ class Phone { - private array $settings; + protected array $settings; private int $userid; private string $returnedVerificationCode; @@ -92,8 +92,9 @@ public function changePhone(string $phone) */ public function resendVerificationCode() { - $curl = curl_init(); $token = $this->settings["serviceUserToken"]; + + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/phone/resend", CURLOPT_RETURNTRANSFER => true, @@ -127,8 +128,8 @@ public function resendVerificationCode() public function verify(string $verifyCode): bool { $token = $this->settings["serviceUserToken"]; - $curl = curl_init(); + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/phone/verify", CURLOPT_RETURNTRANSFER => true, diff --git a/src/User/SetupTwoFactorAuth/Email.php b/src/User/SetupTwoFactorAuth/Email.php index 83daf8e..dcb4af2 100644 --- a/src/User/SetupTwoFactorAuth/Email.php +++ b/src/User/SetupTwoFactorAuth/Email.php @@ -9,7 +9,7 @@ */ class Email { - private array $settings; + protected array $settings; private int $userid; /** @@ -65,8 +65,8 @@ public function remove() private function request(string $action) { $token = $this->settings["userToken"]; - $curl = curl_init(); + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/otp_email", CURLOPT_RETURNTRANSFER => true, diff --git a/src/User/SetupTwoFactorAuth/SMS.php b/src/User/SetupTwoFactorAuth/SMS.php index 3789f79..62aba48 100644 --- a/src/User/SetupTwoFactorAuth/SMS.php +++ b/src/User/SetupTwoFactorAuth/SMS.php @@ -9,7 +9,7 @@ */ class SMS { - private array $settings; + protected array $settings; private int $userid; /** Initialize the SMS OTP setup @@ -54,8 +54,8 @@ public function remove() private function request() { $token = $this->settings["userToken"]; + $curl = curl_init(); - curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/otp_sms", CURLOPT_RETURNTRANSFER => true, diff --git a/src/User/SetupTwoFactorAuth/TOTP.php b/src/User/SetupTwoFactorAuth/TOTP.php index 48b3933..4d00c2a 100644 --- a/src/User/SetupTwoFactorAuth/TOTP.php +++ b/src/User/SetupTwoFactorAuth/TOTP.php @@ -10,7 +10,7 @@ */ class TOTP { - private array $settings; + protected array $settings; private int $userid; private string $secret; private string $totpUri; @@ -65,8 +65,8 @@ public function getQRCode(): string public function start() { $token = $this->settings["userToken"]; - $curl = curl_init(); + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/totp", CURLOPT_RETURNTRANSFER => true, @@ -101,8 +101,8 @@ public function start() public function verify($verifyCode): bool { $token = $this->settings["userToken"]; - $curl = curl_init(); + $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $this->settings["domain"] . "/v2/users/$this->userid/totp/verify", CURLOPT_RETURNTRANSFER => true,