diff --git a/.gitignore b/.gitignore index 1d2be6c..32665be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /tests/System/processed/ /tests/Integration/Importers/processed/ -/tests/UI/processed-ui-screenshots/ \ No newline at end of file +/tests/UI/processed-ui-screenshots/ +.codex \ No newline at end of file diff --git a/API.php b/API.php index 1ca7cf7..04c001e 100644 --- a/API.php +++ b/API.php @@ -37,7 +37,27 @@ public function __construct( public function getClients(): array { Piwik::checkUserHasSuperUserAccess(); - return $this->clientModel->all(); + return array_map([$this, 'sanitizeClient'], $this->clientModel->all()); + } + + /** + * Returns one OAuth2 client configured in Matomo (super users only). + * + * @param string $clientId 32-character hexadecimal client identifier. + * @return array + */ + public function getClient(string $clientId): array + { + Piwik::checkUserHasSuperUserAccess(); + + $clientId = $this->assertValidClientId($clientId); + $client = $this->clientModel->find($clientId); + + if (empty($client)) { + throw new \InvalidArgumentException(Piwik::translate('OAuth2_ClientNotFound')); + } + + return $this->sanitizeClient($client); } /** @@ -76,42 +96,75 @@ public function createClient(string $name, array $grantTypes, string $scope, $re { Piwik::checkUserHasSuperUserAccess(); - $type = $type === 'public' ? 'public' : 'confidential'; + $data = $this->buildValidatedClientData( + $name, + $grantTypes, + $scope, + $redirectUris, + $description, + $type, + $active + ); - $redirects = is_array($redirectUris) ? $redirectUris : preg_split('/[\r\n]+/', (string) $redirectUris); - if ($redirects === false) { - $redirects = []; - } - $redirects = array_values(array_filter(array_map('trim', $redirects), static function ($value) { - return $value !== ''; - })); + $result = $this->clientManager->create([ + 'name' => $data['name'], + 'description' => $data['description'], + 'redirect_uris' => $data['redirect_uris'], + 'grant_types' => $data['grant_types'], + 'scopes' => $data['scopes'], + 'type' => $data['type'], + 'active' => $data['active'], + ], Piwik::getCurrentUserLogin()); - $grantTypes = array_values(array_filter(array_map('trim', (array) $grantTypes), static function ($value) { - return $value !== ''; - })); - $grantTypes = $this->validateGrantTypes($grantTypes); + $result['client'] = $this->sanitizeClient($result['client']); - $this->validateRedirectUris($redirects, $grantTypes); + return $result; + } - if ($type === 'public' && in_array('client_credentials', $grantTypes, true)) { - throw new \InvalidArgumentException(Piwik::translate('OAuth2_ClientCredentialsExceptionPublicClient')); - } + /** + * Updates an OAuth2 client and optionally returns a newly generated secret. + * + * @param string $clientId 32-character hexadecimal client identifier. + * @param string $name Display name shown in the Matomo UI. + * @param string[] $grantTypes Grant types to enable. + * @param string $scope Scope identifier to allow. + * @param string|string[] $redirectUris Allowed redirect URIs. + * @param string $description Optional description for administrators. + * @param string $type `confidential` or `public`. + * @param string $active `'1'` to enable the client or `'0'` to disable it. + * @return array{client: array, secret: string|null} + */ + public function updateClient(string $clientId, string $name, array $grantTypes, string $scope, $redirectUris = [], string $description = '', string $type = 'confidential', string $active = '1'): array + { + Piwik::checkUserHasSuperUserAccess(); - $scope = array_values(array_intersect([$scope], $this->scopeRepository->getAllowedScopeIds())); + $clientId = $this->assertValidClientId($clientId); - if (empty($scope)) { - throw new \InvalidArgumentException(Piwik::translate('OAuth2_InvalidScopeValue')); + if (empty($this->clientModel->find($clientId))) { + throw new \InvalidArgumentException(Piwik::translate('OAuth2_ClientNotFound')); } - $result = $this->clientManager->create([ - 'name' => $name, - 'description' => $description, - 'redirect_uris' => $redirects, - 'grant_types' => $grantTypes, - 'scopes' => $scope, - 'type' => $type, - 'active' => $active, - ], Piwik::getCurrentUserLogin()); + $data = $this->buildValidatedClientData( + $name, + $grantTypes, + $scope, + $redirectUris, + $description, + $type, + $active + ); + + $result = $this->clientManager->update($clientId, [ + 'name' => $data['name'], + 'description' => $data['description'], + 'redirect_uris' => $data['redirect_uris'], + 'grant_types' => $data['grant_types'], + 'scopes' => $data['scopes'], + 'type' => $data['type'], + 'active' => $data['active'], + ]); + + $result['client'] = $this->sanitizeClient($result['client']); return $result; } @@ -132,6 +185,10 @@ public function rotateSecret(string $clientId): array Piwik::checkUserHasSuperUserAccess(); $clientId = $this->assertValidClientId($clientId); + $client = $this->getClient($clientId); + if (empty($clientId) || empty($client['type']) || $client['type'] != 'confidential') { + throw new \InvalidArgumentException(Piwik::translate('OAuth2_InvalidClientToRotateSecretExceptionMessage')); + } $secret = $this->clientManager->rotateSecret($clientId); @@ -141,6 +198,25 @@ public function rotateSecret(string $clientId): array ]; } + /** + * Updates whether an OAuth2 client is active (super users only). + * + * @param string $clientId 32-character hexadecimal client identifier. + * @param string $active `'1'` to enable the client or `'0'` to disable it. + * @return array{client: array} + */ + public function setClientActive(string $clientId, string $active): array + { + Piwik::checkUserHasSuperUserAccess(); + + $clientId = $this->assertValidClientId($clientId); + $client = $this->clientManager->setActive($clientId, $active === '1'); + + return [ + 'client' => $this->sanitizeClient($client), + ]; + } + // TODO: Do we require password for confirmation? /** * Deletes an OAuth2 client and its related access tokens, refresh tokens, and auth codes (super users only). @@ -172,6 +248,53 @@ private function assertValidClientId(string $clientId): string return $clientId; } + private function buildValidatedClientData( + string $name, + array $grantTypes, + string $scope, + $redirectUris, + string $description, + string $type, + string $active + ): array { + $type = $type === 'public' ? 'public' : 'confidential'; + + $redirects = is_array($redirectUris) ? $redirectUris : preg_split('/[\r\n]+/', (string) $redirectUris); + if ($redirects === false) { + $redirects = []; + } + $redirects = array_values(array_filter(array_map('trim', $redirects), static function ($value) { + return $value !== ''; + })); + + $grantTypes = array_values(array_filter(array_map('trim', (array) $grantTypes), static function ($value) { + return $value !== ''; + })); + $grantTypes = $this->validateGrantTypes($grantTypes); + + $this->validateRedirectUris($redirects, $grantTypes); + + if ($type === 'public' && in_array('client_credentials', $grantTypes, true)) { + throw new \InvalidArgumentException(Piwik::translate('OAuth2_ClientCredentialsExceptionPublicClient')); + } + + $scope = array_values(array_intersect([$scope], $this->scopeRepository->getAllowedScopeIds())); + + if (empty($scope)) { + throw new \InvalidArgumentException(Piwik::translate('OAuth2_InvalidScopeValue')); + } + + return [ + 'name' => trim($name), + 'description' => $description, + 'redirect_uris' => $redirects, + 'grant_types' => $grantTypes, + 'scopes' => $scope, + 'type' => $type, + 'active' => $active, + ]; + } + private function validateRedirectUris(array $redirectUris, array $grantTypes): void { if (!in_array('authorization_code', $grantTypes, true)) { @@ -206,4 +329,11 @@ private function validateGrantTypes(array $grantTypes): array return array_values(array_unique($grantTypes)); } + + private function sanitizeClient(array $client): array + { + unset($client['secret_hash']); + + return $client; + } } diff --git a/Activity/CreateClient.php b/Activity/CreateClient.php index 8918523..169a48f 100644 --- a/Activity/CreateClient.php +++ b/Activity/CreateClient.php @@ -37,6 +37,6 @@ public function getTranslatedDescription($activityData, $performingUser) { $client = $activityData['client'] ?? []; - return sprintf('created OAuth2 client "%s"', $this->getClientLabel($client)); + return sprintf('created OAuth 2.0 client "%s"', $this->getClientLabel($client)); } } diff --git a/Activity/DeleteClient.php b/Activity/DeleteClient.php index 688f4b5..cc9770c 100644 --- a/Activity/DeleteClient.php +++ b/Activity/DeleteClient.php @@ -40,6 +40,6 @@ public function getTranslatedDescription($activityData, $performingUser) { $client = $activityData['client'] ?? []; - return sprintf('deleted OAuth2 client "%s"', $this->getClientLabel($client)); + return sprintf('deleted OAuth 2.0 client "%s"', $this->getClientLabel($client)); } } diff --git a/Activity/RotateSecret.php b/Activity/RotateSecret.php index e309ff9..a7a4929 100644 --- a/Activity/RotateSecret.php +++ b/Activity/RotateSecret.php @@ -39,6 +39,6 @@ public function getTranslatedDescription($activityData, $performingUser) { $client = $activityData['client'] ?? []; - return sprintf('rotated secret for OAuth2 client "%s"', $this->getClientLabel($client)); + return sprintf('rotated secret for OAuth 2.0 client "%s"', $this->getClientLabel($client)); } } diff --git a/Activity/SetClientActive.php b/Activity/SetClientActive.php new file mode 100644 index 0000000..bde6ffd --- /dev/null +++ b/Activity/SetClientActive.php @@ -0,0 +1,47 @@ + 'v1', + 'client' => $this->formatClientData($client), + 'action' => !empty($client['active']) ? 'resumed' : 'paused', + ]; + } + + public function getTranslatedDescription($activityData, $performingUser) + { + $client = $activityData['client'] ?? []; + $isActive = !empty($client['active']); + + if ($isActive) { + return sprintf('resumed OAuth 2.0 client "%s"', $this->getClientLabel($client)); + } + + return sprintf('paused OAuth 2.0 client "%s"', $this->getClientLabel($client)); + } +} diff --git a/Activity/UpdateClient.php b/Activity/UpdateClient.php new file mode 100644 index 0000000..54a41a0 --- /dev/null +++ b/Activity/UpdateClient.php @@ -0,0 +1,42 @@ + 'v1', + 'client' => $this->formatClientData($client), + 'action' => 'updated', + ]; + } + + public function getTranslatedDescription($activityData, $performingUser) + { + $client = $activityData['client'] ?? []; + + return sprintf('updated OAuth 2.0 client "%s"', $this->getClientLabel($client)); + } +} diff --git a/Controller.php b/Controller.php index cb6cf89..3e7069d 100644 --- a/Controller.php +++ b/Controller.php @@ -44,7 +44,10 @@ public function index() Piwik::checkUserHasSuperUserAccess(); $viewData = [ - 'clients' => $this->clientModel->all(), + 'clients' => array_map(static function (array $client) { + unset($client['secret_hash']); + return $client; + }, $this->clientModel->all()), 'scopes' => $this->scopeRepository->describeScopes(), ]; diff --git a/Diagnostic/OpenSslRsaCheck.php b/Diagnostic/OpenSslRsaCheck.php index f665add..af856ff 100644 --- a/Diagnostic/OpenSslRsaCheck.php +++ b/Diagnostic/OpenSslRsaCheck.php @@ -31,11 +31,11 @@ public function execute() $missing[] = 'openssl_pkey_get_details()'; } - $label = 'OAuth2 OpenSSL RSA support'; + $label = 'OAuth 2.0 OpenSSL RSA support'; if (!empty($missing)) { $comment = 'Missing OpenSSL RSA constant/function(s): ' . implode(', ', $missing) - . '. Enable the PHP OpenSSL extension to generate OAuth2 RSA keys.'; + . '. Enable the PHP OpenSSL extension to generate OAuth 2.0 RSA keys.'; return [DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_ERROR, $comment)]; } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e72bfdd --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/Model/ClientModel.php b/Model/ClientModel.php index 5bb8f1d..edc6c62 100644 --- a/Model/ClientModel.php +++ b/Model/ClientModel.php @@ -24,7 +24,7 @@ public function __construct() public function all(): array { - $rows = Db::fetchAll('SELECT * FROM ' . $this->table . ' ORDER BY name ASC'); + $rows = Db::fetchAll('SELECT * FROM ' . $this->table . ' ORDER BY updated_at DESC'); return array_map([$this, 'hydrate'], $rows); } @@ -70,10 +70,11 @@ public function update(string $clientId, array $data): void $now = Date::now()->getDatetime(); Db::query( - 'UPDATE ' . $this->table . ' SET name = ?, description = ?, redirect_uris = ?, grant_types = ?, scopes = ?, type = ?, active = ?, owner_login = ?, updated_at = ? WHERE client_id = ?', + 'UPDATE ' . $this->table . ' SET name = ?, description = ?, secret_hash = ?, redirect_uris = ?, grant_types = ?, scopes = ?, type = ?, active = ?, owner_login = ?, updated_at = ? WHERE client_id = ?', [ $data['name'], $data['description'] ?? '', + $data['secret_hash'] ?? null, $this->encodeList($data['redirect_uris'] ?? []), $this->encodeList($data['grant_types'] ?? []), $this->encodeList($data['scopes'] ?? []), @@ -95,6 +96,15 @@ public function rotateSecret(string $clientId, ?string $secretHash): void ); } + public function setActive(string $clientId, bool $active): void + { + $now = Date::now()->getDatetime(); + Db::query( + 'UPDATE ' . $this->table . ' SET active = ?, updated_at = ? WHERE client_id = ?', + [$active ? 1 : 0, $now, $clientId] + ); + } + public function delete(string $clientId): void { Db::query('DELETE FROM ' . $this->table . ' WHERE client_id = ?', [$clientId]); diff --git a/OAuth2.php b/OAuth2.php index be86e3a..5e57d90 100644 --- a/OAuth2.php +++ b/OAuth2.php @@ -106,7 +106,10 @@ public function getClientSideTranslationKeys(&$translationKeys) $translationKeys[] = 'OAuth2_AdminDisabled'; $translationKeys[] = 'OAuth2_AdminRotateSecret'; $translationKeys[] = 'OAuth2_AdminDelete'; + $translationKeys[] = 'OAuth2_AdminEdit'; $translationKeys[] = 'OAuth2_AdminCreateTitle'; + $translationKeys[] = 'OAuth2_AdminEditTitle'; + $translationKeys[] = 'OAuth2_AdminBackToClients'; $translationKeys[] = 'OAuth2_AdminName'; $translationKeys[] = 'OAuth2_AdminDescription'; $translationKeys[] = 'OAuth2_AdminType'; @@ -120,9 +123,11 @@ public function getClientSideTranslationKeys(&$translationKeys) $translationKeys[] = 'OAuth2_AdminRedirectUris'; $translationKeys[] = 'OAuth2_AdminActiveLabel'; $translationKeys[] = 'OAuth2_AdminSave'; + $translationKeys[] = 'OAuth2_AdminUpdate'; $translationKeys[] = 'OAuth2_AdminSecretMessage'; $translationKeys[] = 'OAuth2_AdminSecretHelp'; $translationKeys[] = 'OAuth2_AdminCreated'; + $translationKeys[] = 'OAuth2_AdminUpdated'; $translationKeys[] = 'OAuth2_AdminRotated'; $translationKeys[] = 'OAuth2_AdminDeleted'; $translationKeys[] = 'OAuth2_AdminLoading'; @@ -139,6 +144,16 @@ public function getClientSideTranslationKeys(&$translationKeys) $translationKeys[] = 'OAuth2_ErrorXNotProvided'; $translationKeys[] = 'OAuth2_ClientSecret'; $translationKeys[] = 'OAuth2_ClientSecretHelp'; + $translationKeys[] = 'OAuth2_ClientNotFound'; + $translationKeys[] = 'OAuth2_AdminPause'; + $translationKeys[] = 'OAuth2_AdminResume'; + $translationKeys[] = 'OAuth2_AdminResumed'; + $translationKeys[] = 'OAuth2_AdminPaused'; + $translationKeys[] = 'OAuth2_AdminPauseConfirm'; + $translationKeys[] = 'OAuth2_AdminResumeConfirm'; + $translationKeys[] = 'OAuth2_ClientSecretMaskedHelp'; + $translationKeys[] = 'OAuth2_ClientSecretVisibleHelp'; + $translationKeys[] = 'OAuth2_AdminDescriptionPlaceholder'; } public function getTablesInstalled(&$allTablesInstalled) diff --git a/README.md b/README.md index d0e4df3..774bf50 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# OAuth2 Plugin for Matomo +# OAuth 2.0 Plugin for Matomo This plugin adds a **first-party OAuth2 Authorization Server** to Matomo, allowing external applications to securely access Matomo APIs using OAuth2 access tokens instead of `token_auth`. -It supports standard OAuth2 flows including **Authorization Code (PKCE)**, **Client Credentials**, and **Refresh Token**. +It supports standard OAuth 2.0 flows including **Authorization Code (PKCE)**, **Client Credentials**, and **Refresh Token**. --- # Features -- OAuth2 Authorization Server integrated with Matomo +- OAuth 2.0 Authorization Server integrated with Matomo - Manage OAuth clients via **Administration → Platform → OAuth2** (For Matomo Cloud it will be **Administration → Export → OAuth2**) - Supported grant types: - Authorization Code (with PKCE) @@ -49,8 +49,8 @@ Optional cleaner routes can be added: Navigate to: ``` -Administration → Platform → OAuth2 (On-premise) -dministration → Export → OAuth2 (Matomo Cloud) +Administration → Platform → OAuth 2.0 (On-premise) +dministration → Export → OAuth 2.0 (Matomo Cloud) ``` Create a client and configure: diff --git a/Service/ClientManager.php b/Service/ClientManager.php index 16358c0..41cfee8 100644 --- a/Service/ClientManager.php +++ b/Service/ClientManager.php @@ -9,6 +9,7 @@ namespace Piwik\Plugins\OAuth2\Service; +use Piwik\Date; use Piwik\Plugins\OAuth2\Model\AccessTokenModel; use Piwik\Plugins\OAuth2\Model\AuthCodeModel; use Piwik\Plugins\OAuth2\Model\ClientModel; @@ -33,6 +34,7 @@ public function create(array $data, string $ownerLogin): array $type = $this->normalizeType($data['type'] ?? null); $grantTypes = $this->normalizeGrantTypes($data['grant_types'] ?? []); $this->assertGrantTypesAreAllowed($grantTypes, $type); + $now = Date::now()->getDatetime(); $client = $this->clientModel->create([ 'client_id' => $clientId, @@ -44,28 +46,51 @@ public function create(array $data, string $ownerLogin): array 'scopes' => $data['scopes'] ?? [], 'type' => $type, 'active' => $data['active'] ?? true, + 'created_at' => $now, + 'updated_at' => $now, 'owner_login' => $ownerLogin, ]); return ['client' => $client, 'secret' => $secret]; } - public function update(string $clientId, array $data, ?string $ownerLogin = null): void + public function update(string $clientId, array $data): array { + $existingClient = $this->clientModel->find($clientId); + if (empty($existingClient)) { + throw new \InvalidArgumentException('Client not found'); + } + $type = $this->normalizeType($data['type'] ?? null); $grantTypes = $this->normalizeGrantTypes($data['grant_types'] ?? []); $this->assertGrantTypesAreAllowed($grantTypes, $type); + $secret = null; + $secretHash = $existingClient['secret_hash'] ?? null; + $existingType = $this->normalizeType($existingClient['type'] ?? null); + + if ($existingType === 'public' && $type === 'confidential') { + $secret = $this->generateSecret(); + $secretHash = password_hash($secret, PASSWORD_DEFAULT); + } elseif ($type === 'public') { + $secretHash = null; + } + $this->clientModel->update($clientId, [ 'name' => $data['name'], 'description' => $data['description'] ?? '', 'redirect_uris' => $data['redirect_uris'] ?? [], 'grant_types' => $grantTypes, 'scopes' => $data['scopes'] ?? [], + 'secret_hash' => $secretHash, 'type' => $type, 'active' => $data['active'] ?? true, - 'owner_login' => $ownerLogin ?? $data['owner_login'], + 'owner_login' => $data['owner_login'] ?? ($existingClient['owner_login'] ?? null), ]); + + $client = $this->clientModel->find($clientId); + + return ['client' => $client, 'secret' => $secret]; } public function rotateSecret(string $clientId): ?string @@ -76,6 +101,18 @@ public function rotateSecret(string $clientId): ?string return $secret; } + public function setActive(string $clientId, bool $active): array + { + $existingClient = $this->clientModel->find($clientId); + if (empty($existingClient)) { + throw new \InvalidArgumentException('Client not found'); + } + + $this->clientModel->setActive($clientId, $active); + + return $this->clientModel->find($clientId); + } + public function delete(string $clientId): void { $this->refreshTokenModel->deleteByClient($clientId); diff --git a/lang/en.json b/lang/en.json index 5afc6f4..da39c64 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1,6 +1,6 @@ { "OAuth2": { - "PlatformMenu": "OAuth2", + "PlatformMenu": "OAuth 2.0", "AuthorizeTitle": "Authorise %s", "AuthorizeIntro": "%s is requesting access to your Matomo account.", "AuthorizeTextTitle": "is requesting access to your Matomo account", @@ -8,9 +8,9 @@ "RequestedScopes": "Requested scopes", "Allow": "Allow", "Deny": "Deny", - "AdminHeading": "OAuth2 Clients", + "AdminHeading": "OAuth 2.0 Clients", "AdminClients": "Clients", - "AdminNoClients": "No clients configured yet. Create one below.", + "AdminNoClients": "No clients configured yet.", "AdminClientId": "Client ID", "AdminClientCreatedAt": "Creation date", "AdminClientType": "Type", @@ -21,12 +21,18 @@ "AdminActive": "Active", "AdminDisabled": "Disabled", "AdminRotateSecret": "Rotate secret", + "AdminPause": "Pause", + "AdminResume": "Resume", "AdminDelete": "Delete", + "AdminEdit": "Edit", "AdminCreateTitle": "Create client", + "AdminEditTitle": "Edit client", + "AdminBackToClients": "Back to clients", "AdminName": "Name", "AdminNameHelp": "Displayed to users when they authorise the application and in the OAuth client list.", "AdminDescription": "Description", "AdminDescriptionHelp": "Optional description that explains what this client is used for.", + "AdminDescriptionPlaceholder": "The description of the client", "AdminType": "Type", "AdminConfidential": "Confidential", "AdminPublic": "Public", @@ -43,28 +49,38 @@ "AdminActiveLabel": "Active", "AdminActiveHelp": "Disable to block the client from authenticating without deleting it.", "AdminSave": "Save", + "AdminUpdate": "Update", "AdminSecretMessage": "Client secret:", "AdminSecretHelp": "Copy now; it will not be shown again.", - "AdminCreated": "Client %s created", + "AdminCreated": "Client %s created.", + "AdminUpdated": "Client %s updated.", "AdminRotated": "New secret for %s", - "AdminDeleted": "Client %s deleted", - "AdminLoading": "Loading OAuth2 client manager…", + "AdminPaused": "Client %s has been paused successfully.", + "AdminResumed": "Client %s has been resumed successfully.", + "AdminDeleted": "Client %s has been deleted successfully.", + "AdminLoading": "Loading OAuth 2.0 client manager…", "AdminRotateConfirm": "Are you sure you want to rotate the secret for client %s?", + "AdminPauseConfirm": "Are you sure you want to pause client %s?", + "AdminResumeConfirm": "Are you sure you want to resume client %s?", "AdminDeleteConfirm": "Are you sure you want to delete client %s?", "AdminClientsDescriptions": "OAuth clients allow external applications to securely access Matomo data on behalf of a user. Create and manage clients here to integrate Matomo with your own systems or third-party tools.", "AuthorizationCodeGrantDisabled": "Authorization code grant is disabled.", "ClientSecret": "Client secret", - "ClientSecretHelp": "Copy now; it will not be shown again.", + "ClientSecretHelp": "Copy the client secret now, it will not be shown again.", + "ClientSecretVisibleHelp": "Use this secret to authenticate the client securely. It is only shown in full when it is created or rotated.", + "ClientSecretMaskedHelp": "This secret is hidden after it is created or rotated. If you did not copy it, rotate the secret to generate a new one.", "ClientCredentialsExceptionPublicClient": "Public clients cannot use the client_credentials grant type", "ClientIdException": "clientId must be a 32 character hexadecimal string", + "ClientNotFound": "OAuth 2.0 client not found", "ErrorXNotProvided": "Please provide a value for \"%1$s\".", - "EncryptionKeyNotConfigured": "OAuth2 encryption key is not configured.", + "EncryptionKeyNotConfigured": "OAuth 2.0 encryption key is not configured.", "InvalidAuthorizationRequest": "Invalid authorization request.", "InvalidClientScope": "Invalid scope, check the scope mapped to the requested client.", "InvalidScopeValue": "Invalid scope value.", "InvalidRedirectUri": "Invalid redirect_uri", "InvalidGrantTypes": "Unsupported grant_types", "MultipleScopesNotAllowed": "Multiple scopes are not allowed.", + "InvalidClientToRotateSecretExceptionMessage": "Invalid client, please check your client type.", "ServerError": "Server error", "SystemSettingOauthTitle": "OAuth 2.0", "ScopeReadDescription": "Matomo read level access.", diff --git a/plugin.json b/plugin.json index 51e1e1d..915b019 100644 --- a/plugin.json +++ b/plugin.json @@ -1,9 +1,10 @@ { - "name": "Oauth2", - "description": "First-party OAuth2 server for Matomo (authorisation code with PKCE, client credentials, refresh tokens).", + "name": "OAuth2", + "description": "Provide secure access to the Matomo API using scoped permissions. No static credentials.", "version": "0.1.0", "theme": false, "require": { + "php": ">=8.1.0", "matomo": ">=5.0.0-b1,<6.0.0-b1" }, "authors": [ @@ -13,9 +14,20 @@ "homepage": "https://matomo.org" } ], - "license": "GPL-3.0+", + "support": { + "email": "hello@matomo.org", + "issues": "https://github.com/matomo-org/plugin-MicrosoftTeams/issues", + "forum": "https://forum.matomo.org", + "source": "https://github.com/matomo-org/plugin-MicrosoftTeams", + "wiki": "https://github.com/matomo-org/plugin-MicrosoftTeams/wiki" + }, + "homepage": "", + "license": "GPL v3+", "keywords": [ "oauth2", - "authorization" - ] + "authorization", + "token", + "bearer token" + ], + "category": "security" } diff --git a/tests/Integration/APITest.php b/tests/Integration/APITest.php index 4eb4850..df45798 100644 --- a/tests/Integration/APITest.php +++ b/tests/Integration/APITest.php @@ -9,11 +9,15 @@ namespace Piwik\Plugins\OAuth2\tests\Integration; +use Piwik\Auth\Password; use Piwik\Container\StaticContainer; +use Piwik\Date; use Piwik\Plugins\OAuth2\API; use Piwik\Plugins\OAuth2\Model\ClientModel; use Piwik\Plugins\OAuth2\Repositories\ClientRepository; use Piwik\Plugins\OAuth2\tests\Fixtures\OAuth2Fixture; +use Piwik\Plugins\UsersManager\Model as UserModel; +use Piwik\Plugins\UsersManager\UsersManager; use Piwik\Tests\Framework\Fixture; use Piwik\Tests\Framework\Mock\FakeAccess; @@ -57,6 +61,7 @@ public function getSuperUserOnlyReadMethods(): array { return [ ['getClients'], + ['getClient', ['0123456789abcdef0123456789abcdef']], ['getScopes'], ]; } @@ -97,6 +102,17 @@ public function test_deleteClient_failsForNonSuperUsers() $this->api->deleteClient($client['client']['client_id']); } + public function test_setClientActive_failsForNonSuperUsers() + { + $client = $this->createConfidentialClient(); + + $this->expectException(\Piwik\NoAccessException::class); + $this->expectExceptionMessage('checkUserHasSuperUserAccess'); + + $this->setRegularUser(); + $this->api->setClientActive($client['client']['client_id'], '0'); + } + public function test_getClients_returnsPersistedClientsForSuperUsers() { $created = $this->createConfidentialClient(); @@ -109,6 +125,16 @@ public function test_getClients_returnsPersistedClientsForSuperUsers() $this->assertSame(['authorization_code', 'refresh_token'], $clients[0]['grant_types']); } + public function test_getClient_returnsPersistedClientForSuperUsers() + { + $created = $this->createConfidentialClient(); + + $client = $this->api->getClient($created['client']['client_id']); + + $this->assertSame($created['client']['client_id'], $client['client_id']); + $this->assertSame('Test confidential client', $client['name']); + } + public function test_getScopes_returnsConfiguredScopesForSuperUsers() { $this->assertSame( @@ -204,6 +230,119 @@ public function test_deleteClient_removesPersistedClient() $this->assertNull($this->clientModel->find($result['client']['client_id'])); } + public function test_setClientActive_updatesPersistedClientStatus() + { + $result = $this->createConfidentialClient(); + + $paused = $this->api->setClientActive($result['client']['client_id'], '0'); + $this->assertFalse($paused['client']['active']); + + $resumed = $this->api->setClientActive($result['client']['client_id'], '1'); + $this->assertTrue($resumed['client']['active']); + } + + public function test_updateClient_updatesPersistedClient() + { + $result = $this->createConfidentialClient(); + + $updated = $this->api->updateClient( + $result['client']['client_id'], + 'Updated client', + ['authorization_code', 'refresh_token'], + 'matomo:write', + ['https://updated.example/callback'], + 'Updated description', + 'confidential', + '0' + ); + + $this->assertSame('Updated client', $updated['client']['name']); + $this->assertSame('Updated description', $updated['client']['description']); + $this->assertSame(['matomo:write'], $updated['client']['scopes']); + $this->assertSame(['https://updated.example/callback'], $updated['client']['redirect_uris']); + $this->assertFalse($updated['client']['active']); + $this->assertNull($updated['secret']); + } + + public function test_updateClient_preservesExistingOwnerWhenEditedByAnotherSuperUser() + { + $result = $this->createConfidentialClient(); + $this->createSuperUser('otherSuperUser'); + + FakeAccess::clearAccess(true, [], [], 'otherSuperUser'); + + $updated = $this->api->updateClient( + $result['client']['client_id'], + 'Updated client', + ['authorization_code', 'refresh_token'], + 'matomo:write', + ['https://updated.example/callback'], + 'Updated description', + 'confidential', + '1' + ); + + $this->assertSame(Fixture::ADMIN_USER_LOGIN, $updated['client']['owner_login']); + $this->assertSame( + Fixture::ADMIN_USER_LOGIN, + $this->clientModel->find($result['client']['client_id'])['owner_login'] + ); + } + + public function test_updateClient_generatesSecretWhenChangingPublicClientToConfidential() + { + $result = $this->api->createClient( + 'Test public client', + ['authorization_code', 'refresh_token'], + 'matomo:read', + ['https://public-client.example/callback'], + 'Public client description', + 'public' + ); + + $updated = $this->api->updateClient( + $result['client']['client_id'], + 'Updated public client', + ['authorization_code', 'refresh_token'], + 'matomo:read', + ['https://public-client.example/callback'], + 'Updated public client description', + 'confidential' + ); + + $this->assertSame('confidential', $updated['client']['type']); + $this->assertNotEmpty($updated['secret']); + $this->assertTrue( + $this->clientRepository->validateClient( + $result['client']['client_id'], + $updated['secret'], + 'authorization_code' + ) + ); + } + + public function test_updateClient_clearsSecretWhenChangingConfidentialClientToPublic() + { + $result = $this->createConfidentialClient(); + + $updated = $this->api->updateClient( + $result['client']['client_id'], + 'Now public client', + ['authorization_code', 'refresh_token'], + 'matomo:read', + ['https://client.example/callback'], + 'Now public client description', + 'public' + ); + + $stored = $this->clientModel->find($result['client']['client_id']); + + $this->assertSame('public', $updated['client']['type']); + $this->assertNull($updated['secret']); + $this->assertNotNull($stored); + $this->assertNull($stored['secret_hash']); + } + public function provideContainerConfig() { return [ @@ -234,6 +373,21 @@ private function createConfidentialClient(): array 'confidential' ); } + + private function createSuperUser(string $login): void + { + $userModel = new UserModel(); + $passwordHelper = new Password(); + $hashedPassword = $passwordHelper->hash(UsersManager::getPasswordHash('test-password')); + + if (empty($userModel->getUser($login))) { + $userModel->addUser($login, $hashedPassword, $login . '@example.org', Date::now()->getDatetime()); + } else { + $userModel->updateUser($login, $hashedPassword, $login . '@example.org'); + } + + $userModel->setSuperUserAccess($login, true); + } } APITest::$fixture = new OAuth2Fixture(); diff --git a/tests/Integration/OAuthFlowTest.php b/tests/Integration/OAuthFlowTest.php index 04cdefd..269ab4f 100644 --- a/tests/Integration/OAuthFlowTest.php +++ b/tests/Integration/OAuthFlowTest.php @@ -11,7 +11,9 @@ use Matomo\Dependencies\Oauth2\Nyholm\Psr7\Response; use Matomo\Dependencies\Oauth2\Nyholm\Psr7\ServerRequest; +use Piwik\Auth\Password; use Piwik\Container\StaticContainer; +use Piwik\Date; use Piwik\Db; use Piwik\Plugins\OAuth2\API; use Piwik\Plugins\OAuth2\Entities\UserEntity; @@ -25,6 +27,8 @@ use Piwik\Plugins\OAuth2\Service\ServerFactory; use Piwik\Plugins\OAuth2\SystemSettings; use Piwik\Plugins\OAuth2\tests\Fixtures\OAuth2Fixture; +use Piwik\Plugins\UsersManager\Model as UserModel; +use Piwik\Plugins\UsersManager\UsersManager; use Piwik\Tests\Framework\Fixture; use Piwik\Tests\Framework\Mock\FakeAccess; @@ -139,6 +143,51 @@ public function test_clientCredentialsFlow_returnsAccessTokenForConfidentialClie $this->assertSame($client['client']['client_id'], $storedToken['client_id']); } + public function test_clientCredentialsFlow_preservesOriginalOwnerAfterAnotherSuperUserEditsClient() + { + $client = $this->api->createClient( + 'Machine client', + ['client_credentials'], + 'matomo:write', + [], + 'Server to server client', + 'confidential' + ); + $this->createSuperUser('otherSuperUser'); + + FakeAccess::clearAccess(true, [], [], 'otherSuperUser'); + $this->api->updateClient( + $client['client']['client_id'], + 'Machine client edited', + ['client_credentials'], + 'matomo:write', + [], + 'Edited by another superuser', + 'confidential', + '1' + ); + + FakeAccess::clearAccess(true); + + $response = $this->serverFactory->makeAuthorizationServer()->respondToAccessTokenRequest( + (new ServerRequest('POST', 'https://matomo.example/token'))->withParsedBody([ + 'grant_type' => 'client_credentials', + 'client_id' => $client['client']['client_id'], + 'client_secret' => $client['secret'], + 'scope' => 'matomo:write', + ]), + new Response() + ); + + $storedToken = Db::fetchRow( + 'SELECT * FROM ' . \Piwik\Common::prefixTable('oauth2_access_token') . ' ORDER BY created_at DESC LIMIT 1' + ); + + $this->assertSame(200, $response->getStatusCode()); + $this->assertSame(Fixture::ADMIN_USER_LOGIN, $storedToken['user_login']); + $this->assertSame($client['client']['client_id'], $storedToken['client_id']); + } + private function createConfidentialAuthCodeClient(): array { $client = $this->api->createClient( @@ -207,6 +256,21 @@ private function exchangeAuthorizationCodeForTokens(array $client): array return $tokenPayload; } + private function createSuperUser(string $login): void + { + $userModel = new UserModel(); + $passwordHelper = new Password(); + $hashedPassword = $passwordHelper->hash(UsersManager::getPasswordHash('test-password')); + + if (empty($userModel->getUser($login))) { + $userModel->addUser($login, $hashedPassword, $login . '@example.org', Date::now()->getDatetime()); + } else { + $userModel->updateUser($login, $hashedPassword, $login . '@example.org'); + } + + $userModel->setSuperUserAccess($login, true); + } + public function provideContainerConfig() { return [ diff --git a/tests/UI/OAuth2_spec.js b/tests/UI/OAuth2_spec.js index e310181..e2cb2b9 100644 --- a/tests/UI/OAuth2_spec.js +++ b/tests/UI/OAuth2_spec.js @@ -14,6 +14,7 @@ describe("OAuth2Admin", function () { }; const adminUrl = '?module=OAuth2&action=index&idSite=1&period=day&date=2024-01-01'; + const createUrl = `${adminUrl}#?idClient=0`; const settingsUrl = '?module=CoreAdminHome&action=generalSettings#/OAuth2'; before(function () { @@ -25,6 +26,12 @@ describe("OAuth2Admin", function () { { await page.waitForNetworkIdle(); await page.waitForTimeout(250); + await page.evaluate(function () { + $('.client-id-code').html('fixedValueForTest'); + $('#client_id').val('fixedValueForTest'); + $('.client-secret-code').html('fixedSecretValueForTest'); + $('.created-at').html('2026-03-16 00:00:00'); + }); expect(await page.screenshotSelector('.pageWrap,#notificationContainer')).to.matchImage(name); } @@ -49,10 +56,7 @@ describe("OAuth2Admin", function () { await page.waitForNetworkIdle(); await page.waitForTimeout(300); await page.evaluate(function () { - $('.client-id-code').html('fixedValueForTest'); - $('.client-secret-code').html('fixedSecretValueForTest'); $('.success-msg-created').html('Client fixedValueForTest created'); - $('.created-at').html('2026-03-16 00:00:00'); }); } @@ -84,6 +88,14 @@ describe("OAuth2Admin", function () { await page.waitForTimeout(100); } + async function editFirstClient() + { + await page.waitForSelector('.icon-edit', { visible: true }); + await page.click('.icon-edit'); + await page.waitForNetworkIdle(); + await page.waitForTimeout(300); + } + it('should show the OAuth2 system settings page', async function () { await page.goto(settingsUrl); await page.waitForNetworkIdle(); @@ -91,38 +103,49 @@ describe("OAuth2Admin", function () { expect(await page.screenshotSelector('#OAuth2PluginSettings')).to.matchImage('system_settings'); }); - it('should show the create client page', async function () { + it('should show the OAuth2 clients list page', async function () { await page.goto(adminUrl); await capturePage('admin_page'); }); + it('should show the create client page', async function () { + await page.goto(createUrl); + await capturePage('create_client_page'); + }); + it('should validate the create client form', async function () { - await page.goto(adminUrl); + await page.goto(createUrl); await submitForm(); await capturePage('create_client_validation'); }); it('should create a confidential client and show the secret once', async function () { - await page.goto(adminUrl); + await page.goto(createUrl); await fillClientForm('Confidential UI client', 'Confidential', 'https://confidential.example/callback'); await submitForm(); await capturePage('create_confidential_success'); }); it('should create a public client successfully', async function () { - await page.goto(adminUrl); + await page.goto(createUrl); await fillClientForm('Public UI client', 'Public', 'https://public.example/callback'); await submitForm(); await capturePage('create_public_success'); }); + it('should show the edit client page', async function () { + await page.goto(createUrl); + await fillClientForm('Editable UI client', 'Confidential', 'https://editable.example/callback'); + await submitForm(); + await page.goto(adminUrl); + await editFirstClient(); + await capturePage('edit_client_page'); + }); + it('should no longer show the client secret after reload', async function () { await page.reload(); await page.evaluate(function () { - $('.client-id-code').html('fixedValueForTest'); - $('.client-secret-code').html('fixedSecretValueForTest'); $('.success-msg-created').html('Client fixedValueForTest created'); - $('.created-at').html('2026-03-16 00:00:00'); }); await capturePage('secret_not_shown_again'); }); diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_admin_page.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_admin_page.png index a02d804..a37d934 100644 Binary files a/tests/UI/expected-ui-screenshots/OAuth2Admin_admin_page.png and b/tests/UI/expected-ui-screenshots/OAuth2Admin_admin_page.png differ diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_page.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_page.png new file mode 100644 index 0000000..f401728 Binary files /dev/null and b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_page.png differ diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_validation.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_validation.png index d95c0bf..2cb59a7 100644 Binary files a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_validation.png and b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_client_validation.png differ diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_confidential_success.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_confidential_success.png index 3308208..e950409 100644 Binary files a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_confidential_success.png and b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_confidential_success.png differ diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_public_success.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_public_success.png index ce01add..0da043b 100644 Binary files a/tests/UI/expected-ui-screenshots/OAuth2Admin_create_public_success.png and b/tests/UI/expected-ui-screenshots/OAuth2Admin_create_public_success.png differ diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_edit_client_page.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_edit_client_page.png new file mode 100644 index 0000000..ef3adce Binary files /dev/null and b/tests/UI/expected-ui-screenshots/OAuth2Admin_edit_client_page.png differ diff --git a/tests/UI/expected-ui-screenshots/OAuth2Admin_secret_not_shown_again.png b/tests/UI/expected-ui-screenshots/OAuth2Admin_secret_not_shown_again.png index 434f566..ef3adce 100644 Binary files a/tests/UI/expected-ui-screenshots/OAuth2Admin_secret_not_shown_again.png and b/tests/UI/expected-ui-screenshots/OAuth2Admin_secret_not_shown_again.png differ diff --git a/vue/dist/OAuth2.css b/vue/dist/OAuth2.css new file mode 100644 index 0000000..ba3dbc0 --- /dev/null +++ b/vue/dist/OAuth2.css @@ -0,0 +1 @@ +.redirect-uri[data-v-9cba7004]{max-width:250px;display:inline-block;word-wrap:break-word}.oauth2-secret-head[data-v-15c605de]{margin-bottom:0}.client-secret-code[data-v-15c605de]{word-break:break-word;white-space:pre-wrap;overflow-wrap:anywhere;margin:0} \ No newline at end of file diff --git a/vue/dist/OAuth2.umd.js b/vue/dist/OAuth2.umd.js index d540d78..bd791b4 100644 --- a/vue/dist/OAuth2.umd.js +++ b/vue/dist/OAuth2.umd.js @@ -101,6 +101,28 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__; +/***/ }), + +/***/ "6949": +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var _node_modules_vue_cli_service_node_modules_mini_css_extract_plugin_dist_loader_js_ref_7_oneOf_1_0_node_modules_vue_cli_service_node_modules_css_loader_dist_cjs_js_ref_7_oneOf_1_1_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_7_oneOf_1_2_node_modules_vue_cli_service_node_modules_cache_loader_dist_cjs_js_ref_1_0_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_index_js_ref_1_1_List_vue_vue_type_style_index_0_id_9cba7004_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("a85f"); +/* harmony import */ var _node_modules_vue_cli_service_node_modules_mini_css_extract_plugin_dist_loader_js_ref_7_oneOf_1_0_node_modules_vue_cli_service_node_modules_css_loader_dist_cjs_js_ref_7_oneOf_1_1_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_7_oneOf_1_2_node_modules_vue_cli_service_node_modules_cache_loader_dist_cjs_js_ref_1_0_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_index_js_ref_1_1_List_vue_vue_type_style_index_0_id_9cba7004_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_cli_service_node_modules_mini_css_extract_plugin_dist_loader_js_ref_7_oneOf_1_0_node_modules_vue_cli_service_node_modules_css_loader_dist_cjs_js_ref_7_oneOf_1_1_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_7_oneOf_1_2_node_modules_vue_cli_service_node_modules_cache_loader_dist_cjs_js_ref_1_0_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_index_js_ref_1_1_List_vue_vue_type_style_index_0_id_9cba7004_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__); +/* unused harmony reexport * */ + + +/***/ }), + +/***/ "7964": +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var _node_modules_vue_cli_service_node_modules_mini_css_extract_plugin_dist_loader_js_ref_7_oneOf_1_0_node_modules_vue_cli_service_node_modules_css_loader_dist_cjs_js_ref_7_oneOf_1_1_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_7_oneOf_1_2_node_modules_vue_cli_service_node_modules_cache_loader_dist_cjs_js_ref_1_0_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_index_js_ref_1_1_Edit_vue_vue_type_style_index_0_id_15c605de_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("b47c"); +/* harmony import */ var _node_modules_vue_cli_service_node_modules_mini_css_extract_plugin_dist_loader_js_ref_7_oneOf_1_0_node_modules_vue_cli_service_node_modules_css_loader_dist_cjs_js_ref_7_oneOf_1_1_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_7_oneOf_1_2_node_modules_vue_cli_service_node_modules_cache_loader_dist_cjs_js_ref_1_0_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_index_js_ref_1_1_Edit_vue_vue_type_style_index_0_id_15c605de_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_cli_service_node_modules_mini_css_extract_plugin_dist_loader_js_ref_7_oneOf_1_0_node_modules_vue_cli_service_node_modules_css_loader_dist_cjs_js_ref_7_oneOf_1_1_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_7_oneOf_1_2_node_modules_vue_cli_service_node_modules_cache_loader_dist_cjs_js_ref_1_0_node_modules_vue_cli_service_node_modules_vue_loader_v16_dist_index_js_ref_1_1_Edit_vue_vue_type_style_index_0_id_15c605de_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__); +/* unused harmony reexport * */ + + /***/ }), /***/ "8bbf": @@ -117,6 +139,20 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__; /***/ }), +/***/ "a85f": +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), + +/***/ "b47c": +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), + /***/ "fae3": /***/ (function(module, __webpack_exports__, __webpack_require__) { @@ -125,7 +161,7 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__; __webpack_require__.r(__webpack_exports__); // EXPORTS -__webpack_require__.d(__webpack_exports__, "Oauth2AdminApp", function() { return /* reexport */ AdminApp; }); +__webpack_require__.d(__webpack_exports__, "Oauth2AdminApp", function() { return /* reexport */ Manage; }); // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js // This file is imported into lib/wc client bundles. @@ -146,55 +182,294 @@ if (typeof window !== 'undefined') { // EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"} var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf"); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/AdminApp.vue?vue&type=template&id=67e0d42a +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?vue&type=template&id=f7d6db3a const _hoisted_1 = { class: "oauth2-admin" }; -const _hoisted_2 = { - key: 0, - class: "alert alert-warning" -}; -const _hoisted_3 = { - class: "client-secret-code" +function render(_ctx, _cache, $props, $setup, $data, $options) { + const _component_Oauth2ClientList = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Oauth2ClientList"); + const _component_Oauth2ClientEdit = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Oauth2ClientEdit"); + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_1, [!_ctx.isEditMode ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Oauth2ClientList, { + key: 0, + clients: _ctx.clients, + onCreate: _ctx.createClient, + onEdit: _ctx.editClient, + onDeleted: _ctx.onClientDeleted, + onUpdated: _ctx.onClientUpdated + }, null, 8, ["clients", "onCreate", "onEdit", "onDeleted", "onUpdated"])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Oauth2ClientEdit, { + key: 1, + "client-id": _ctx.editedClientId, + scopes: _ctx.scopes, + "initial-secret": _ctx.secret, + onCancel: _ctx.showList, + onSaved: _ctx.onClientSaved + }, null, 8, ["client-id", "scopes", "initial-secret", "onCancel", "onSaved"]))]); +} +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?vue&type=template&id=f7d6db3a + +// EXTERNAL MODULE: external "CoreHome" +var external_CoreHome_ = __webpack_require__("19dc"); + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/OAuthClients/List.vue?vue&type=template&id=9cba7004&scoped=true + +const _withScopeId = n => (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["pushScopeId"])("data-v-9cba7004"), n = n(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["popScopeId"])(), n); +const Listvue_type_template_id_9cba7004_scoped_true_hoisted_1 = { + class: "oauth2-admin oauth2-admin-list" }; -const _hoisted_4 = { - class: "form-help" +const _hoisted_2 = { + class: "ui-confirm", + ref: "confirmDeleteClient" }; +const _hoisted_3 = ["value"]; +const _hoisted_4 = ["value"]; const _hoisted_5 = { class: "ui-confirm", - ref: "confirmDeleteClient" + ref: "confirmToggleClient" }; const _hoisted_6 = ["value"]; const _hoisted_7 = ["value"]; const _hoisted_8 = { - class: "ui-confirm", - ref: "confirmRotateClient" + key: 0 }; -const _hoisted_9 = ["value"]; -const _hoisted_10 = ["value"]; -const _hoisted_11 = { - key: 0, - class: "card card-table entityTable" +const _hoisted_9 = { + style: { + "width": "220px" + } }; -const _hoisted_12 = ["title"]; -const _hoisted_13 = { +const _hoisted_10 = ["title"]; +const _hoisted_11 = { class: "client-id-code" }; -const _hoisted_14 = { +const _hoisted_12 = { + class: "redirect-uri" +}; +const _hoisted_13 = { class: "created-at" }; +const _hoisted_14 = ["onClick", "title"]; const _hoisted_15 = ["onClick", "title"]; const _hoisted_16 = ["onClick", "title"]; const _hoisted_17 = { key: 1 }; const _hoisted_18 = { + class: "tableActionBar" +}; +const _hoisted_19 = /*#__PURE__*/_withScopeId(() => /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "icon-add" +}, null, -1)); +function Listvue_type_template_id_9cba7004_scoped_true_render(_ctx, _cache, $props, $setup, $data, $options) { + const _component_ContentBlock = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ContentBlock"); + const _directive_content_table = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("content-table"); + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Listvue_type_template_id_9cba7004_scoped_true_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.confirmDeleteLabel), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + role: "yes", + type: "button", + value: _ctx.translate('General_Yes') + }, null, 8, _hoisted_3), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + role: "no", + type: "button", + value: _ctx.translate('General_No') + }, null, 8, _hoisted_4)], 512), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.confirmToggleLabel), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + role: "yes", + type: "button", + value: _ctx.translate('General_Yes') + }, null, 8, _hoisted_6), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + role: "no", + type: "button", + value: _ctx.translate('General_No') + }, null, 8, _hoisted_7)], 512), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ContentBlock, { + "content-title": _ctx.translate('OAuth2_AdminHeading'), + feature: _ctx.translate('OAuth2_AdminHeading') + }, { + default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(() => [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientsDescriptions')), 1), _ctx.clients.length ? Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("table", _hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("thead", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tr", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminName')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientType')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientGrants')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientStatus')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientId')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientRedirects')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientCreatedAt')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", _hoisted_9, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientActions')), 1)])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tbody", null, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.clients, client => { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("tr", { + key: client.client_id + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", { + title: _ctx.$sanitize(client.description) + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.name), 9, _hoisted_10), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.typeOptions[client.type]), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])((client.grant_types || []).join(', ')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.active ? _ctx.translate('OAuth2_AdminActive') : _ctx.translate('OAuth2_AdminDisabled')), 1)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("code", _hoisted_11, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.client_id), 1)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(client.redirect_uris || [], uri => { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + key: uri + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("code", _hoisted_12, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(uri), 1)]); + }), 128))]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", _hoisted_13, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.created_at), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(`table-action ${client.active ? 'icon-pause' : 'icon-play'}`), + onClick: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.toggleClientStatus(client), ["prevent"]), + title: client.active ? _ctx.translate('OAuth2_AdminPause') : _ctx.translate('OAuth2_AdminResume') + }, null, 10, _hoisted_14), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", { + class: "table-action icon-edit", + onClick: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.$emit('edit', client.client_id), ["prevent"]), + title: _ctx.translate('OAuth2_AdminEdit') + }, null, 8, _hoisted_15), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", { + class: "table-action icon-delete", + onClick: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.deleteClient(client), ["prevent"]), + title: _ctx.translate('OAuth2_AdminDelete') + }, null, 8, _hoisted_16)])]); + }), 128))])])), [[_directive_content_table]]) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_17, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminNoClients')), 1)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_18, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + class: "createNewClient", + onClick: _cache[0] || (_cache[0] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.$emit('create'), ["prevent"])) + }, [_hoisted_19, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminCreateTitle')), 1)])])]), + _: 1 + }, 8, ["content-title", "feature"])]); +} +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/List.vue?vue&type=template&id=9cba7004&scoped=true + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--15-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/OAuthClients/List.vue?vue&type=script&lang=ts + + +const notificationId = 'oauth2clientlist'; +/* harmony default export */ var Listvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + name: 'Oauth2ClientList', + props: { + clients: { + type: Array, + required: true + } + }, + emits: ['create', 'edit', 'deleted', 'updated'], + components: { + ContentBlock: external_CoreHome_["ContentBlock"] + }, + directives: { + ContentTable: external_CoreHome_["ContentTable"] + }, + data() { + return { + confirmDeleteLabel: '', + confirmToggleLabel: '', + typeOptions: { + confidential: this.translate('OAuth2_AdminConfidential'), + public: this.translate('OAuth2_AdminPublic') + } + }; + }, + methods: { + showNotification(message, context, type = null) { + const instanceId = external_CoreHome_["NotificationsStore"].show({ + message, + context, + id: notificationId, + type: type !== null ? type : 'toast' + }); + setTimeout(() => { + external_CoreHome_["NotificationsStore"].scrollToNotification(instanceId); + }, 200); + }, + removeNotifications() { + external_CoreHome_["NotificationsStore"].remove(notificationId); + external_CoreHome_["NotificationsStore"].remove('ajaxHelper'); + }, + toggleClientStatus(client) { + this.confirmToggleLabel = client.active ? this.translate('OAuth2_AdminPauseConfirm', client.name || client.client_id) : this.translate('OAuth2_AdminResumeConfirm', client.name || client.client_id); + external_CoreHome_["Matomo"].helper.modalConfirm(this.$refs.confirmToggleClient, { + yes: () => { + external_CoreHome_["AjaxHelper"].fetch({ + method: 'OAuth2.setClientActive', + clientId: client.client_id, + active: client.active ? '0' : '1' + }).then(response => { + if (response !== null && response !== void 0 && response.client) { + this.removeNotifications(); + this.showNotification(response.client.active ? this.translate('OAuth2_AdminResumed', response.client.name || response.client.client_id) : this.translate('OAuth2_AdminPaused', response.client.name || response.client.client_id), 'success'); + this.$emit('updated', response.client); + } + }); + } + }); + }, + deleteClient(client) { + this.confirmDeleteLabel = this.translate('OAuth2_AdminDeleteConfirm', client.name || client.client_id); + external_CoreHome_["Matomo"].helper.modalConfirm(this.$refs.confirmDeleteClient, { + yes: () => { + external_CoreHome_["AjaxHelper"].fetch({ + method: 'OAuth2.deleteClient', + clientId: client.client_id + }).then(response => { + if (response !== null && response !== void 0 && response.deleted) { + this.removeNotifications(); + this.showNotification(this.translate('OAuth2_AdminDeleted', client.name), 'success'); + this.$emit('deleted', client.client_id); + } + }); + } + }); + } + } +})); +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/List.vue?vue&type=script&lang=ts + +// EXTERNAL MODULE: ./plugins/OAuth2/vue/src/OAuthClients/List.vue?vue&type=style&index=0&id=9cba7004&scoped=true&lang=css +var Listvue_type_style_index_0_id_9cba7004_scoped_true_lang_css = __webpack_require__("6949"); + +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/List.vue + + + + + +Listvue_type_script_lang_ts.render = Listvue_type_template_id_9cba7004_scoped_true_render +Listvue_type_script_lang_ts.__scopeId = "data-v-9cba7004" + +/* harmony default export */ var List = (Listvue_type_script_lang_ts); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?vue&type=template&id=15c605de&scoped=true + +const Editvue_type_template_id_15c605de_scoped_true_withScopeId = n => (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["pushScopeId"])("data-v-15c605de"), n = n(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["popScopeId"])(), n); +const Editvue_type_template_id_15c605de_scoped_true_hoisted_1 = { + class: "oauth2-admin oauth2-admin-edit" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_2 = { + class: "ui-confirm", + ref: "confirmRotateClient" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_3 = ["value"]; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_4 = ["value"]; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_5 = { + key: 0 +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_6 = { + class: "loadingPiwik" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_7 = /*#__PURE__*/Editvue_type_template_id_15c605de_scoped_true_withScopeId(() => /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + src: "plugins/Morpheus/images/loading-blue.gif" +}, null, -1)); +const Editvue_type_template_id_15c605de_scoped_true_hoisted_8 = { class: "row" }; -const _hoisted_19 = { +const Editvue_type_template_id_15c605de_scoped_true_hoisted_9 = { class: "row" }; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_10 = { + key: 0, + class: "row" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_11 = { + key: 1, + class: "row oauth2-secret-head" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_12 = { + class: "col s12" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_13 = { + key: 2, + class: "oauth2-secret-div form-group row matomo-form-field" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_14 = { + class: "col s12 m6" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_15 = { + class: "copy-secret-wrapper-div" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_16 = { + key: 0, + class: "client-secret-code" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_17 = { + key: 1, + class: "client-secret-code" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_18 = { + class: "col s12 m6" +}; +const Editvue_type_template_id_15c605de_scoped_true_hoisted_19 = ["innerHTML"]; const _hoisted_20 = { class: "row", name: "type" @@ -214,86 +489,81 @@ const _hoisted_24 = { class: "row" }; const _hoisted_25 = ["disabled"]; -function render(_ctx, _cache, $props, $setup, $data, $options) { - const _component_ContentBlock = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ContentBlock"); +const _hoisted_26 = { + class: "entityCancel" +}; +function Editvue_type_template_id_15c605de_scoped_true_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field"); - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_1, [_ctx.secret ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("strong", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_ClientSecret')) + ": ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("code", _hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.secret), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_4, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_ClientSecretHelp')), 1)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.confirmDeleteLabel), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { - role: "yes", - type: "button", - value: _ctx.translate('General_Yes') - }, null, 8, _hoisted_6), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { - role: "no", - type: "button", - value: _ctx.translate('General_No') - }, null, 8, _hoisted_7)], 512), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.confirmRotateLabel), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + const _component_ContentBlock = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ContentBlock"); + const _directive_copy_to_clipboard = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("copy-to-clipboard"); + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.confirmRotateLabel), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { role: "yes", type: "button", value: _ctx.translate('General_Yes') - }, null, 8, _hoisted_9), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + }, null, 8, Editvue_type_template_id_15c605de_scoped_true_hoisted_3), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { role: "no", type: "button", value: _ctx.translate('General_No') - }, null, 8, _hoisted_10)], 512), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ContentBlock, { - "content-title": _ctx.translate('OAuth2_AdminHeading'), - feature: _ctx.translate('OAuth2_AdminHeading') - }, { - default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(() => [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientsDescriptions')), 1), _ctx.clients && _ctx.clients.length ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("table", _hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("thead", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tr", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminName')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientId')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientCreatedAt')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientType')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientGrants')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientRedirects')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminClientActions')), 1)])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tbody", null, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.clients, client => { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("tr", { - key: client.client_id - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", { - title: client.description - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("strong", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.name), 1)], 8, _hoisted_12), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("code", _hoisted_13, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.client_id), 1)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", _hoisted_14, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(client.created_at), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.type_options[client.type]), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])((client.grant_types || []).join(', ')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(client.redirect_uris || [], uri => { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { - key: uri - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("code", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(uri), 1)]); - }), 128))]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", { - class: "table-action icon-refresh", - onClick: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.rotateSecret(client), ["prevent"]), - title: _ctx.translate('OAuth2_AdminRotateSecret') - }, null, 8, _hoisted_15), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", { - class: "table-action icon-delete", - onClick: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.deleteClient(client), ["prevent"]), - title: _ctx.translate('OAuth2_AdminDelete') - }, null, 8, _hoisted_16)])]); - }), 128))])])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_17, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminNoClients')), 1))]), - _: 1 - }, 8, ["content-title", "feature"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ContentBlock, { - "content-title": _ctx.translate('OAuth2_AdminCreateTitle') + }, null, 8, Editvue_type_template_id_15c605de_scoped_true_hoisted_4)], 512), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ContentBlock, { + "content-title": _ctx.contentTitle }, { - default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(() => [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("form", { - onSubmit: _cache[6] || (_cache[6] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])((...args) => _ctx.createClient && _ctx.createClient(...args), ["prevent"])) - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_18, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(() => [_ctx.loading ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", Editvue_type_template_id_15c605de_scoped_true_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", Editvue_type_template_id_15c605de_scoped_true_hoisted_6, [Editvue_type_template_id_15c605de_scoped_true_hoisted_7, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_LoadingData')), 1)])])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("form", { + key: 1, + onSubmit: _cache[8] || (_cache[8] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])((...args) => _ctx.submit && _ctx.submit(...args), ["prevent"])) + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { uicontrol: "text", name: "name", modelValue: _ctx.form.name, "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => _ctx.form.name = $event), "inline-help": _ctx.translate('OAuth2_AdminNameHelp'), title: _ctx.translate('OAuth2_AdminName') - }, null, 8, ["modelValue", "inline-help", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_19, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + }, null, 8, ["modelValue", "inline-help", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { uicontrol: "textarea", name: "description", modelValue: _ctx.form.description, "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => _ctx.form.description = $event), + rows: 1, + "ui-control-attributes": { + style: 'min-height: auto;' + }, "inline-help": _ctx.translate('OAuth2_AdminDescriptionHelp'), - title: _ctx.translate('OAuth2_AdminDescription') - }, null, 8, ["modelValue", "inline-help", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_20, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + title: _ctx.translate('OAuth2_AdminDescription'), + placeholder: _ctx.translate('OAuth2_AdminDescriptionPlaceholder') + }, null, 8, ["modelValue", "inline-help", "title", "placeholder"])]), _ctx.isEditMode ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_10, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: "text", + name: "client_id", + "model-value": _ctx.clientId, + title: _ctx.translate('OAuth2_AdminClientId'), + disabled: true + }, null, 8, ["model-value", "title"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.showSecretPanel ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", Editvue_type_template_id_15c605de_scoped_true_hoisted_12, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_ClientSecret')) + " ", 1), _ctx.canRegenerateSecret ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + key: 0, + onClick: _cache[2] || (_cache[2] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])((...args) => _ctx.rotateSecret && _ctx.rotateSecret(...args), ["prevent"])) + }, " (" + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminRotateSecret')) + ") ", 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.showSecretPanel ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_13, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_14, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_15, [_ctx.visibleSecret ? Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("pre", Editvue_type_template_id_15c605de_scoped_true_hoisted_16, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.displayedSecret), 1)])), [[_directive_copy_to_clipboard, {}]]) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("pre", Editvue_type_template_id_15c605de_scoped_true_hoisted_17, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.displayedSecret), 1))])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Editvue_type_template_id_15c605de_scoped_true_hoisted_18, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { + class: "form-help", + innerHTML: _ctx.$sanitize(_ctx.secretInlineHelp) + }, null, 8, Editvue_type_template_id_15c605de_scoped_true_hoisted_19)])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_20, [!_ctx.isEditMode ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Field, { + key: 0, uicontrol: "select", name: "type", modelValue: _ctx.form.type, - "onUpdate:modelValue": _cache[2] || (_cache[2] = $event => _ctx.form.type = $event), + "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => _ctx.form.type = $event), title: _ctx.translate('OAuth2_AdminType'), "inline-help": _ctx.translate('OAuth2_AdminTypeHelp', '', ''), - options: { - confidential: _ctx.translate('OAuth2_AdminConfidential'), - public: _ctx.translate('OAuth2_AdminPublic') - } - }, null, 8, ["modelValue", "title", "inline-help", "options"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_21, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + options: _ctx.typeOptions + }, null, 8, ["modelValue", "title", "inline-help", "options"])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Field, { + key: 1, + uicontrol: "text", + name: "type", + "model-value": _ctx.typeOptions[_ctx.form.type] || _ctx.form.type, + title: _ctx.translate('OAuth2_AdminType'), + disabled: true + }, null, 8, ["model-value", "title"]))]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_21, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { uicontrol: "checkbox", options: _ctx.visibleGrantOptions, "var-type": "array", name: "grant_types", modelValue: _ctx.form.grant_types, - "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => _ctx.form.grant_types = $event), + "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => _ctx.form.grant_types = $event), "inline-help": _ctx.translate('OAuth2_AdminGrantTypesHelp'), title: _ctx.translate('OAuth2_AdminClientGrants') }, null, 8, ["options", "modelValue", "inline-help", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_22, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { @@ -301,14 +571,14 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { options: _ctx.scopes, name: "scopes", modelValue: _ctx.form.scope, - "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => _ctx.form.scope = $event), + "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => _ctx.form.scope = $event), "inline-help": _ctx.translate('OAuth2_AdminScopeHelp', '', ''), title: _ctx.translate('OAuth2_AdminScope') }, null, 8, ["options", "modelValue", "inline-help", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_23, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { uicontrol: "textarea", name: "redirect_uris", modelValue: _ctx.form.redirect_uris, - "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => _ctx.form.redirect_uris = $event), + "onUpdate:modelValue": _cache[6] || (_cache[6] = $event => _ctx.form.redirect_uris = $event), placeholder: "https://example.com/callback", "inline-help": _ctx.translate('OAuth2_AdminRedirectUrisHelp'), title: _ctx.translate('OAuth2_AdminRedirectUris') @@ -316,38 +586,57 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { type: "submit", class: "btn", disabled: _ctx.loading - }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('OAuth2_AdminSave')), 9, _hoisted_25)])], 32)]), + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.submitLabel), 9, _hoisted_25)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_26, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + onClick: _cache[7] || (_cache[7] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])($event => _ctx.$emit('cancel'), ["prevent"])) + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Cancel')), 1)])], 32))]), _: 1 }, 8, ["content-title"])]); } -// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/AdminApp.vue?vue&type=template&id=67e0d42a +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?vue&type=template&id=15c605de&scoped=true // EXTERNAL MODULE: external "CorePluginsAdmin" var external_CorePluginsAdmin_ = __webpack_require__("a5a2"); -// EXTERNAL MODULE: external "CoreHome" -var external_CoreHome_ = __webpack_require__("19dc"); - -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--15-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/AdminApp.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--15-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?vue&type=script&lang=ts -const notificationId = 'oauth2clientcreate'; -/* harmony default export */ var AdminAppvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ - name: 'Oauth2AdminApp', +const Editvue_type_script_lang_ts_notificationId = 'oauth2clientedit'; +function getDefaultForm(scopes) { + const firstScope = Object.keys(scopes || {})[0] || ''; + return { + name: '', + description: '', + type: 'confidential', + grant_types: ['authorization_code', 'client_credentials', 'refresh_token'], + scope: firstScope, + redirect_uris: '', + active: true + }; +} +/* harmony default export */ var Editvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + name: 'Oauth2ClientEdit', props: { - initialClients: { - type: Array, + clientId: { + type: String, required: true }, + initialSecret: { + type: String, + default: '' + }, scopes: { type: Object, required: true } }, + directives: { + CopyToClipboard: external_CoreHome_["CopyToClipboard"] + }, + emits: ['cancel', 'saved'], components: { - Field: external_CorePluginsAdmin_["Field"], - ContentBlock: external_CoreHome_["ContentBlock"] + ContentBlock: external_CoreHome_["ContentBlock"], + Field: external_CorePluginsAdmin_["Field"] }, data() { const typeOptions = { @@ -360,163 +649,158 @@ const notificationId = 'oauth2clientcreate'; refresh_token: this.translate('OAuth2_AdminGrantRefreshToken') }; return { - clients: this.initialClients || [], loading: false, - secret: '', - confirmDeleteLabel: '', confirmRotateLabel: '', - grant_options: grantOptions, - type_options: typeOptions, - form: { - name: '', - description: '', - type: 'confidential', - grant_types: ['authorization_code', 'client_credentials', 'refresh_token'], - scope: '', - redirect_uris: '', - active: true - } + typeOptions, + grantOptions, + form: getDefaultForm(this.scopes), + visibleSecret: this.initialSecret }; }, + created() { + this.init(); + }, + watch: { + clientId() { + this.init(); + }, + initialSecret(newSecret) { + this.visibleSecret = newSecret; + }, + 'form.type': 'onFormTypeChange' + }, computed: { + isEditMode() { + return this.clientId !== '0'; + }, + contentTitle() { + return this.isEditMode ? this.translate('OAuth2_AdminEditTitle') : this.translate('OAuth2_AdminCreateTitle'); + }, + submitLabel() { + return this.isEditMode ? this.translate('OAuth2_AdminUpdate') : this.translate('OAuth2_AdminSave'); + }, visibleGrantOptions() { if (this.form.type === 'public') { const filtered = {}; - if (this.grant_options.authorization_code) { - filtered.authorization_code = this.grant_options.authorization_code; + if (this.grantOptions.authorization_code) { + filtered.authorization_code = this.grantOptions.authorization_code; } - if (this.grant_options.refresh_token) { - filtered.refresh_token = this.grant_options.refresh_token; + if (this.grantOptions.refresh_token) { + filtered.refresh_token = this.grantOptions.refresh_token; } return filtered; } - return this.grant_options; + return this.grantOptions; + }, + showSecretPanel() { + return this.form.type === 'confidential' && (this.isEditMode || !!this.visibleSecret); + }, + canRegenerateSecret() { + return this.isEditMode && this.form.type === 'confidential'; + }, + displayedSecret() { + return this.visibleSecret || '*************'; + }, + secretInlineHelp() { + if (this.visibleSecret) { + return this.translate('OAuth2_ClientSecretVisibleHelp'); + } + return this.translate('OAuth2_ClientSecretMaskedHelp'); } }, - watch: { - 'form.type': 'onFormTypeChange' - }, methods: { + init() { + this.removeNotifications(); + this.form = getDefaultForm(this.scopes); + this.visibleSecret = this.initialSecret; + if (!this.isEditMode) { + return; + } + this.loading = true; + external_CoreHome_["AjaxHelper"].fetch({ + method: 'OAuth2.getClient', + clientId: this.clientId + }).then(client => { + this.form = { + name: client.name || '', + description: client.description || '', + type: client.type || 'confidential', + grant_types: client.grant_types || [], + scope: client.scopes && client.scopes[0] || Object.keys(this.scopes || {})[0] || '', + redirect_uris: (client.redirect_uris || []).join('\n'), + active: !!client.active + }; + }).finally(() => { + this.loading = false; + }); + }, onFormTypeChange(newType) { if (newType === 'public' && this.form.grant_types.includes('client_credentials')) { this.form.grant_types = this.form.grant_types.filter(value => value !== 'client_credentials'); } + if (newType === 'public') { + this.visibleSecret = ''; + } }, - showSuccessNotification(method, message) { - const messageBody = `${message}`; - const instanceId = external_CoreHome_["NotificationsStore"].show({ - id: `OAuth2_${method}`, - type: 'transient', - context: 'success', - message: messageBody - }); - setTimeout(() => { - external_CoreHome_["NotificationsStore"].scrollToNotification(instanceId); - }); - }, - async fetchClients() { - this.loading = true; - try { - await external_CoreHome_["AjaxHelper"].fetch({ - method: 'OAuth2.getClients', - filter_limit: '-1' - }).then(clients => { - this.clients = clients; - }); - } finally { - this.loading = false; + rotateSecret() { + if (!this.canRegenerateSecret) { + return; } + this.confirmRotateLabel = this.translate('OAuth2_AdminRotateConfirm', this.form.name || this.clientId); + external_CoreHome_["Matomo"].helper.modalConfirm(this.$refs.confirmRotateClient, { + yes: () => { + this.loading = true; + external_CoreHome_["AjaxHelper"].fetch({ + method: 'OAuth2.rotateSecret', + clientId: this.clientId + }).then(response => { + if (response !== null && response !== void 0 && response.secret) { + this.visibleSecret = response.secret; + } + }).finally(() => { + this.loading = false; + }); + } + }); }, - async createClient() { - this.removeAnyClientNotification(); + submit() { + this.removeNotifications(); if (!this.checkRequiredFieldsAreSet()) { return; } this.loading = true; - this.secret = ''; const params = { - method: 'OAuth2.createClient', - name: this.form.name, + method: this.isEditMode ? 'OAuth2.updateClient' : 'OAuth2.createClient', + name: this.form.name.trim(), description: this.form.description, type: this.form.type, grantTypes: this.form.grant_types, scope: this.form.scope, redirectUris: this.form.redirect_uris, - active: 1 + active: this.form.active ? '1' : '0' }; - try { - await external_CoreHome_["AjaxHelper"].fetch(params).then(response => { - this.clients.push(response.client); - const message = this.translate('OAuth2_AdminCreated', response.client.client_id); - this.showSuccessNotification('createClient', message); - if (response.secret) { - this.secret = response.secret; - } - this.resetForm(); + if (this.isEditMode) { + params.clientId = this.clientId; + } + external_CoreHome_["AjaxHelper"].fetch(params).then(response => { + this.visibleSecret = response.secret || ''; + const clientMessage = this.isEditMode ? this.translate('OAuth2_AdminUpdated', response.client.name) : this.translate('OAuth2_AdminCreated', response.client.name); + const secretMessage = response.secret ? this.translate('OAuth2_ClientSecretHelp') : ''; + const message = [clientMessage, secretMessage].filter(Boolean).join(' '); + this.$emit('saved', { + client: response.client, + secret: response.secret || null }); - } finally { + external_CoreHome_["MatomoUrl"].updateHash(Object.assign(Object.assign({}, external_CoreHome_["MatomoUrl"].hashParsed.value), {}, { + idClient: response.client.client_id + })); + setTimeout(() => { + this.showNotification(`${message}`, 'success', 'transient'); + }, 50); + }).finally(() => { this.loading = false; - } - }, - async rotateSecret(client) { - if (!client) { - return; - } - this.confirmRotateLabel = this.translate('OAuth2_AdminRotateConfirm', (client === null || client === void 0 ? void 0 : client.name) || (client === null || client === void 0 ? void 0 : client.client_id)); - external_CoreHome_["Matomo"].helper.modalConfirm(this.$refs.confirmRotateClient, { - yes: () => { - this.loading = true; - try { - external_CoreHome_["AjaxHelper"].fetch({ - method: 'OAuth2.rotateSecret', - clientId: client.client_id - }).then(response => { - if (response && response.secret) { - this.secret = response.secret; - const message = this.translate('OAuth2_AdminRotated', client.client_id); - this.showSuccessNotification('rotateSecret', message); - } - }); - } finally { - this.loading = false; - } - } }); }, - async deleteClient(client) { - if (!client) { - return; - } - this.confirmDeleteLabel = this.translate('OAuth2_AdminDeleteConfirm', (client === null || client === void 0 ? void 0 : client.name) || (client === null || client === void 0 ? void 0 : client.client_id)); - external_CoreHome_["Matomo"].helper.modalConfirm(this.$refs.confirmDeleteClient, { - yes: () => { - this.loading = true; - try { - external_CoreHome_["AjaxHelper"].fetch({ - method: 'OAuth2.deleteClient', - clientId: client.client_id - }).then(response => { - if (response.deleted) { - this.clients = this.clients.filter(c => c.client_id !== client.client_id); - const message = this.translate('OAuth2_AdminDeleted', client.client_id); - this.showSuccessNotification('deleteClient', message); - } - }); - } finally { - this.loading = false; - } - } - }); - }, - resetForm() { - this.form.name = ''; - this.form.description = ''; - this.form.type = 'confidential'; - this.form.grant_types = ['authorization_code', 'client_credentials', 'refresh_token']; - this.form.scope = ''; - this.form.redirect_uris = ''; - this.form.active = true; - }, checkRequiredFieldsAreSet() { let response = true; let errorMessage = ''; @@ -541,15 +825,15 @@ const notificationId = 'oauth2clientcreate'; } return response; }, - removeAnyClientNotification() { - external_CoreHome_["NotificationsStore"].remove(notificationId); + removeNotifications() { + external_CoreHome_["NotificationsStore"].remove(Editvue_type_script_lang_ts_notificationId); external_CoreHome_["NotificationsStore"].remove('ajaxHelper'); }, showNotification(message, context, type = null) { const notificationInstanceId = external_CoreHome_["NotificationsStore"].show({ message, context, - id: notificationId, + id: Editvue_type_script_lang_ts_notificationId, type: type !== null ? type : 'toast' }); setTimeout(() => { @@ -562,15 +846,139 @@ const notificationId = 'oauth2clientcreate'; } } })); -// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/AdminApp.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?vue&type=script&lang=ts + +// EXTERNAL MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?vue&type=style&index=0&id=15c605de&scoped=true&lang=css +var Editvue_type_style_index_0_id_15c605de_scoped_true_lang_css = __webpack_require__("7964"); + +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Edit.vue + + + + + +Editvue_type_script_lang_ts.render = Editvue_type_template_id_15c605de_scoped_true_render +Editvue_type_script_lang_ts.__scopeId = "data-v-15c605de" + +/* harmony default export */ var Edit = (Editvue_type_script_lang_ts); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--15-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--1-1!./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?vue&type=script&lang=ts + + + + +/* harmony default export */ var Managevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + name: 'Oauth2AdminApp', + props: { + initialClients: { + type: Array, + required: true + }, + scopes: { + type: Object, + required: true + } + }, + components: { + Oauth2ClientList: List, + Oauth2ClientEdit: Edit + }, + data() { + return { + clients: this.initialClients || [], + secret: '', + secretClientId: '', + editedClientId: '' + }; + }, + created() { + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(() => external_CoreHome_["MatomoUrl"].hashParsed.value.idClient, idClient => { + this.initState(idClient); + }); + this.initState(external_CoreHome_["MatomoUrl"].hashParsed.value.idClient); + }, + methods: { + initState(idClient) { + if (!idClient) { + this.secret = ''; + this.secretClientId = ''; + } else if (this.secretClientId && this.secretClientId !== idClient) { + this.secret = ''; + this.secretClientId = ''; + } + this.editedClientId = idClient || ''; + }, + createClient() { + external_CoreHome_["MatomoUrl"].updateHash(Object.assign(Object.assign({}, external_CoreHome_["MatomoUrl"].hashParsed.value), {}, { + idClient: '0' + })); + this.secret = ''; + this.secretClientId = ''; + }, + editClient(clientId) { + if (this.secretClientId !== clientId) { + this.secret = ''; + this.secretClientId = ''; + } + external_CoreHome_["MatomoUrl"].updateHash(Object.assign(Object.assign({}, external_CoreHome_["MatomoUrl"].hashParsed.value), {}, { + idClient: clientId + })); + }, + showList() { + const params = Object.assign({}, external_CoreHome_["MatomoUrl"].hashParsed.value); + delete params.idClient; + this.secret = ''; + this.secretClientId = ''; + external_CoreHome_["MatomoUrl"].updateHash(params); + }, + onClientSaved(payload) { + const index = this.clients.findIndex(client => client.client_id === payload.client.client_id); + if (index === -1) { + this.clients.push(payload.client); + } else { + this.clients.splice(index, 1, payload.client); + } + this.clients = [...this.clients].sort((left, right) => { + const leftTime = left.updated_at ? new Date(left.updated_at).getTime() : 0; + const rightTime = right.updated_at ? new Date(right.updated_at).getTime() : 0; + if (rightTime !== leftTime) { + return rightTime - leftTime; + } + return left.name.localeCompare(right.name); + }); + this.secret = payload.secret || ''; + this.secretClientId = payload.secret ? payload.client.client_id : ''; + }, + onClientDeleted(clientId) { + this.secret = ''; + if (this.secretClientId === clientId) { + this.secretClientId = ''; + } + this.clients = this.clients.filter(client => client.client_id !== clientId); + }, + onClientUpdated(updatedClient) { + const index = this.clients.findIndex(client => client.client_id === updatedClient.client_id); + if (index === -1) { + return; + } + this.clients.splice(index, 1, updatedClient); + this.clients = [...this.clients]; + } + }, + computed: { + isEditMode() { + return !!this.editedClientId; + } + } +})); +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?vue&type=script&lang=ts -// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/AdminApp.vue +// CONCATENATED MODULE: ./plugins/OAuth2/vue/src/OAuthClients/Manage.vue -AdminAppvue_type_script_lang_ts.render = render +Managevue_type_script_lang_ts.render = render -/* harmony default export */ var AdminApp = (AdminAppvue_type_script_lang_ts); +/* harmony default export */ var Manage = (Managevue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/OAuth2/vue/src/index.ts /*! * Matomo - free/libre analytics platform diff --git a/vue/dist/OAuth2.umd.js.map b/vue/dist/OAuth2.umd.js.map index e3abf18..535e15b 100644 --- a/vue/dist/OAuth2.umd.js.map +++ b/vue/dist/OAuth2.umd.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://OAuth2/webpack/universalModuleDefinition","webpack://OAuth2/webpack/bootstrap","webpack://OAuth2/external \"CoreHome\"","webpack://OAuth2/external {\"commonjs\":\"vue\",\"commonjs2\":\"vue\",\"root\":\"Vue\"}","webpack://OAuth2/external \"CorePluginsAdmin\"","webpack://OAuth2/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue?ce89","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue?858b","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue?e86a","webpack://OAuth2/./plugins/OAuth2/vue/src/index.ts","webpack://OAuth2/./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js"],"names":[],"mappings":"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","file":"OAuth2.umd.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"CoreHome\", , \"CorePluginsAdmin\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"OAuth2\"] = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse\n\t\troot[\"OAuth2\"] = factory(root[\"CoreHome\"], root[\"Vue\"], root[\"CorePluginsAdmin\"]);\n})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"plugins/OAuth2/vue/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fae3\");\n","module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;","module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;","module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","\n\n\n","\nimport { defineComponent } from 'vue';\nimport { Field } from 'CorePluginsAdmin';\nimport {\n Matomo,\n ContentBlock,\n AjaxHelper,\n NotificationsStore,\n NotificationType,\n} from 'CoreHome';\n\ntype Client = {\n client_id: string;\n name: string;\n description?: string;\n type: string;\n grant_types: string[];\n redirect_uris: string[];\n active: boolean;\n};\n\nconst notificationId = 'oauth2clientcreate';\n\nexport default defineComponent({\n name: 'Oauth2AdminApp',\n props: {\n initialClients: {\n type: Array,\n required: true,\n },\n scopes: {\n type: Object,\n required: true,\n },\n },\n components: {\n Field,\n ContentBlock,\n },\n data() {\n const typeOptions = {\n confidential: this.translate('OAuth2_AdminConfidential'),\n public: this.translate('OAuth2_AdminPublic'),\n };\n\n const grantOptions = {\n authorization_code: this.translate('OAuth2_AdminGrantAuthorizationCode'),\n client_credentials: this.translate('OAuth2_AdminGrantClientCredentials'),\n refresh_token: this.translate('OAuth2_AdminGrantRefreshToken'),\n };\n\n return {\n clients: (this.initialClients as Client[]) || [],\n loading: false,\n secret: '',\n confirmDeleteLabel: '',\n confirmRotateLabel: '',\n grant_options: grantOptions,\n type_options: typeOptions,\n form: {\n name: '',\n description: '',\n type: 'confidential',\n grant_types: ['authorization_code', 'client_credentials', 'refresh_token'],\n scope: '',\n redirect_uris: '',\n active: true,\n },\n };\n },\n computed: {\n visibleGrantOptions(): Record {\n if (this.form.type === 'public') {\n const filtered: Record = {};\n if (this.grant_options.authorization_code) {\n filtered.authorization_code = this.grant_options.authorization_code;\n }\n if (this.grant_options.refresh_token) {\n filtered.refresh_token = this.grant_options.refresh_token;\n }\n return filtered;\n }\n\n return this.grant_options;\n },\n },\n watch: {\n 'form.type': 'onFormTypeChange',\n },\n methods: {\n onFormTypeChange(newType: string) {\n if (newType === 'public' && this.form.grant_types.includes('client_credentials')) {\n this.form.grant_types = this.form.grant_types.filter((value: string) => value !== 'client_credentials');\n }\n },\n showSuccessNotification(method: string, message: string) {\n const messageBody = `${message}`;\n const instanceId = NotificationsStore.show({\n id: `OAuth2_${method}`,\n type: 'transient',\n context: 'success',\n message: messageBody,\n });\n\n setTimeout(() => {\n NotificationsStore.scrollToNotification(instanceId);\n });\n },\n async fetchClients() {\n this.loading = true;\n try {\n await AjaxHelper.fetch({\n method: 'OAuth2.getClients',\n filter_limit: '-1',\n }).then((clients) => {\n this.clients = clients;\n });\n } finally {\n this.loading = false;\n }\n },\n async createClient() {\n this.removeAnyClientNotification();\n if (!this.checkRequiredFieldsAreSet()) {\n return;\n }\n this.loading = true;\n this.secret = '';\n const params = {\n method: 'OAuth2.createClient',\n name: this.form.name,\n description: this.form.description,\n type: this.form.type,\n grantTypes: this.form.grant_types,\n scope: this.form.scope,\n redirectUris: this.form.redirect_uris,\n active: 1,\n };\n try {\n await AjaxHelper.fetch(params).then((response) => {\n this.clients.push(response.client);\n\n const message = this.translate('OAuth2_AdminCreated', response.client.client_id);\n this.showSuccessNotification('createClient', message);\n\n if (response.secret) {\n this.secret = response.secret;\n }\n this.resetForm();\n });\n } finally {\n this.loading = false;\n }\n },\n async rotateSecret(client: Client) {\n if (!client) {\n return;\n }\n\n this.confirmRotateLabel = this.translate('OAuth2_AdminRotateConfirm', client?.name || client?.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmRotateClient as HTMLElement, {\n yes: () => {\n this.loading = true;\n try {\n AjaxHelper.fetch({\n method: 'OAuth2.rotateSecret',\n clientId: client.client_id,\n }).then((response) => {\n if (response && response.secret) {\n this.secret = response.secret;\n\n const message = this.translate('OAuth2_AdminRotated', client.client_id);\n this.showSuccessNotification('rotateSecret', message);\n }\n });\n } finally {\n this.loading = false;\n }\n },\n });\n },\n async deleteClient(client: Client) {\n if (!client) {\n return;\n }\n\n this.confirmDeleteLabel = this.translate('OAuth2_AdminDeleteConfirm', client?.name || client?.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmDeleteClient as HTMLElement, {\n yes: () => {\n this.loading = true;\n try {\n AjaxHelper.fetch({\n method: 'OAuth2.deleteClient',\n clientId: client.client_id,\n }).then((response) => {\n if (response.deleted) {\n this.clients = this.clients.filter((c) => c.client_id !== client.client_id);\n\n const message = this.translate('OAuth2_AdminDeleted', client.client_id);\n this.showSuccessNotification('deleteClient', message);\n }\n });\n } finally {\n this.loading = false;\n }\n },\n });\n },\n resetForm() {\n this.form.name = '';\n this.form.description = '';\n this.form.type = 'confidential';\n this.form.grant_types = ['authorization_code', 'client_credentials', 'refresh_token'];\n this.form.scope = '';\n this.form.redirect_uris = '';\n this.form.active = true;\n },\n checkRequiredFieldsAreSet() {\n let response = true;\n let errorMessage = '';\n if (!this.form.name.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminName');\n } else if (!this.form.type.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminType');\n } else if (!this.form.grant_types.length) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminClientGrants');\n } else if (!this.form.scope.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminScope');\n } else if (!this.form.redirect_uris.trim() && this.form.grant_types.includes('authorization_code')) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminRedirectUris');\n }\n if (!response && errorMessage) {\n this.showErrorFieldNotProvidedNotification(errorMessage);\n }\n\n return response;\n },\n removeAnyClientNotification() {\n NotificationsStore.remove(notificationId);\n NotificationsStore.remove('ajaxHelper');\n },\n showNotification(message: string, context: NotificationType['context'],\n type: null|NotificationType['type'] = null) {\n const notificationInstanceId = NotificationsStore.show({\n message,\n context,\n id: notificationId,\n type: type !== null ? type : 'toast',\n });\n setTimeout(() => {\n NotificationsStore.scrollToNotification(notificationInstanceId);\n }, 200);\n },\n showErrorFieldNotProvidedNotification(title: string) {\n const message = this.translate('OAuth2_ErrorXNotProvided', [title]);\n this.showNotification(message, 'error');\n },\n },\n});\n","export { default } from \"-!../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./AdminApp.vue?vue&type=script&lang=ts\"; export * from \"-!../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./AdminApp.vue?vue&type=script&lang=ts\"","import { render } from \"./AdminApp.vue?vue&type=template&id=67e0d42a\"\nimport script from \"./AdminApp.vue?vue&type=script&lang=ts\"\nexport * from \"./AdminApp.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","/*!\n * Matomo - free/libre analytics platform\n *\n * @link https://matomo.org\n * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n */\n\nexport { default as Oauth2AdminApp } from './AdminApp.vue';\n","import './setPublicPath'\nexport * from '~entry'\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://OAuth2/webpack/universalModuleDefinition","webpack://OAuth2/webpack/bootstrap","webpack://OAuth2/external \"CoreHome\"","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?5afb","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?c30b","webpack://OAuth2/external {\"commonjs\":\"vue\",\"commonjs2\":\"vue\",\"root\":\"Vue\"}","webpack://OAuth2/external \"CorePluginsAdmin\"","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?98fb","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?aa4f","webpack://OAuth2/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?1486","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?0502","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?93f1","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?ce49","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?a589","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?3733","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?175b","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?4a8b","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?084c","webpack://OAuth2/./plugins/OAuth2/vue/src/index.ts","webpack://OAuth2/./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js"],"names":[],"mappings":"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","file":"OAuth2.umd.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"CoreHome\", , \"CorePluginsAdmin\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"OAuth2\"] = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse\n\t\troot[\"OAuth2\"] = factory(root[\"CoreHome\"], root[\"Vue\"], root[\"CorePluginsAdmin\"]);\n})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"plugins/OAuth2/vue/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fae3\");\n","module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;","export * from \"-!../../../../../node_modules/@vue/cli-service/node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./List.vue?vue&type=style&index=0&id=9cba7004&scoped=true&lang=css\"","export * from \"-!../../../../../node_modules/@vue/cli-service/node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./Edit.vue?vue&type=style&index=0&id=15c605de&scoped=true&lang=css\"","module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;","module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;","// extracted by mini-css-extract-plugin","// extracted by mini-css-extract-plugin","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","\n\n\n","\n\n\n\n\n","\nimport { defineComponent, PropType } from 'vue';\nimport {\n AjaxHelper,\n ContentBlock,\n ContentTable,\n Matomo,\n NotificationType,\n NotificationsStore,\n} from 'CoreHome';\nimport { Client } from '../types';\n\nconst notificationId = 'oauth2clientlist';\n\nexport default defineComponent({\n name: 'Oauth2ClientList',\n props: {\n clients: {\n type: Array as PropType,\n required: true,\n },\n },\n emits: ['create', 'edit', 'deleted', 'updated'],\n components: {\n ContentBlock,\n },\n directives: {\n ContentTable,\n },\n data() {\n return {\n confirmDeleteLabel: '',\n confirmToggleLabel: '',\n typeOptions: {\n confidential: this.translate('OAuth2_AdminConfidential'),\n public: this.translate('OAuth2_AdminPublic'),\n } as Record,\n };\n },\n methods: {\n showNotification(message: string, context: NotificationType['context'],\n type: null|NotificationType['type'] = null) {\n const instanceId = NotificationsStore.show({\n message,\n context,\n id: notificationId,\n type: type !== null ? type : 'toast',\n });\n\n setTimeout(() => {\n NotificationsStore.scrollToNotification(instanceId);\n }, 200);\n },\n removeNotifications() {\n NotificationsStore.remove(notificationId);\n NotificationsStore.remove('ajaxHelper');\n },\n toggleClientStatus(client: Client) {\n this.confirmToggleLabel = client.active\n ? this.translate('OAuth2_AdminPauseConfirm', client.name || client.client_id)\n : this.translate('OAuth2_AdminResumeConfirm', client.name || client.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmToggleClient as HTMLElement, {\n yes: () => {\n AjaxHelper.fetch({\n method: 'OAuth2.setClientActive',\n clientId: client.client_id,\n active: client.active ? '0' : '1',\n }).then((response) => {\n if (response?.client) {\n this.removeNotifications();\n this.showNotification(\n response.client.active\n ? this.translate('OAuth2_AdminResumed', response.client.name || response.client.client_id)\n : this.translate('OAuth2_AdminPaused', response.client.name || response.client.client_id),\n 'success',\n );\n this.$emit('updated', response.client);\n }\n });\n },\n });\n },\n deleteClient(client: Client) {\n this.confirmDeleteLabel = this.translate('OAuth2_AdminDeleteConfirm', client.name || client.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmDeleteClient as HTMLElement, {\n yes: () => {\n AjaxHelper.fetch({\n method: 'OAuth2.deleteClient',\n clientId: client.client_id,\n }).then((response) => {\n if (response?.deleted) {\n this.removeNotifications();\n this.showNotification(this.translate('OAuth2_AdminDeleted', client.name), 'success');\n this.$emit('deleted', client.client_id);\n }\n });\n },\n });\n },\n },\n});\n","export { default } from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./List.vue?vue&type=script&lang=ts\"; export * from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./List.vue?vue&type=script&lang=ts\"","import { render } from \"./List.vue?vue&type=template&id=9cba7004&scoped=true\"\nimport script from \"./List.vue?vue&type=script&lang=ts\"\nexport * from \"./List.vue?vue&type=script&lang=ts\"\n\nimport \"./List.vue?vue&type=style&index=0&id=9cba7004&scoped=true&lang=css\"\nscript.render = render\nscript.__scopeId = \"data-v-9cba7004\"\n\nexport default script","\n\n\n\n\n","\nimport { defineComponent, PropType } from 'vue';\nimport {\n AjaxHelper,\n ContentBlock,\n MatomoUrl,\n Matomo,\n NotificationType,\n NotificationsStore,\n CopyToClipboard,\n} from 'CoreHome';\nimport { Field } from 'CorePluginsAdmin';\nimport { Client, ClientForm } from '../types';\n\nconst notificationId = 'oauth2clientedit';\n\nfunction getDefaultForm(scopes: Record): ClientForm {\n const firstScope = Object.keys(scopes || {})[0] || '';\n\n return {\n name: '',\n description: '',\n type: 'confidential',\n grant_types: ['authorization_code', 'client_credentials', 'refresh_token'],\n scope: firstScope,\n redirect_uris: '',\n active: true,\n };\n}\n\nexport default defineComponent({\n name: 'Oauth2ClientEdit',\n props: {\n clientId: {\n type: String,\n required: true,\n },\n initialSecret: {\n type: String,\n default: '',\n },\n scopes: {\n type: Object as PropType>,\n required: true,\n },\n },\n directives: {\n CopyToClipboard,\n },\n emits: ['cancel', 'saved'],\n components: {\n ContentBlock,\n Field,\n },\n data() {\n const typeOptions = {\n confidential: this.translate('OAuth2_AdminConfidential'),\n public: this.translate('OAuth2_AdminPublic'),\n };\n\n const grantOptions = {\n authorization_code: this.translate('OAuth2_AdminGrantAuthorizationCode'),\n client_credentials: this.translate('OAuth2_AdminGrantClientCredentials'),\n refresh_token: this.translate('OAuth2_AdminGrantRefreshToken'),\n };\n\n return {\n loading: false,\n confirmRotateLabel: '',\n typeOptions,\n grantOptions,\n form: getDefaultForm(this.scopes),\n visibleSecret: this.initialSecret,\n };\n },\n created() {\n this.init();\n },\n watch: {\n clientId() {\n this.init();\n },\n initialSecret(newSecret: string) {\n this.visibleSecret = newSecret;\n },\n 'form.type': 'onFormTypeChange',\n },\n computed: {\n isEditMode(): boolean {\n return this.clientId !== '0';\n },\n contentTitle(): string {\n return this.isEditMode\n ? this.translate('OAuth2_AdminEditTitle')\n : this.translate('OAuth2_AdminCreateTitle');\n },\n submitLabel(): string {\n return this.isEditMode\n ? this.translate('OAuth2_AdminUpdate')\n : this.translate('OAuth2_AdminSave');\n },\n visibleGrantOptions(): Record {\n if (this.form.type === 'public') {\n const filtered: Record = {};\n if (this.grantOptions.authorization_code) {\n filtered.authorization_code = this.grantOptions.authorization_code;\n }\n if (this.grantOptions.refresh_token) {\n filtered.refresh_token = this.grantOptions.refresh_token;\n }\n return filtered;\n }\n\n return this.grantOptions;\n },\n showSecretPanel(): boolean {\n return this.form.type === 'confidential' && (this.isEditMode || !!this.visibleSecret);\n },\n canRegenerateSecret(): boolean {\n return this.isEditMode && this.form.type === 'confidential';\n },\n displayedSecret(): string {\n return this.visibleSecret || '*************';\n },\n secretInlineHelp(): string {\n if (this.visibleSecret) {\n return this.translate('OAuth2_ClientSecretVisibleHelp');\n }\n\n return this.translate('OAuth2_ClientSecretMaskedHelp');\n },\n },\n methods: {\n init() {\n this.removeNotifications();\n this.form = getDefaultForm(this.scopes);\n this.visibleSecret = this.initialSecret;\n\n if (!this.isEditMode) {\n return;\n }\n\n this.loading = true;\n AjaxHelper.fetch({\n method: 'OAuth2.getClient',\n clientId: this.clientId,\n }).then((client) => {\n this.form = {\n name: client.name || '',\n description: client.description || '',\n type: client.type || 'confidential',\n grant_types: client.grant_types || [],\n scope: (client.scopes && client.scopes[0]) || Object.keys(this.scopes || {})[0] || '',\n redirect_uris: (client.redirect_uris || []).join('\\n'),\n active: !!client.active,\n };\n }).finally(() => {\n this.loading = false;\n });\n },\n onFormTypeChange(newType: string) {\n if (newType === 'public' && this.form.grant_types.includes('client_credentials')) {\n this.form.grant_types = this.form.grant_types.filter((value: string) => value !== 'client_credentials');\n }\n\n if (newType === 'public') {\n this.visibleSecret = '';\n }\n },\n rotateSecret() {\n if (!this.canRegenerateSecret) {\n return;\n }\n\n this.confirmRotateLabel = this.translate('OAuth2_AdminRotateConfirm', this.form.name || this.clientId);\n Matomo.helper.modalConfirm(this.$refs.confirmRotateClient as HTMLElement, {\n yes: () => {\n this.loading = true;\n AjaxHelper.fetch({\n method: 'OAuth2.rotateSecret',\n clientId: this.clientId,\n }).then((response) => {\n if (response?.secret) {\n this.visibleSecret = response.secret;\n }\n }).finally(() => {\n this.loading = false;\n });\n },\n });\n },\n submit() {\n this.removeNotifications();\n if (!this.checkRequiredFieldsAreSet()) {\n return;\n }\n\n this.loading = true;\n const params = {\n method: this.isEditMode ? 'OAuth2.updateClient' : 'OAuth2.createClient',\n name: this.form.name.trim(),\n description: this.form.description,\n type: this.form.type,\n grantTypes: this.form.grant_types,\n scope: this.form.scope,\n redirectUris: this.form.redirect_uris,\n active: this.form.active ? '1' : '0',\n } as Record;\n\n if (this.isEditMode) {\n params.clientId = this.clientId;\n }\n\n AjaxHelper.fetch(params).then((response) => {\n this.visibleSecret = response.secret || '';\n const clientMessage = this.isEditMode\n ? this.translate('OAuth2_AdminUpdated', response.client.name)\n : this.translate('OAuth2_AdminCreated', response.client.name);\n const secretMessage = response.secret\n ? this.translate('OAuth2_ClientSecretHelp')\n : '';\n const message = [clientMessage, secretMessage].filter(Boolean).join(' ');\n\n this.$emit('saved', {\n client: response.client,\n secret: response.secret || null,\n });\n\n MatomoUrl.updateHash({\n ...MatomoUrl.hashParsed.value,\n idClient: response.client.client_id,\n });\n\n setTimeout(() => {\n this.showNotification(`${message}`, 'success', 'transient');\n }, 50);\n }).finally(() => {\n this.loading = false;\n });\n },\n checkRequiredFieldsAreSet() {\n let response = true;\n let errorMessage = '';\n if (!this.form.name.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminName');\n } else if (!this.form.type.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminType');\n } else if (!this.form.grant_types.length) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminClientGrants');\n } else if (!this.form.scope.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminScope');\n } else if (!this.form.redirect_uris.trim() && this.form.grant_types.includes('authorization_code')) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminRedirectUris');\n }\n\n if (!response && errorMessage) {\n this.showErrorFieldNotProvidedNotification(errorMessage);\n }\n\n return response;\n },\n removeNotifications() {\n NotificationsStore.remove(notificationId);\n NotificationsStore.remove('ajaxHelper');\n },\n showNotification(message: string, context: NotificationType['context'],\n type: null|NotificationType['type'] = null) {\n const notificationInstanceId = NotificationsStore.show({\n message,\n context,\n id: notificationId,\n type: type !== null ? type : 'toast',\n });\n setTimeout(() => {\n NotificationsStore.scrollToNotification(notificationInstanceId);\n }, 200);\n },\n showErrorFieldNotProvidedNotification(title: string) {\n const message = this.translate('OAuth2_ErrorXNotProvided', [title]);\n this.showNotification(message, 'error');\n },\n },\n});\n","export { default } from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./Edit.vue?vue&type=script&lang=ts\"; export * from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./Edit.vue?vue&type=script&lang=ts\"","import { render } from \"./Edit.vue?vue&type=template&id=15c605de&scoped=true\"\nimport script from \"./Edit.vue?vue&type=script&lang=ts\"\nexport * from \"./Edit.vue?vue&type=script&lang=ts\"\n\nimport \"./Edit.vue?vue&type=style&index=0&id=15c605de&scoped=true&lang=css\"\nscript.render = render\nscript.__scopeId = \"data-v-15c605de\"\n\nexport default script","\nimport { defineComponent, watch } from 'vue';\nimport { MatomoUrl } from 'CoreHome';\nimport Oauth2ClientList from './List.vue';\nimport Oauth2ClientEdit from './Edit.vue';\nimport { Client } from '../types';\n\nexport default defineComponent({\n name: 'Oauth2AdminApp',\n props: {\n initialClients: {\n type: Array as () => Client[],\n required: true,\n },\n scopes: {\n type: Object as () => Record,\n required: true,\n },\n },\n components: {\n Oauth2ClientList,\n Oauth2ClientEdit,\n },\n data() {\n return {\n clients: this.initialClients as Client[] || [],\n secret: '',\n secretClientId: '',\n editedClientId: '',\n };\n },\n created() {\n watch(() => MatomoUrl.hashParsed.value.idClient as string, (idClient) => {\n this.initState(idClient);\n });\n\n this.initState(MatomoUrl.hashParsed.value.idClient as string);\n },\n methods: {\n initState(idClient?: string) {\n if (!idClient) {\n this.secret = '';\n this.secretClientId = '';\n } else if (this.secretClientId && this.secretClientId !== idClient) {\n this.secret = '';\n this.secretClientId = '';\n }\n\n this.editedClientId = idClient || '';\n },\n createClient() {\n MatomoUrl.updateHash({\n ...MatomoUrl.hashParsed.value,\n idClient: '0',\n });\n this.secret = '';\n this.secretClientId = '';\n },\n editClient(clientId: string) {\n if (this.secretClientId !== clientId) {\n this.secret = '';\n this.secretClientId = '';\n }\n\n MatomoUrl.updateHash({\n ...MatomoUrl.hashParsed.value,\n idClient: clientId,\n });\n },\n showList() {\n const params = {\n ...MatomoUrl.hashParsed.value,\n };\n delete params.idClient;\n this.secret = '';\n this.secretClientId = '';\n MatomoUrl.updateHash(params);\n },\n onClientSaved(payload: { client: Client; secret: string|null }) {\n const index = this.clients.findIndex(\n (client) => client.client_id === payload.client.client_id,\n );\n if (index === -1) {\n this.clients.push(payload.client);\n } else {\n this.clients.splice(index, 1, payload.client);\n }\n\n this.clients = [...this.clients].sort((left, right) => {\n const leftTime = left.updated_at ? new Date(left.updated_at).getTime() : 0;\n const rightTime = right.updated_at ? new Date(right.updated_at).getTime() : 0;\n\n if (rightTime !== leftTime) {\n return rightTime - leftTime;\n }\n\n return left.name.localeCompare(right.name);\n });\n this.secret = payload.secret || '';\n this.secretClientId = payload.secret ? payload.client.client_id : '';\n },\n onClientDeleted(clientId: string) {\n this.secret = '';\n if (this.secretClientId === clientId) {\n this.secretClientId = '';\n }\n this.clients = this.clients.filter((client) => client.client_id !== clientId);\n },\n onClientUpdated(updatedClient: Client) {\n const index = this.clients.findIndex(\n (client) => client.client_id === updatedClient.client_id,\n );\n if (index === -1) {\n return;\n }\n\n this.clients.splice(index, 1, updatedClient);\n this.clients = [...this.clients];\n },\n },\n computed: {\n isEditMode() {\n return !!this.editedClientId;\n },\n },\n});\n","export { default } from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./Manage.vue?vue&type=script&lang=ts\"; export * from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--15-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./Manage.vue?vue&type=script&lang=ts\"","import { render } from \"./Manage.vue?vue&type=template&id=f7d6db3a\"\nimport script from \"./Manage.vue?vue&type=script&lang=ts\"\nexport * from \"./Manage.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","/*!\n * Matomo - free/libre analytics platform\n *\n * @link https://matomo.org\n * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n */\n\nexport { default as Oauth2AdminApp } from './OAuthClients/Manage.vue';\n","import './setPublicPath'\nexport * from '~entry'\n"],"sourceRoot":""} \ No newline at end of file diff --git a/vue/dist/OAuth2.umd.min.js b/vue/dist/OAuth2.umd.min.js index 37035c3..58ac934 100644 --- a/vue/dist/OAuth2.umd.min.js +++ b/vue/dist/OAuth2.umd.min.js @@ -1,4 +1,4 @@ -(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):"function"===typeof define&&define.amd?define(["CoreHome",,"CorePluginsAdmin"],t):"object"===typeof exports?exports["OAuth2"]=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):e["OAuth2"]=t(e["CoreHome"],e["Vue"],e["CorePluginsAdmin"])})("undefined"!==typeof self?self:this,(function(e,t,n){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="plugins/OAuth2/vue/dist/",n(n.s="fae3")}({"19dc":function(t,n){t.exports=e},"8bbf":function(e,n){e.exports=t},a5a2:function(e,t){e.exports=n},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"Oauth2AdminApp",(function(){return R})),"undefined"!==typeof window){var i=window.document.currentScript,o=i&&i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);o&&(n.p=o[1])}var l=n("8bbf");const r={class:"oauth2-admin"},a={key:0,class:"alert alert-warning"},c={class:"client-secret-code"},s={class:"form-help"},d={class:"ui-confirm",ref:"confirmDeleteClient"},u=["value"],m=["value"],h={class:"ui-confirm",ref:"confirmRotateClient"},p=["value"],O=["value"],f={key:0,class:"card card-table entityTable"},b=["title"],j={class:"client-id-code"},A={class:"created-at"},_=["onClick","title"],y=["onClick","title"],N={key:1},g={class:"row"},V={class:"row"},C={class:"row",name:"type"},v={class:"row",name:"grantType"},E={class:"row",name:"scopes"},S={class:"row"},k={class:"row"},D=["disabled"];function w(e,t,n,i,o,w){const x=Object(l["resolveComponent"])("ContentBlock"),T=Object(l["resolveComponent"])("Field");return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",r,[e.secret?(Object(l["openBlock"])(),Object(l["createElementBlock"])("div",a,[Object(l["createElementVNode"])("strong",null,Object(l["toDisplayString"])(e.translate("OAuth2_ClientSecret"))+": ",1),Object(l["createTextVNode"])(),Object(l["createElementVNode"])("code",c,Object(l["toDisplayString"])(e.secret),1),Object(l["createElementVNode"])("div",s,Object(l["toDisplayString"])(e.translate("OAuth2_ClientSecretHelp")),1)])):Object(l["createCommentVNode"])("",!0),Object(l["createElementVNode"])("div",d,[Object(l["createElementVNode"])("h2",null,Object(l["toDisplayString"])(e.confirmDeleteLabel),1),Object(l["createElementVNode"])("input",{role:"yes",type:"button",value:e.translate("General_Yes")},null,8,u),Object(l["createElementVNode"])("input",{role:"no",type:"button",value:e.translate("General_No")},null,8,m)],512),Object(l["createTextVNode"])(),Object(l["createElementVNode"])("div",h,[Object(l["createElementVNode"])("h2",null,Object(l["toDisplayString"])(e.confirmRotateLabel),1),Object(l["createElementVNode"])("input",{role:"yes",type:"button",value:e.translate("General_Yes")},null,8,p),Object(l["createElementVNode"])("input",{role:"no",type:"button",value:e.translate("General_No")},null,8,O)],512),Object(l["createVNode"])(x,{"content-title":e.translate("OAuth2_AdminHeading"),feature:e.translate("OAuth2_AdminHeading")},{default:Object(l["withCtx"])(()=>[Object(l["createElementVNode"])("p",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientsDescriptions")),1),e.clients&&e.clients.length?(Object(l["openBlock"])(),Object(l["createElementBlock"])("table",f,[Object(l["createElementVNode"])("thead",null,[Object(l["createElementVNode"])("tr",null,[Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminName")),1),Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientId")),1),Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientCreatedAt")),1),Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientType")),1),Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientGrants")),1),Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientRedirects")),1),Object(l["createElementVNode"])("th",null,Object(l["toDisplayString"])(e.translate("OAuth2_AdminClientActions")),1)])]),Object(l["createElementVNode"])("tbody",null,[(Object(l["openBlock"])(!0),Object(l["createElementBlock"])(l["Fragment"],null,Object(l["renderList"])(e.clients,t=>(Object(l["openBlock"])(),Object(l["createElementBlock"])("tr",{key:t.client_id},[Object(l["createElementVNode"])("td",{title:t.description},[Object(l["createElementVNode"])("strong",null,Object(l["toDisplayString"])(t.name),1)],8,b),Object(l["createElementVNode"])("td",null,[Object(l["createElementVNode"])("code",j,Object(l["toDisplayString"])(t.client_id),1)]),Object(l["createElementVNode"])("td",A,Object(l["toDisplayString"])(t.created_at),1),Object(l["createElementVNode"])("td",null,Object(l["toDisplayString"])(e.type_options[t.type]),1),Object(l["createElementVNode"])("td",null,Object(l["toDisplayString"])((t.grant_types||[]).join(", ")),1),Object(l["createElementVNode"])("td",null,[(Object(l["openBlock"])(!0),Object(l["createElementBlock"])(l["Fragment"],null,Object(l["renderList"])(t.redirect_uris||[],e=>(Object(l["openBlock"])(),Object(l["createElementBlock"])("div",{key:e},[Object(l["createElementVNode"])("code",null,Object(l["toDisplayString"])(e),1)]))),128))]),Object(l["createElementVNode"])("td",null,[Object(l["createElementVNode"])("button",{class:"table-action icon-refresh",onClick:Object(l["withModifiers"])(n=>e.rotateSecret(t),["prevent"]),title:e.translate("OAuth2_AdminRotateSecret")},null,8,_),Object(l["createElementVNode"])("button",{class:"table-action icon-delete",onClick:Object(l["withModifiers"])(n=>e.deleteClient(t),["prevent"]),title:e.translate("OAuth2_AdminDelete")},null,8,y)])]))),128))])])):(Object(l["openBlock"])(),Object(l["createElementBlock"])("div",N,Object(l["toDisplayString"])(e.translate("OAuth2_AdminNoClients")),1))]),_:1},8,["content-title","feature"]),Object(l["createVNode"])(x,{"content-title":e.translate("OAuth2_AdminCreateTitle")},{default:Object(l["withCtx"])(()=>[Object(l["createElementVNode"])("form",{onSubmit:t[6]||(t[6]=Object(l["withModifiers"])((...t)=>e.createClient&&e.createClient(...t),["prevent"]))},[Object(l["createElementVNode"])("div",g,[Object(l["createVNode"])(T,{uicontrol:"text",name:"name",modelValue:e.form.name,"onUpdate:modelValue":t[0]||(t[0]=t=>e.form.name=t),"inline-help":e.translate("OAuth2_AdminNameHelp"),title:e.translate("OAuth2_AdminName")},null,8,["modelValue","inline-help","title"])]),Object(l["createElementVNode"])("div",V,[Object(l["createVNode"])(T,{uicontrol:"textarea",name:"description",modelValue:e.form.description,"onUpdate:modelValue":t[1]||(t[1]=t=>e.form.description=t),"inline-help":e.translate("OAuth2_AdminDescriptionHelp"),title:e.translate("OAuth2_AdminDescription")},null,8,["modelValue","inline-help","title"])]),Object(l["createElementVNode"])("div",C,[Object(l["createVNode"])(T,{uicontrol:"select",name:"type",modelValue:e.form.type,"onUpdate:modelValue":t[2]||(t[2]=t=>e.form.type=t),title:e.translate("OAuth2_AdminType"),"inline-help":e.translate("OAuth2_AdminTypeHelp","",""),options:{confidential:e.translate("OAuth2_AdminConfidential"),public:e.translate("OAuth2_AdminPublic")}},null,8,["modelValue","title","inline-help","options"])]),Object(l["createElementVNode"])("div",v,[Object(l["createVNode"])(T,{uicontrol:"checkbox",options:e.visibleGrantOptions,"var-type":"array",name:"grant_types",modelValue:e.form.grant_types,"onUpdate:modelValue":t[3]||(t[3]=t=>e.form.grant_types=t),"inline-help":e.translate("OAuth2_AdminGrantTypesHelp"),title:e.translate("OAuth2_AdminClientGrants")},null,8,["options","modelValue","inline-help","title"])]),Object(l["createElementVNode"])("div",E,[Object(l["createVNode"])(T,{uicontrol:"select",options:e.scopes,name:"scopes",modelValue:e.form.scope,"onUpdate:modelValue":t[4]||(t[4]=t=>e.form.scope=t),"inline-help":e.translate("OAuth2_AdminScopeHelp","",""),title:e.translate("OAuth2_AdminScope")},null,8,["options","modelValue","inline-help","title"])]),Object(l["createElementVNode"])("div",S,[Object(l["createVNode"])(T,{uicontrol:"textarea",name:"redirect_uris",modelValue:e.form.redirect_uris,"onUpdate:modelValue":t[5]||(t[5]=t=>e.form.redirect_uris=t),placeholder:"https://example.com/callback","inline-help":e.translate("OAuth2_AdminRedirectUrisHelp"),title:e.translate("OAuth2_AdminRedirectUris")},null,8,["modelValue","inline-help","title"])]),Object(l["createElementVNode"])("div",k,[Object(l["createElementVNode"])("button",{type:"submit",class:"btn",disabled:e.loading},Object(l["toDisplayString"])(e.translate("OAuth2_AdminSave")),9,D)])],32)]),_:1},8,["content-title"])])}var x=n("a5a2"),T=n("19dc");const B="oauth2clientcreate";var H=Object(l["defineComponent"])({name:"Oauth2AdminApp",props:{initialClients:{type:Array,required:!0},scopes:{type:Object,required:!0}},components:{Field:x["Field"],ContentBlock:T["ContentBlock"]},data(){const e={confidential:this.translate("OAuth2_AdminConfidential"),public:this.translate("OAuth2_AdminPublic")},t={authorization_code:this.translate("OAuth2_AdminGrantAuthorizationCode"),client_credentials:this.translate("OAuth2_AdminGrantClientCredentials"),refresh_token:this.translate("OAuth2_AdminGrantRefreshToken")};return{clients:this.initialClients||[],loading:!1,secret:"",confirmDeleteLabel:"",confirmRotateLabel:"",grant_options:t,type_options:e,form:{name:"",description:"",type:"confidential",grant_types:["authorization_code","client_credentials","refresh_token"],scope:"",redirect_uris:"",active:!0}}},computed:{visibleGrantOptions(){if("public"===this.form.type){const e={};return this.grant_options.authorization_code&&(e.authorization_code=this.grant_options.authorization_code),this.grant_options.refresh_token&&(e.refresh_token=this.grant_options.refresh_token),e}return this.grant_options}},watch:{"form.type":"onFormTypeChange"},methods:{onFormTypeChange(e){"public"===e&&this.form.grant_types.includes("client_credentials")&&(this.form.grant_types=this.form.grant_types.filter(e=>"client_credentials"!==e))},showSuccessNotification(e,t){const n=`${t}`,i=T["NotificationsStore"].show({id:"OAuth2_"+e,type:"transient",context:"success",message:n});setTimeout(()=>{T["NotificationsStore"].scrollToNotification(i)})},async fetchClients(){this.loading=!0;try{await T["AjaxHelper"].fetch({method:"OAuth2.getClients",filter_limit:"-1"}).then(e=>{this.clients=e})}finally{this.loading=!1}},async createClient(){if(this.removeAnyClientNotification(),!this.checkRequiredFieldsAreSet())return;this.loading=!0,this.secret="";const e={method:"OAuth2.createClient",name:this.form.name,description:this.form.description,type:this.form.type,grantTypes:this.form.grant_types,scope:this.form.scope,redirectUris:this.form.redirect_uris,active:1};try{await T["AjaxHelper"].fetch(e).then(e=>{this.clients.push(e.client);const t=this.translate("OAuth2_AdminCreated",e.client.client_id);this.showSuccessNotification("createClient",t),e.secret&&(this.secret=e.secret),this.resetForm()})}finally{this.loading=!1}},async rotateSecret(e){e&&(this.confirmRotateLabel=this.translate("OAuth2_AdminRotateConfirm",(null===e||void 0===e?void 0:e.name)||(null===e||void 0===e?void 0:e.client_id)),T["Matomo"].helper.modalConfirm(this.$refs.confirmRotateClient,{yes:()=>{this.loading=!0;try{T["AjaxHelper"].fetch({method:"OAuth2.rotateSecret",clientId:e.client_id}).then(t=>{if(t&&t.secret){this.secret=t.secret;const n=this.translate("OAuth2_AdminRotated",e.client_id);this.showSuccessNotification("rotateSecret",n)}})}finally{this.loading=!1}}}))},async deleteClient(e){e&&(this.confirmDeleteLabel=this.translate("OAuth2_AdminDeleteConfirm",(null===e||void 0===e?void 0:e.name)||(null===e||void 0===e?void 0:e.client_id)),T["Matomo"].helper.modalConfirm(this.$refs.confirmDeleteClient,{yes:()=>{this.loading=!0;try{T["AjaxHelper"].fetch({method:"OAuth2.deleteClient",clientId:e.client_id}).then(t=>{if(t.deleted){this.clients=this.clients.filter(t=>t.client_id!==e.client_id);const t=this.translate("OAuth2_AdminDeleted",e.client_id);this.showSuccessNotification("deleteClient",t)}})}finally{this.loading=!1}}}))},resetForm(){this.form.name="",this.form.description="",this.form.type="confidential",this.form.grant_types=["authorization_code","client_credentials","refresh_token"],this.form.scope="",this.form.redirect_uris="",this.form.active=!0},checkRequiredFieldsAreSet(){let e=!0,t="";return this.form.name.trim()?this.form.type.trim()?this.form.grant_types.length?this.form.scope.trim()?!this.form.redirect_uris.trim()&&this.form.grant_types.includes("authorization_code")&&(e=!1,t=this.translate("OAuth2_AdminRedirectUris")):(e=!1,t=this.translate("OAuth2_AdminScope")):(e=!1,t=this.translate("OAuth2_AdminClientGrants")):(e=!1,t=this.translate("OAuth2_AdminType")):(e=!1,t=this.translate("OAuth2_AdminName")),!e&&t&&this.showErrorFieldNotProvidedNotification(t),e},removeAnyClientNotification(){T["NotificationsStore"].remove(B),T["NotificationsStore"].remove("ajaxHelper")},showNotification(e,t,n=null){const i=T["NotificationsStore"].show({message:e,context:t,id:B,type:null!==n?n:"toast"});setTimeout(()=>{T["NotificationsStore"].scrollToNotification(i)},200)},showErrorFieldNotProvidedNotification(e){const t=this.translate("OAuth2_ErrorXNotProvided",[e]);this.showNotification(t,"error")}}});H.render=w;var R=H; +(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):"function"===typeof define&&define.amd?define(["CoreHome",,"CorePluginsAdmin"],t):"object"===typeof exports?exports["OAuth2"]=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):e["OAuth2"]=t(e["CoreHome"],e["Vue"],e["CorePluginsAdmin"])})("undefined"!==typeof self?self:this,(function(e,t,i){return function(e){var t={};function i(n){if(t[n])return t[n].exports;var l=t[n]={i:n,l:!1,exports:{}};return e[n].call(l.exports,l,l.exports,i),l.l=!0,l.exports}return i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)i.d(n,l,function(t){return e[t]}.bind(null,l));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="plugins/OAuth2/vue/dist/",i(i.s="fae3")}({"19dc":function(t,i){t.exports=e},6949:function(e,t,i){"use strict";i("a85f")},7964:function(e,t,i){"use strict";i("b47c")},"8bbf":function(e,i){e.exports=t},a5a2:function(e,t){e.exports=i},a85f:function(e,t,i){},b47c:function(e,t,i){},fae3:function(e,t,i){"use strict";if(i.r(t),i.d(t,"Oauth2AdminApp",(function(){return he})),"undefined"!==typeof window){var n=window.document.currentScript,l=n&&n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);l&&(i.p=l[1])}var o=i("8bbf");const c={class:"oauth2-admin"};function a(e,t,i,n,l,a){const r=Object(o["resolveComponent"])("Oauth2ClientList"),s=Object(o["resolveComponent"])("Oauth2ClientEdit");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",c,[e.isEditMode?(Object(o["openBlock"])(),Object(o["createBlock"])(s,{key:1,"client-id":e.editedClientId,scopes:e.scopes,"initial-secret":e.secret,onCancel:e.showList,onSaved:e.onClientSaved},null,8,["client-id","scopes","initial-secret","onCancel","onSaved"])):(Object(o["openBlock"])(),Object(o["createBlock"])(r,{key:0,clients:e.clients,onCreate:e.createClient,onEdit:e.editClient,onDeleted:e.onClientDeleted,onUpdated:e.onClientUpdated},null,8,["clients","onCreate","onEdit","onDeleted","onUpdated"]))])}var r=i("19dc");const s=e=>(Object(o["pushScopeId"])("data-v-9cba7004"),e=e(),Object(o["popScopeId"])(),e),d={class:"oauth2-admin oauth2-admin-list"},u={class:"ui-confirm",ref:"confirmDeleteClient"},m=["value"],h=["value"],p={class:"ui-confirm",ref:"confirmToggleClient"},O=["value"],b=["value"],j={key:0},f={style:{width:"220px"}},A=["title"],y={class:"client-id-code"},_={class:"redirect-uri"},v={class:"created-at"},C=["onClick","title"],g=["onClick","title"],N=["onClick","title"],E={key:1},S={class:"tableActionBar"},V=s(()=>Object(o["createElementVNode"])("span",{class:"icon-add"},null,-1));function k(e,t,i,n,l,c){const a=Object(o["resolveComponent"])("ContentBlock"),r=Object(o["resolveDirective"])("content-table");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",d,[Object(o["createElementVNode"])("div",u,[Object(o["createElementVNode"])("h2",null,Object(o["toDisplayString"])(e.confirmDeleteLabel),1),Object(o["createElementVNode"])("input",{role:"yes",type:"button",value:e.translate("General_Yes")},null,8,m),Object(o["createElementVNode"])("input",{role:"no",type:"button",value:e.translate("General_No")},null,8,h)],512),Object(o["createElementVNode"])("div",p,[Object(o["createElementVNode"])("h2",null,Object(o["toDisplayString"])(e.confirmToggleLabel),1),Object(o["createElementVNode"])("input",{role:"yes",type:"button",value:e.translate("General_Yes")},null,8,O),Object(o["createElementVNode"])("input",{role:"no",type:"button",value:e.translate("General_No")},null,8,b)],512),Object(o["createVNode"])(a,{"content-title":e.translate("OAuth2_AdminHeading"),feature:e.translate("OAuth2_AdminHeading")},{default:Object(o["withCtx"])(()=>[Object(o["createElementVNode"])("p",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientsDescriptions")),1),e.clients.length?Object(o["withDirectives"])((Object(o["openBlock"])(),Object(o["createElementBlock"])("table",j,[Object(o["createElementVNode"])("thead",null,[Object(o["createElementVNode"])("tr",null,[Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminName")),1),Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientType")),1),Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientGrants")),1),Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientStatus")),1),Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientId")),1),Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientRedirects")),1),Object(o["createElementVNode"])("th",null,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientCreatedAt")),1),Object(o["createElementVNode"])("th",f,Object(o["toDisplayString"])(e.translate("OAuth2_AdminClientActions")),1)])]),Object(o["createElementVNode"])("tbody",null,[(Object(o["openBlock"])(!0),Object(o["createElementBlock"])(o["Fragment"],null,Object(o["renderList"])(e.clients,t=>(Object(o["openBlock"])(),Object(o["createElementBlock"])("tr",{key:t.client_id},[Object(o["createElementVNode"])("td",{title:e.$sanitize(t.description)},Object(o["toDisplayString"])(t.name),9,A),Object(o["createElementVNode"])("td",null,Object(o["toDisplayString"])(e.typeOptions[t.type]),1),Object(o["createElementVNode"])("td",null,Object(o["toDisplayString"])((t.grant_types||[]).join(", ")),1),Object(o["createElementVNode"])("td",null,[Object(o["createElementVNode"])("span",null,Object(o["toDisplayString"])(t.active?e.translate("OAuth2_AdminActive"):e.translate("OAuth2_AdminDisabled")),1)]),Object(o["createElementVNode"])("td",null,[Object(o["createElementVNode"])("code",y,Object(o["toDisplayString"])(t.client_id),1)]),Object(o["createElementVNode"])("td",null,[(Object(o["openBlock"])(!0),Object(o["createElementBlock"])(o["Fragment"],null,Object(o["renderList"])(t.redirect_uris||[],e=>(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{key:e},[Object(o["createElementVNode"])("code",_,Object(o["toDisplayString"])(e),1)]))),128))]),Object(o["createElementVNode"])("td",v,Object(o["toDisplayString"])(t.created_at),1),Object(o["createElementVNode"])("td",null,[Object(o["createElementVNode"])("button",{class:Object(o["normalizeClass"])("table-action "+(t.active?"icon-pause":"icon-play")),onClick:Object(o["withModifiers"])(i=>e.toggleClientStatus(t),["prevent"]),title:t.active?e.translate("OAuth2_AdminPause"):e.translate("OAuth2_AdminResume")},null,10,C),Object(o["createElementVNode"])("button",{class:"table-action icon-edit",onClick:Object(o["withModifiers"])(i=>e.$emit("edit",t.client_id),["prevent"]),title:e.translate("OAuth2_AdminEdit")},null,8,g),Object(o["createElementVNode"])("button",{class:"table-action icon-delete",onClick:Object(o["withModifiers"])(i=>e.deleteClient(t),["prevent"]),title:e.translate("OAuth2_AdminDelete")},null,8,N)])]))),128))])])),[[r]]):(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",E,Object(o["toDisplayString"])(e.translate("OAuth2_AdminNoClients")),1)),Object(o["createElementVNode"])("div",S,[Object(o["createElementVNode"])("a",{class:"createNewClient",onClick:t[0]||(t[0]=Object(o["withModifiers"])(t=>e.$emit("create"),["prevent"]))},[V,Object(o["createTextVNode"])(" "+Object(o["toDisplayString"])(e.translate("OAuth2_AdminCreateTitle")),1)])])]),_:1},8,["content-title","feature"])])}const D="oauth2clientlist";var w=Object(o["defineComponent"])({name:"Oauth2ClientList",props:{clients:{type:Array,required:!0}},emits:["create","edit","deleted","updated"],components:{ContentBlock:r["ContentBlock"]},directives:{ContentTable:r["ContentTable"]},data(){return{confirmDeleteLabel:"",confirmToggleLabel:"",typeOptions:{confidential:this.translate("OAuth2_AdminConfidential"),public:this.translate("OAuth2_AdminPublic")}}},methods:{showNotification(e,t,i=null){const n=r["NotificationsStore"].show({message:e,context:t,id:D,type:null!==i?i:"toast"});setTimeout(()=>{r["NotificationsStore"].scrollToNotification(n)},200)},removeNotifications(){r["NotificationsStore"].remove(D),r["NotificationsStore"].remove("ajaxHelper")},toggleClientStatus(e){this.confirmToggleLabel=e.active?this.translate("OAuth2_AdminPauseConfirm",e.name||e.client_id):this.translate("OAuth2_AdminResumeConfirm",e.name||e.client_id),r["Matomo"].helper.modalConfirm(this.$refs.confirmToggleClient,{yes:()=>{r["AjaxHelper"].fetch({method:"OAuth2.setClientActive",clientId:e.client_id,active:e.active?"0":"1"}).then(e=>{null!==e&&void 0!==e&&e.client&&(this.removeNotifications(),this.showNotification(e.client.active?this.translate("OAuth2_AdminResumed",e.client.name||e.client.client_id):this.translate("OAuth2_AdminPaused",e.client.name||e.client.client_id),"success"),this.$emit("updated",e.client))})}})},deleteClient(e){this.confirmDeleteLabel=this.translate("OAuth2_AdminDeleteConfirm",e.name||e.client_id),r["Matomo"].helper.modalConfirm(this.$refs.confirmDeleteClient,{yes:()=>{r["AjaxHelper"].fetch({method:"OAuth2.deleteClient",clientId:e.client_id}).then(t=>{null!==t&&void 0!==t&&t.deleted&&(this.removeNotifications(),this.showNotification(this.translate("OAuth2_AdminDeleted",e.name),"success"),this.$emit("deleted",e.client_id))})}})}}});i("6949");w.render=k,w.__scopeId="data-v-9cba7004";var B=w;const I=e=>(Object(o["pushScopeId"])("data-v-15c605de"),e=e(),Object(o["popScopeId"])(),e),M={class:"oauth2-admin oauth2-admin-edit"},T={class:"ui-confirm",ref:"confirmRotateClient"},x=["value"],H=["value"],P={key:0},U={class:"loadingPiwik"},L=I(()=>Object(o["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif"},null,-1)),R={class:"row"},G={class:"row"},q={key:0,class:"row"},$={key:1,class:"row oauth2-secret-head"},F={class:"col s12"},z={key:2,class:"oauth2-secret-div form-group row matomo-form-field"},Y={class:"col s12 m6"},X={class:"copy-secret-wrapper-div"},J={key:0,class:"client-secret-code"},K={key:1,class:"client-secret-code"},Q={class:"col s12 m6"},W=["innerHTML"],Z={class:"row",name:"type"},ee={class:"row",name:"grantType"},te={class:"row",name:"scopes"},ie={class:"row"},ne={class:"row"},le=["disabled"],oe={class:"entityCancel"};function ce(e,t,i,n,l,c){const a=Object(o["resolveComponent"])("Field"),r=Object(o["resolveComponent"])("ContentBlock"),s=Object(o["resolveDirective"])("copy-to-clipboard");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",M,[Object(o["createElementVNode"])("div",T,[Object(o["createElementVNode"])("h2",null,Object(o["toDisplayString"])(e.confirmRotateLabel),1),Object(o["createElementVNode"])("input",{role:"yes",type:"button",value:e.translate("General_Yes")},null,8,x),Object(o["createElementVNode"])("input",{role:"no",type:"button",value:e.translate("General_No")},null,8,H)],512),Object(o["createVNode"])(r,{"content-title":e.contentTitle},{default:Object(o["withCtx"])(()=>[e.loading?(Object(o["openBlock"])(),Object(o["createElementBlock"])("p",P,[Object(o["createElementVNode"])("span",U,[L,Object(o["createTextVNode"])(" "+Object(o["toDisplayString"])(e.translate("General_LoadingData")),1)])])):(Object(o["openBlock"])(),Object(o["createElementBlock"])("form",{key:1,onSubmit:t[8]||(t[8]=Object(o["withModifiers"])((...t)=>e.submit&&e.submit(...t),["prevent"]))},[Object(o["createElementVNode"])("div",R,[Object(o["createVNode"])(a,{uicontrol:"text",name:"name",modelValue:e.form.name,"onUpdate:modelValue":t[0]||(t[0]=t=>e.form.name=t),"inline-help":e.translate("OAuth2_AdminNameHelp"),title:e.translate("OAuth2_AdminName")},null,8,["modelValue","inline-help","title"])]),Object(o["createElementVNode"])("div",G,[Object(o["createVNode"])(a,{uicontrol:"textarea",name:"description",modelValue:e.form.description,"onUpdate:modelValue":t[1]||(t[1]=t=>e.form.description=t),rows:1,"ui-control-attributes":{style:"min-height: auto;"},"inline-help":e.translate("OAuth2_AdminDescriptionHelp"),title:e.translate("OAuth2_AdminDescription"),placeholder:e.translate("OAuth2_AdminDescriptionPlaceholder")},null,8,["modelValue","inline-help","title","placeholder"])]),e.isEditMode?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",q,[Object(o["createVNode"])(a,{uicontrol:"text",name:"client_id","model-value":e.clientId,title:e.translate("OAuth2_AdminClientId"),disabled:!0},null,8,["model-value","title"])])):Object(o["createCommentVNode"])("",!0),e.showSecretPanel?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",$,[Object(o["createElementVNode"])("label",F,[Object(o["createTextVNode"])(Object(o["toDisplayString"])(e.translate("OAuth2_ClientSecret"))+" ",1),e.canRegenerateSecret?(Object(o["openBlock"])(),Object(o["createElementBlock"])("a",{key:0,onClick:t[2]||(t[2]=Object(o["withModifiers"])((...t)=>e.rotateSecret&&e.rotateSecret(...t),["prevent"]))}," ("+Object(o["toDisplayString"])(e.translate("OAuth2_AdminRotateSecret"))+") ",1)):Object(o["createCommentVNode"])("",!0)])])):Object(o["createCommentVNode"])("",!0),e.showSecretPanel?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",z,[Object(o["createElementVNode"])("div",Y,[Object(o["createElementVNode"])("div",X,[e.visibleSecret?Object(o["withDirectives"])((Object(o["openBlock"])(),Object(o["createElementBlock"])("pre",J,[Object(o["createTextVNode"])(Object(o["toDisplayString"])(e.displayedSecret),1)])),[[s,{}]]):(Object(o["openBlock"])(),Object(o["createElementBlock"])("pre",K,Object(o["toDisplayString"])(e.displayedSecret),1))])]),Object(o["createElementVNode"])("div",Q,[Object(o["createElementVNode"])("div",{class:"form-help",innerHTML:e.$sanitize(e.secretInlineHelp)},null,8,W)])])):Object(o["createCommentVNode"])("",!0),Object(o["createElementVNode"])("div",Z,[e.isEditMode?(Object(o["openBlock"])(),Object(o["createBlock"])(a,{key:1,uicontrol:"text",name:"type","model-value":e.typeOptions[e.form.type]||e.form.type,title:e.translate("OAuth2_AdminType"),disabled:!0},null,8,["model-value","title"])):(Object(o["openBlock"])(),Object(o["createBlock"])(a,{key:0,uicontrol:"select",name:"type",modelValue:e.form.type,"onUpdate:modelValue":t[3]||(t[3]=t=>e.form.type=t),title:e.translate("OAuth2_AdminType"),"inline-help":e.translate("OAuth2_AdminTypeHelp","",""),options:e.typeOptions},null,8,["modelValue","title","inline-help","options"]))]),Object(o["createElementVNode"])("div",ee,[Object(o["createVNode"])(a,{uicontrol:"checkbox",options:e.visibleGrantOptions,"var-type":"array",name:"grant_types",modelValue:e.form.grant_types,"onUpdate:modelValue":t[4]||(t[4]=t=>e.form.grant_types=t),"inline-help":e.translate("OAuth2_AdminGrantTypesHelp"),title:e.translate("OAuth2_AdminClientGrants")},null,8,["options","modelValue","inline-help","title"])]),Object(o["createElementVNode"])("div",te,[Object(o["createVNode"])(a,{uicontrol:"select",options:e.scopes,name:"scopes",modelValue:e.form.scope,"onUpdate:modelValue":t[5]||(t[5]=t=>e.form.scope=t),"inline-help":e.translate("OAuth2_AdminScopeHelp","",""),title:e.translate("OAuth2_AdminScope")},null,8,["options","modelValue","inline-help","title"])]),Object(o["createElementVNode"])("div",ie,[Object(o["createVNode"])(a,{uicontrol:"textarea",name:"redirect_uris",modelValue:e.form.redirect_uris,"onUpdate:modelValue":t[6]||(t[6]=t=>e.form.redirect_uris=t),placeholder:"https://example.com/callback","inline-help":e.translate("OAuth2_AdminRedirectUrisHelp"),title:e.translate("OAuth2_AdminRedirectUris")},null,8,["modelValue","inline-help","title"])]),Object(o["createElementVNode"])("div",ne,[Object(o["createElementVNode"])("button",{type:"submit",class:"btn",disabled:e.loading},Object(o["toDisplayString"])(e.submitLabel),9,le)]),Object(o["createElementVNode"])("div",oe,[Object(o["createElementVNode"])("a",{onClick:t[7]||(t[7]=Object(o["withModifiers"])(t=>e.$emit("cancel"),["prevent"]))},Object(o["toDisplayString"])(e.translate("General_Cancel")),1)])],32))]),_:1},8,["content-title"])])}var ae=i("a5a2");const re="oauth2clientedit";function se(e){const t=Object.keys(e||{})[0]||"";return{name:"",description:"",type:"confidential",grant_types:["authorization_code","client_credentials","refresh_token"],scope:t,redirect_uris:"",active:!0}}var de=Object(o["defineComponent"])({name:"Oauth2ClientEdit",props:{clientId:{type:String,required:!0},initialSecret:{type:String,default:""},scopes:{type:Object,required:!0}},directives:{CopyToClipboard:r["CopyToClipboard"]},emits:["cancel","saved"],components:{ContentBlock:r["ContentBlock"],Field:ae["Field"]},data(){const e={confidential:this.translate("OAuth2_AdminConfidential"),public:this.translate("OAuth2_AdminPublic")},t={authorization_code:this.translate("OAuth2_AdminGrantAuthorizationCode"),client_credentials:this.translate("OAuth2_AdminGrantClientCredentials"),refresh_token:this.translate("OAuth2_AdminGrantRefreshToken")};return{loading:!1,confirmRotateLabel:"",typeOptions:e,grantOptions:t,form:se(this.scopes),visibleSecret:this.initialSecret}},created(){this.init()},watch:{clientId(){this.init()},initialSecret(e){this.visibleSecret=e},"form.type":"onFormTypeChange"},computed:{isEditMode(){return"0"!==this.clientId},contentTitle(){return this.isEditMode?this.translate("OAuth2_AdminEditTitle"):this.translate("OAuth2_AdminCreateTitle")},submitLabel(){return this.isEditMode?this.translate("OAuth2_AdminUpdate"):this.translate("OAuth2_AdminSave")},visibleGrantOptions(){if("public"===this.form.type){const e={};return this.grantOptions.authorization_code&&(e.authorization_code=this.grantOptions.authorization_code),this.grantOptions.refresh_token&&(e.refresh_token=this.grantOptions.refresh_token),e}return this.grantOptions},showSecretPanel(){return"confidential"===this.form.type&&(this.isEditMode||!!this.visibleSecret)},canRegenerateSecret(){return this.isEditMode&&"confidential"===this.form.type},displayedSecret(){return this.visibleSecret||"*************"},secretInlineHelp(){return this.visibleSecret?this.translate("OAuth2_ClientSecretVisibleHelp"):this.translate("OAuth2_ClientSecretMaskedHelp")}},methods:{init(){this.removeNotifications(),this.form=se(this.scopes),this.visibleSecret=this.initialSecret,this.isEditMode&&(this.loading=!0,r["AjaxHelper"].fetch({method:"OAuth2.getClient",clientId:this.clientId}).then(e=>{this.form={name:e.name||"",description:e.description||"",type:e.type||"confidential",grant_types:e.grant_types||[],scope:e.scopes&&e.scopes[0]||Object.keys(this.scopes||{})[0]||"",redirect_uris:(e.redirect_uris||[]).join("\n"),active:!!e.active}}).finally(()=>{this.loading=!1}))},onFormTypeChange(e){"public"===e&&this.form.grant_types.includes("client_credentials")&&(this.form.grant_types=this.form.grant_types.filter(e=>"client_credentials"!==e)),"public"===e&&(this.visibleSecret="")},rotateSecret(){this.canRegenerateSecret&&(this.confirmRotateLabel=this.translate("OAuth2_AdminRotateConfirm",this.form.name||this.clientId),r["Matomo"].helper.modalConfirm(this.$refs.confirmRotateClient,{yes:()=>{this.loading=!0,r["AjaxHelper"].fetch({method:"OAuth2.rotateSecret",clientId:this.clientId}).then(e=>{null!==e&&void 0!==e&&e.secret&&(this.visibleSecret=e.secret)}).finally(()=>{this.loading=!1})}}))},submit(){if(this.removeNotifications(),!this.checkRequiredFieldsAreSet())return;this.loading=!0;const e={method:this.isEditMode?"OAuth2.updateClient":"OAuth2.createClient",name:this.form.name.trim(),description:this.form.description,type:this.form.type,grantTypes:this.form.grant_types,scope:this.form.scope,redirectUris:this.form.redirect_uris,active:this.form.active?"1":"0"};this.isEditMode&&(e.clientId=this.clientId),r["AjaxHelper"].fetch(e).then(e=>{this.visibleSecret=e.secret||"";const t=this.isEditMode?this.translate("OAuth2_AdminUpdated",e.client.name):this.translate("OAuth2_AdminCreated",e.client.name),i=e.secret?this.translate("OAuth2_ClientSecretHelp"):"",n=[t,i].filter(Boolean).join(" ");this.$emit("saved",{client:e.client,secret:e.secret||null}),r["MatomoUrl"].updateHash(Object.assign(Object.assign({},r["MatomoUrl"].hashParsed.value),{},{idClient:e.client.client_id})),setTimeout(()=>{this.showNotification(`${n}`,"success","transient")},50)}).finally(()=>{this.loading=!1})},checkRequiredFieldsAreSet(){let e=!0,t="";return this.form.name.trim()?this.form.type.trim()?this.form.grant_types.length?this.form.scope.trim()?!this.form.redirect_uris.trim()&&this.form.grant_types.includes("authorization_code")&&(e=!1,t=this.translate("OAuth2_AdminRedirectUris")):(e=!1,t=this.translate("OAuth2_AdminScope")):(e=!1,t=this.translate("OAuth2_AdminClientGrants")):(e=!1,t=this.translate("OAuth2_AdminType")):(e=!1,t=this.translate("OAuth2_AdminName")),!e&&t&&this.showErrorFieldNotProvidedNotification(t),e},removeNotifications(){r["NotificationsStore"].remove(re),r["NotificationsStore"].remove("ajaxHelper")},showNotification(e,t,i=null){const n=r["NotificationsStore"].show({message:e,context:t,id:re,type:null!==i?i:"toast"});setTimeout(()=>{r["NotificationsStore"].scrollToNotification(n)},200)},showErrorFieldNotProvidedNotification(e){const t=this.translate("OAuth2_ErrorXNotProvided",[e]);this.showNotification(t,"error")}}});i("7964");de.render=ce,de.__scopeId="data-v-15c605de";var ue=de,me=Object(o["defineComponent"])({name:"Oauth2AdminApp",props:{initialClients:{type:Array,required:!0},scopes:{type:Object,required:!0}},components:{Oauth2ClientList:B,Oauth2ClientEdit:ue},data(){return{clients:this.initialClients||[],secret:"",secretClientId:"",editedClientId:""}},created(){Object(o["watch"])(()=>r["MatomoUrl"].hashParsed.value.idClient,e=>{this.initState(e)}),this.initState(r["MatomoUrl"].hashParsed.value.idClient)},methods:{initState(e){e?this.secretClientId&&this.secretClientId!==e&&(this.secret="",this.secretClientId=""):(this.secret="",this.secretClientId=""),this.editedClientId=e||""},createClient(){r["MatomoUrl"].updateHash(Object.assign(Object.assign({},r["MatomoUrl"].hashParsed.value),{},{idClient:"0"})),this.secret="",this.secretClientId=""},editClient(e){this.secretClientId!==e&&(this.secret="",this.secretClientId=""),r["MatomoUrl"].updateHash(Object.assign(Object.assign({},r["MatomoUrl"].hashParsed.value),{},{idClient:e}))},showList(){const e=Object.assign({},r["MatomoUrl"].hashParsed.value);delete e.idClient,this.secret="",this.secretClientId="",r["MatomoUrl"].updateHash(e)},onClientSaved(e){const t=this.clients.findIndex(t=>t.client_id===e.client.client_id);-1===t?this.clients.push(e.client):this.clients.splice(t,1,e.client),this.clients=[...this.clients].sort((e,t)=>{const i=e.updated_at?new Date(e.updated_at).getTime():0,n=t.updated_at?new Date(t.updated_at).getTime():0;return n!==i?n-i:e.name.localeCompare(t.name)}),this.secret=e.secret||"",this.secretClientId=e.secret?e.client.client_id:""},onClientDeleted(e){this.secret="",this.secretClientId===e&&(this.secretClientId=""),this.clients=this.clients.filter(t=>t.client_id!==e)},onClientUpdated(e){const t=this.clients.findIndex(t=>t.client_id===e.client_id);-1!==t&&(this.clients.splice(t,1,e),this.clients=[...this.clients])}},computed:{isEditMode(){return!!this.editedClientId}}});me.render=a;var he=me; /*! * Matomo - free/libre analytics platform * diff --git a/vue/dist/OAuth2.umd.min.js.map b/vue/dist/OAuth2.umd.min.js.map index 8e8d857..91169e9 100644 --- a/vue/dist/OAuth2.umd.min.js.map +++ b/vue/dist/OAuth2.umd.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://OAuth2/webpack/universalModuleDefinition","webpack://OAuth2/webpack/bootstrap","webpack://OAuth2/external \"CoreHome\"","webpack://OAuth2/external {\"commonjs\":\"vue\",\"commonjs2\":\"vue\",\"root\":\"Vue\"}","webpack://OAuth2/external \"CorePluginsAdmin\"","webpack://OAuth2/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue?ce89","webpack://OAuth2/./plugins/OAuth2/vue/src/AdminApp.vue?e86a"],"names":["root","factory","exports","module","require","define","amd","self","this","__WEBPACK_EXTERNAL_MODULE__19dc__","__WEBPACK_EXTERNAL_MODULE__8bbf__","__WEBPACK_EXTERNAL_MODULE_a5a2__","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","window","currentScript","document","src","match","class","ref","secret","translate","confirmDeleteLabel","role","type","confirmRotateLabel","content-title","feature","clients","length","client","client_id","title","description","created_at","type_options","grant_types","join","redirect_uris","uri","rotateSecret","deleteClient","createClient","uicontrol","form","inline-help","options","visibleGrantOptions","var-type","scopes","scope","placeholder","disabled","loading","notificationId","props","initialClients","Array","required","components","Field","ContentBlock","typeOptions","confidential","public","grantOptions","authorization_code","client_credentials","refresh_token","grant_options","active","computed","filtered","watch","methods","newType","includes","filter","method","message","messageBody","instanceId","show","id","context","setTimeout","scrollToNotification","fetch","filter_limit","then","removeAnyClientNotification","checkRequiredFieldsAreSet","params","grantTypes","redirectUris","response","push","showSuccessNotification","resetForm","helper","modalConfirm","$refs","confirmRotateClient","yes","clientId","confirmDeleteClient","deleted","errorMessage","trim","showErrorFieldNotProvidedNotification","remove","notificationInstanceId","showNotification","render"],"mappings":"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","file":"OAuth2.umd.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"CoreHome\", , \"CorePluginsAdmin\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"OAuth2\"] = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse\n\t\troot[\"OAuth2\"] = factory(root[\"CoreHome\"], root[\"Vue\"], root[\"CorePluginsAdmin\"]);\n})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"plugins/OAuth2/vue/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fae3\");\n","module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;","module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;","module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","\n\n\n","\nimport { defineComponent } from 'vue';\nimport { Field } from 'CorePluginsAdmin';\nimport {\n Matomo,\n ContentBlock,\n AjaxHelper,\n NotificationsStore,\n NotificationType,\n} from 'CoreHome';\n\ntype Client = {\n client_id: string;\n name: string;\n description?: string;\n type: string;\n grant_types: string[];\n redirect_uris: string[];\n active: boolean;\n};\n\nconst notificationId = 'oauth2clientcreate';\n\nexport default defineComponent({\n name: 'Oauth2AdminApp',\n props: {\n initialClients: {\n type: Array,\n required: true,\n },\n scopes: {\n type: Object,\n required: true,\n },\n },\n components: {\n Field,\n ContentBlock,\n },\n data() {\n const typeOptions = {\n confidential: this.translate('OAuth2_AdminConfidential'),\n public: this.translate('OAuth2_AdminPublic'),\n };\n\n const grantOptions = {\n authorization_code: this.translate('OAuth2_AdminGrantAuthorizationCode'),\n client_credentials: this.translate('OAuth2_AdminGrantClientCredentials'),\n refresh_token: this.translate('OAuth2_AdminGrantRefreshToken'),\n };\n\n return {\n clients: (this.initialClients as Client[]) || [],\n loading: false,\n secret: '',\n confirmDeleteLabel: '',\n confirmRotateLabel: '',\n grant_options: grantOptions,\n type_options: typeOptions,\n form: {\n name: '',\n description: '',\n type: 'confidential',\n grant_types: ['authorization_code', 'client_credentials', 'refresh_token'],\n scope: '',\n redirect_uris: '',\n active: true,\n },\n };\n },\n computed: {\n visibleGrantOptions(): Record {\n if (this.form.type === 'public') {\n const filtered: Record = {};\n if (this.grant_options.authorization_code) {\n filtered.authorization_code = this.grant_options.authorization_code;\n }\n if (this.grant_options.refresh_token) {\n filtered.refresh_token = this.grant_options.refresh_token;\n }\n return filtered;\n }\n\n return this.grant_options;\n },\n },\n watch: {\n 'form.type': 'onFormTypeChange',\n },\n methods: {\n onFormTypeChange(newType: string) {\n if (newType === 'public' && this.form.grant_types.includes('client_credentials')) {\n this.form.grant_types = this.form.grant_types.filter((value: string) => value !== 'client_credentials');\n }\n },\n showSuccessNotification(method: string, message: string) {\n const messageBody = `${message}`;\n const instanceId = NotificationsStore.show({\n id: `OAuth2_${method}`,\n type: 'transient',\n context: 'success',\n message: messageBody,\n });\n\n setTimeout(() => {\n NotificationsStore.scrollToNotification(instanceId);\n });\n },\n async fetchClients() {\n this.loading = true;\n try {\n await AjaxHelper.fetch({\n method: 'OAuth2.getClients',\n filter_limit: '-1',\n }).then((clients) => {\n this.clients = clients;\n });\n } finally {\n this.loading = false;\n }\n },\n async createClient() {\n this.removeAnyClientNotification();\n if (!this.checkRequiredFieldsAreSet()) {\n return;\n }\n this.loading = true;\n this.secret = '';\n const params = {\n method: 'OAuth2.createClient',\n name: this.form.name,\n description: this.form.description,\n type: this.form.type,\n grantTypes: this.form.grant_types,\n scope: this.form.scope,\n redirectUris: this.form.redirect_uris,\n active: 1,\n };\n try {\n await AjaxHelper.fetch(params).then((response) => {\n this.clients.push(response.client);\n\n const message = this.translate('OAuth2_AdminCreated', response.client.client_id);\n this.showSuccessNotification('createClient', message);\n\n if (response.secret) {\n this.secret = response.secret;\n }\n this.resetForm();\n });\n } finally {\n this.loading = false;\n }\n },\n async rotateSecret(client: Client) {\n if (!client) {\n return;\n }\n\n this.confirmRotateLabel = this.translate('OAuth2_AdminRotateConfirm', client?.name || client?.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmRotateClient as HTMLElement, {\n yes: () => {\n this.loading = true;\n try {\n AjaxHelper.fetch({\n method: 'OAuth2.rotateSecret',\n clientId: client.client_id,\n }).then((response) => {\n if (response && response.secret) {\n this.secret = response.secret;\n\n const message = this.translate('OAuth2_AdminRotated', client.client_id);\n this.showSuccessNotification('rotateSecret', message);\n }\n });\n } finally {\n this.loading = false;\n }\n },\n });\n },\n async deleteClient(client: Client) {\n if (!client) {\n return;\n }\n\n this.confirmDeleteLabel = this.translate('OAuth2_AdminDeleteConfirm', client?.name || client?.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmDeleteClient as HTMLElement, {\n yes: () => {\n this.loading = true;\n try {\n AjaxHelper.fetch({\n method: 'OAuth2.deleteClient',\n clientId: client.client_id,\n }).then((response) => {\n if (response.deleted) {\n this.clients = this.clients.filter((c) => c.client_id !== client.client_id);\n\n const message = this.translate('OAuth2_AdminDeleted', client.client_id);\n this.showSuccessNotification('deleteClient', message);\n }\n });\n } finally {\n this.loading = false;\n }\n },\n });\n },\n resetForm() {\n this.form.name = '';\n this.form.description = '';\n this.form.type = 'confidential';\n this.form.grant_types = ['authorization_code', 'client_credentials', 'refresh_token'];\n this.form.scope = '';\n this.form.redirect_uris = '';\n this.form.active = true;\n },\n checkRequiredFieldsAreSet() {\n let response = true;\n let errorMessage = '';\n if (!this.form.name.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminName');\n } else if (!this.form.type.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminType');\n } else if (!this.form.grant_types.length) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminClientGrants');\n } else if (!this.form.scope.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminScope');\n } else if (!this.form.redirect_uris.trim() && this.form.grant_types.includes('authorization_code')) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminRedirectUris');\n }\n if (!response && errorMessage) {\n this.showErrorFieldNotProvidedNotification(errorMessage);\n }\n\n return response;\n },\n removeAnyClientNotification() {\n NotificationsStore.remove(notificationId);\n NotificationsStore.remove('ajaxHelper');\n },\n showNotification(message: string, context: NotificationType['context'],\n type: null|NotificationType['type'] = null) {\n const notificationInstanceId = NotificationsStore.show({\n message,\n context,\n id: notificationId,\n type: type !== null ? type : 'toast',\n });\n setTimeout(() => {\n NotificationsStore.scrollToNotification(notificationInstanceId);\n }, 200);\n },\n showErrorFieldNotProvidedNotification(title: string) {\n const message = this.translate('OAuth2_ErrorXNotProvided', [title]);\n this.showNotification(message, 'error');\n },\n },\n});\n","import { render } from \"./AdminApp.vue?vue&type=template&id=67e0d42a\"\nimport script from \"./AdminApp.vue?vue&type=script&lang=ts\"\nexport * from \"./AdminApp.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://OAuth2/webpack/universalModuleDefinition","webpack://OAuth2/webpack/bootstrap","webpack://OAuth2/external \"CoreHome\"","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?5afb","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?c30b","webpack://OAuth2/external {\"commonjs\":\"vue\",\"commonjs2\":\"vue\",\"root\":\"Vue\"}","webpack://OAuth2/external \"CorePluginsAdmin\"","webpack://OAuth2/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?1486","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/List.vue?93f1","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?ce49","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Edit.vue?3733","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?175b","webpack://OAuth2/./plugins/OAuth2/vue/src/OAuthClients/Manage.vue?084c"],"names":["root","factory","exports","module","require","define","amd","self","this","__WEBPACK_EXTERNAL_MODULE__19dc__","__WEBPACK_EXTERNAL_MODULE__8bbf__","__WEBPACK_EXTERNAL_MODULE_a5a2__","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","window","currentScript","document","src","match","class","isEditMode","client-id","editedClientId","scopes","initial-secret","secret","showList","onClientSaved","clients","createClient","editClient","onClientDeleted","onClientUpdated","ref","style","confirmDeleteLabel","role","type","translate","confirmToggleLabel","content-title","feature","length","client","client_id","title","$sanitize","description","typeOptions","grant_types","join","active","redirect_uris","uri","created_at","toggleClientStatus","$emit","deleteClient","notificationId","props","Array","required","emits","components","ContentBlock","directives","ContentTable","confidential","public","methods","message","context","instanceId","show","id","setTimeout","scrollToNotification","remove","helper","modalConfirm","$refs","confirmToggleClient","yes","fetch","method","clientId","then","response","removeNotifications","showNotification","confirmDeleteClient","deleted","render","__scopeId","confirmRotateLabel","contentTitle","loading","submit","uicontrol","form","inline-help","rows","ui-control-attributes","placeholder","model-value","disabled","showSecretPanel","canRegenerateSecret","rotateSecret","visibleSecret","displayedSecret","secretInlineHelp","options","visibleGrantOptions","var-type","scope","submitLabel","getDefaultForm","firstScope","keys","String","initialSecret","default","CopyToClipboard","Field","grantOptions","authorization_code","client_credentials","refresh_token","init","watch","newSecret","computed","filtered","finally","newType","includes","filter","confirmRotateClient","checkRequiredFieldsAreSet","params","trim","grantTypes","redirectUris","clientMessage","secretMessage","Boolean","updateHash","hashParsed","idClient","errorMessage","showErrorFieldNotProvidedNotification","notificationInstanceId","initialClients","Oauth2ClientList","Oauth2ClientEdit","secretClientId","initState","payload","index","findIndex","push","splice","sort","left","right","leftTime","updated_at","Date","getTime","rightTime","localeCompare","updatedClient"],"mappings":"CAAA,SAA2CA,EAAMC,GAC1B,kBAAZC,SAA0C,kBAAXC,OACxCA,OAAOD,QAAUD,EAAQG,QAAQ,YAAaA,QAAQ,OAAQA,QAAQ,qBAC7C,oBAAXC,QAAyBA,OAAOC,IAC9CD,OAAO,CAAC,WAAY,CAAE,oBAAqBJ,GACjB,kBAAZC,QACdA,QAAQ,UAAYD,EAAQG,QAAQ,YAAaA,QAAQ,OAAQA,QAAQ,qBAEzEJ,EAAK,UAAYC,EAAQD,EAAK,YAAaA,EAAK,OAAQA,EAAK,sBAR/D,CASoB,qBAATO,KAAuBA,KAAOC,MAAO,SAASC,EAAmCC,EAAmCC,GAC/H,O,YCTE,IAAIC,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUZ,QAGnC,IAAIC,EAASS,EAAiBE,GAAY,CACzCC,EAAGD,EACHE,GAAG,EACHd,QAAS,IAUV,OANAe,EAAQH,GAAUI,KAAKf,EAAOD,QAASC,EAAQA,EAAOD,QAASW,GAG/DV,EAAOa,GAAI,EAGJb,EAAOD,QA0Df,OArDAW,EAAoBM,EAAIF,EAGxBJ,EAAoBO,EAAIR,EAGxBC,EAAoBQ,EAAI,SAASnB,EAASoB,EAAMC,GAC3CV,EAAoBW,EAAEtB,EAASoB,IAClCG,OAAOC,eAAexB,EAASoB,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEV,EAAoBgB,EAAI,SAAS3B,GACX,qBAAX4B,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAexB,EAAS4B,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAexB,EAAS,aAAc,CAAE8B,OAAO,KAQvDnB,EAAoBoB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQnB,EAAoBmB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,kBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFAxB,EAAoBgB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOnB,EAAoBQ,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRvB,EAAoB2B,EAAI,SAASrC,GAChC,IAAIoB,EAASpB,GAAUA,EAAOgC,WAC7B,WAAwB,OAAOhC,EAAO,YACtC,WAA8B,OAAOA,GAEtC,OADAU,EAAoBQ,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRV,EAAoBW,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG7B,EAAoBgC,EAAI,2BAIjBhC,EAAoBA,EAAoBiC,EAAI,Q,uBClFrD3C,EAAOD,QAAUO,G,kCCAjB,W,kCCAA,W,qBCAAN,EAAOD,QAAUQ,G,mBCAjBP,EAAOD,QAAUS,G,gFCEjB,G,uDAAsB,qBAAXoC,OAAwB,CACjC,IAAIC,EAAgBD,OAAOE,SAASD,cAWhCE,EAAMF,GAAiBA,EAAcE,IAAIC,MAAM,2BAC/CD,IACF,IAA0BA,EAAI,IAKnB,I,qBCpBRE,MAAM,gB,sKAAX,gCAiBM,MAjBN,EAiBM,CAfK,EAAAC,Y,yBAOT,yBAOE,G,MALCC,YAAW,EAAAC,eACXC,OAAQ,EAAAA,OACRC,iBAAgB,EAAAC,OAChB,SAAQ,EAAAC,SACR,QAAO,EAAAC,e,gGAdV,yBAOE,G,MALCC,QAAS,EAAAA,QACT,SAAQ,EAAAC,aACR,OAAM,EAAAC,WACN,UAAS,EAAAC,gBACT,UAAS,EAAAC,iB,iLCPTb,MAAM,kC,GAEPA,MAAM,aACNc,IAAI,uB,2BAeJd,MAAM,aACNc,IAAI,uB,qCAgCMC,MAAA,iB,eAuBIf,MAAM,kB,GAOJA,MAAM,gB,GAGZA,MAAM,c,+EA4BXA,MAAM,kB,QAIR,gCAAyB,QAAnBA,MAAM,YAAU,U,+JApH7B,gCAuHM,MAvHN,EAuHM,CAtHJ,gCAeM,MAfN,EAeM,CAXJ,gCAAkC,uCAA3B,EAAAgB,oBAAkB,GACzB,gCAIE,SAHAC,KAAK,MACLC,KAAK,SACJtC,MAAO,EAAAuC,UAAU,gB,UAEpB,gCAIE,SAHAF,KAAK,KACLC,KAAK,SACJtC,MAAO,EAAAuC,UAAU,e,gBAGtB,gCAeM,MAfN,EAeM,CAXJ,gCAAkC,uCAA3B,EAAAC,oBAAkB,GACzB,gCAIE,SAHAH,KAAK,MACLC,KAAK,SACJtC,MAAO,EAAAuC,UAAU,gB,UAEpB,gCAIE,SAHAF,KAAK,KACLC,KAAK,SACJtC,MAAO,EAAAuC,UAAU,e,gBAGtB,yBAqFe,GApFZE,gBAAe,EAAAF,UAAU,uBACzBG,QAAS,EAAAH,UAAU,wB,8BAEpB,IAAyD,CAAzD,gCAAyD,sCAAnD,EAAAA,UAAU,oCAAD,GAGP,EAAAV,QAAQc,O,sDAFhB,gCAsEQ,WAlEN,gCAWQ,cAVN,gCASK,WARH,gCAA4C,uCAArC,EAAAJ,UAAU,qBAAD,GAChB,gCAAkD,uCAA3C,EAAAA,UAAU,2BAAD,GAChB,gCAAoD,uCAA7C,EAAAA,UAAU,6BAAD,GAChB,gCAAoD,uCAA7C,EAAAA,UAAU,6BAAD,GAChB,gCAAgD,uCAAzC,EAAAA,UAAU,yBAAD,GAChB,gCAAuD,uCAAhD,EAAAA,UAAU,gCAAD,GAChB,gCAAuD,uCAAhD,EAAAA,UAAU,gCAAD,GAChB,gCAA2E,KAA3E,EAA2E,6BAA9C,EAAAA,UAAU,8BAAD,OAG1C,gCAqDQ,e,2BApDN,gCAmDK,2CAlDc,EAAAV,QAAVe,I,yBADT,gCAmDK,MAjDFtC,IAAKsC,EAAOC,W,CAEb,gCAEK,MAFAC,MAAO,EAAAC,UAAUH,EAAOI,c,6BACxBJ,EAAOtD,MAAI,KAEhB,gCAAuC,uCAAhC,EAAA2D,YAAYL,EAAON,OAAI,GAC9B,gCAAoD,wCAA5CM,EAAOM,aAAe,IAAIC,KAAK,OAAD,GACtC,gCAQK,WAPH,gCAMO,yCAJHP,EAAOQ,OAA6B,YAAS,sBAA6C,YAAS,8BAMzG,gCAEK,WADH,gCAA0D,OAA1D,EAA0D,6BAA1BR,EAAOC,WAAS,KAElD,gCAOK,Y,2BANH,gCAKM,2CAJWD,EAAOS,eAAiB,GAAhCC,I,yBADT,gCAKM,OAHHhD,IAAKgD,GAAG,CAET,gCAA2C,OAA3C,EAA2C,6BAAbA,GAAG,O,QAGrC,gCAAmD,KAAnD,EAAmD,6BAAzBV,EAAOW,YAAU,GAC3C,gCAoBK,WAnBH,gCAQE,UAPCnC,MAAK,6CAAkBwB,EAAOQ,OAAS,aAAe,cACtD,QAAK,8BAAU,EAAAI,mBAAmBZ,GAAM,aACxCE,MAA0B,EAAO,OAA6B,YAAS,qBAA4C,YAAS,uB,WAM/H,gCAIE,UAHA1B,MAAM,yBACL,QAAK,8BAAU,EAAAqC,MAAM,OAAQb,EAAOC,WAAS,aAC7CC,MAAO,EAAAP,UAAU,qB,UAEpB,gCAIE,UAHAnB,MAAM,2BACL,QAAK,8BAAU,EAAAsC,aAAad,GAAM,aAClCE,MAAO,EAAAP,UAAU,uB,4DAM5B,gCAEM,qCADD,EAAAA,UAAU,0BAAD,IAEd,gCAKM,MALN,EAKM,CAJJ,gCAGyE,KAFvEnB,MAAM,kBACL,QAAK,0CAAU,EAAAqC,MAAM,UAAD,e,CACtB,E,6BAAyB,IAAC,6BAAG,EAAAlB,UAAU,4BAAD,S,sCCzG/C,MAAMoB,EAAiB,mBAER,mCAAgB,CAC7BrE,KAAM,mBACNsE,MAAO,CACL/B,QAAS,CACPS,KAAMuB,MACNC,UAAU,IAGdC,MAAO,CAAC,SAAU,OAAQ,UAAW,WACrCC,WAAY,CACVC,aAAA,mBAEFC,WAAY,CACVC,aAAA,mBAEF,OACE,MAAO,CACL/B,mBAAoB,GACpBI,mBAAoB,GACpBS,YAAa,CACXmB,aAAc5F,KAAK+D,UAAU,4BAC7B8B,OAAQ7F,KAAK+D,UAAU,yBAI7B+B,QAAS,CACP,iBAAiBC,EAAiBC,EAChClC,EAAsC,MACtC,MAAMmC,EAAa,wBAAmBC,KAAK,CACzCH,UACAC,UACAG,GAAIhB,EACJrB,KAAe,OAATA,EAAgBA,EAAO,UAG/BsC,WAAW,KACT,wBAAmBC,qBAAqBJ,IACvC,MAEL,sBACE,wBAAmBK,OAAOnB,GAC1B,wBAAmBmB,OAAO,eAE5B,mBAAmBlC,GACjBpE,KAAKgE,mBAAqBI,EAAOQ,OAC7B5E,KAAK+D,UAAU,2BAA4BK,EAAOtD,MAAQsD,EAAOC,WACjErE,KAAK+D,UAAU,4BAA6BK,EAAOtD,MAAQsD,EAAOC,WAEtE,YAAOkC,OAAOC,aAAaxG,KAAKyG,MAAMC,oBAAoC,CACxEC,IAAK,KACH,gBAAWC,MAAM,CACfC,OAAQ,yBACRC,SAAU1C,EAAOC,UACjBO,OAAQR,EAAOQ,OAAS,IAAM,MAC7BmC,KAAMC,IACK,OAARA,QAAQ,IAARA,KAAU5C,SACZpE,KAAKiH,sBACLjH,KAAKkH,iBACHF,EAAS5C,OAAOQ,OACZ5E,KAAK+D,UAAU,sBAAuBiD,EAAS5C,OAAOtD,MAAQkG,EAAS5C,OAAOC,WAC9ErE,KAAK+D,UAAU,qBAAsBiD,EAAS5C,OAAOtD,MAAQkG,EAAS5C,OAAOC,WACjF,WAEFrE,KAAKiF,MAAM,UAAW+B,EAAS5C,eAMzC,aAAaA,GACXpE,KAAK4D,mBAAqB5D,KAAK+D,UAAU,4BAA6BK,EAAOtD,MAAQsD,EAAOC,WAE5F,YAAOkC,OAAOC,aAAaxG,KAAKyG,MAAMU,oBAAoC,CACxER,IAAK,KACH,gBAAWC,MAAM,CACfC,OAAQ,sBACRC,SAAU1C,EAAOC,YAChB0C,KAAMC,IACK,OAARA,QAAQ,IAARA,KAAUI,UACZpH,KAAKiH,sBACLjH,KAAKkH,iBAAiBlH,KAAK+D,UAAU,sBAAuBK,EAAOtD,MAAO,WAC1Ed,KAAKiF,MAAM,UAAWb,EAAOC,qB,UC1F3C,EAAOgD,OAAS,EAChB,EAAOC,UAAY,kBAEJ,Q,8FCPR1E,MAAM,kC,GAEPA,MAAM,aACNc,IAAI,uB,qCAkBId,MAAM,gB,QAAe,gCAAsD,OAAjDF,IAAI,4CAA0C,U,GAOzEE,MAAM,O,GASNA,MAAM,O,SAaPA,MAAM,O,SAaRA,MAAM,0B,GAECA,MAAM,W,SAYbA,MAAM,sD,GAEDA,MAAM,c,GACJA,MAAM,2B,SAIPA,MAAM,sB,SAINA,MAAM,sB,GAIPA,MAAM,c,mBAIRA,MAAM,MAAM9B,KAAK,Q,IAsBpB8B,MAAM,MACN9B,KAAK,a,IAaL8B,MAAM,MACN9B,KAAK,U,IAWF8B,MAAM,O,IAUNA,MAAM,O,oBASNA,MAAM,gB,6MAnKjB,gCAwKM,MAxKN,EAwKM,CAvKJ,gCAeM,MAfN,EAeM,CAXJ,gCAAkC,uCAA3B,EAAA2E,oBAAkB,GACzB,gCAIE,SAHA1D,KAAK,MACLC,KAAK,SACJtC,MAAO,EAAAuC,UAAU,gB,UAEpB,gCAIE,SAHAF,KAAK,KACLC,KAAK,SACJtC,MAAO,EAAAuC,UAAU,e,gBAGtB,yBAsJe,GArJZE,gBAAe,EAAAuD,cAAY,C,6BAE5B,IAGI,CAHK,EAAAC,S,yBAAT,gCAGI,OAFF,gCAC+C,OAD/C,EAC+C,CADpB,E,6BAAsD,IAC/E,6BAAG,EAAA1D,UAAU,wBAAD,S,yBAEhB,gCA8IO,Q,MA5IJ,SAAM,+CAAU,EAAA2D,QAAA,EAAAA,UAAA,GAAM,e,CAEvB,gCAQM,MARN,EAQM,CAPJ,yBAME,GALEC,UAAU,OACV7G,KAAK,O,WACI,EAAA8G,KAAK9G,K,qCAAL,EAAA8G,KAAK9G,KAAI,GACjB+G,cAAa,EAAA9D,UAAU,wBACvBO,MAAO,EAAAP,UAAU,qB,+CAGxB,gCAWM,MAXN,EAWM,CAVJ,yBASE,GARE4D,UAAU,WACV7G,KAAK,c,WACI,EAAA8G,KAAKpD,Y,qCAAL,EAAAoD,KAAKpD,YAAW,GACxBsD,KAAM,EACNC,wBAAuB,4BACvBF,cAAa,EAAA9D,UAAU,+BACvBO,MAAO,EAAAP,UAAU,2BACjBiE,YAAa,EAAAjE,UAAU,uC,6DAKpB,EAAAlB,Y,yBAFV,gCAWM,MAXN,EAWM,CAPJ,yBAME,GALE8E,UAAU,OACV7G,KAAK,YACJmH,cAAa,EAAAnB,SACbxC,MAAO,EAAAP,UAAU,wBACjBmE,UAAU,G,0EAIT,EAAAC,iB,yBADR,gCAaM,MAbN,EAaM,CATJ,gCAQQ,QARR,EAQQ,C,0DAPH,EAAApE,UAAU,wBAAyB,IACtC,GACQ,EAAAqE,qB,yBADR,gCAKI,K,MAHD,QAAK,+CAAU,EAAAC,cAAA,EAAAA,gBAAA,GAAY,eAC7B,KACE,6BAAG,EAAAtE,UAAU,6BAA8B,KAC9C,I,mFAII,EAAAoE,iB,yBADR,gCAoBM,MApBN,EAoBM,CAhBJ,gCAYM,MAZN,EAYM,CAXJ,gCAUM,MAVN,EAUM,CARI,EAAAG,c,sDADR,gCAI4B,MAJ5B,EAI4B,C,0DAAxB,EAAAC,iBAAe,M,IAFI,O,yBAGvB,gCAG4B,MAH5B,EAG4B,6BAAxB,EAAAA,iBAAe,QAGvB,gCAEM,MAFN,EAEM,CADJ,gCAA8D,OAAzD3F,MAAM,YAAY,UAAQ,EAAA2B,UAAU,EAAAiE,mB,sDAG7C,gCAoBM,MApBN,EAoBM,CAnBa,EAAA3F,Y,yBAWf,yBAME,G,MALA8E,UAAU,OACV7G,KAAK,OACJmH,cAAa,EAAAxD,YAAY,EAAAmD,KAAK9D,OAAS,EAAA8D,KAAK9D,KAC5CQ,MAAO,EAAAP,UAAU,oBACjBmE,UAAU,G,2DAfb,yBAOE,G,MANAP,UAAU,SACV7G,KAAK,O,WACI,EAAA8G,KAAK9D,K,qCAAL,EAAA8D,KAAK9D,KAAI,GACjBQ,MAAO,EAAAP,UAAU,oBACjB8D,cAAa,EAAA9D,UAAU,uBAAwB,WAAY,aAC3D0E,QAAS,EAAAhE,a,0DAahB,gCAaM,MAbN,GAaM,CATJ,yBAQE,GAPAkD,UAAU,WACTc,QAAS,EAAAC,oBACVC,WAAS,QACT7H,KAAK,c,WACI,EAAA8G,KAAKlD,Y,qCAAL,EAAAkD,KAAKlD,YAAW,GACxBmD,cAAa,EAAA9D,UAAU,8BACvBO,MAAO,EAAAP,UAAU,6B,yDAGtB,gCAYM,MAZN,GAYM,CARJ,yBAOE,GANA4D,UAAU,SACTc,QAAS,EAAAzF,OACVlC,KAAK,S,WACI,EAAA8G,KAAKgB,M,qCAAL,EAAAhB,KAAKgB,MAAK,GAClBf,cAAa,EAAA9D,UAAU,wBAAyB,WAAY,aAC5DO,MAAO,EAAAP,UAAU,sB,yDAGtB,gCASM,MATN,GASM,CARJ,yBAOE,GANA4D,UAAU,WACV7G,KAAK,gB,WACI,EAAA8G,KAAK/C,c,qCAAL,EAAA+C,KAAK/C,cAAa,GAC3BmD,YAAY,+BACXH,cAAa,EAAA9D,UAAU,gCACvBO,MAAO,EAAAP,UAAU,6B,+CAGtB,gCAQM,MARN,GAQM,CAPJ,gCAMS,UALPD,KAAK,SACLlB,MAAM,MACLsF,SAAU,EAAAT,S,6BAER,EAAAoB,aAAW,QAGlB,gCAEM,MAFN,GAEM,CADJ,gCAAyE,KAArE,QAAK,0CAAU,EAAA5D,MAAM,UAAD,e,6BAAe,EAAAlB,UAAU,mBAAD,M,oDCvJ1D,MAAM,GAAiB,mBAEvB,SAAS+E,GAAe9F,GACtB,MAAM+F,EAAa9H,OAAO+H,KAAKhG,GAAU,IAAI,IAAM,GAEnD,MAAO,CACLlC,KAAM,GACN0D,YAAa,GACbV,KAAM,eACNY,YAAa,CAAC,qBAAsB,qBAAsB,iBAC1DkE,MAAOG,EACPlE,cAAe,GACfD,QAAQ,GAIG,oCAAgB,CAC7B9D,KAAM,mBACNsE,MAAO,CACL0B,SAAU,CACRhD,KAAMmF,OACN3D,UAAU,GAEZ4D,cAAe,CACbpF,KAAMmF,OACNE,QAAS,IAEXnG,OAAQ,CACNc,KAAM7C,OACNqE,UAAU,IAGdI,WAAY,CACV0D,gBAAA,sBAEF7D,MAAO,CAAC,SAAU,SAClBC,WAAY,CACVC,aAAA,kBACA4D,MAAA,aAEF,OACE,MAAM5E,EAAc,CAClBmB,aAAc5F,KAAK+D,UAAU,4BAC7B8B,OAAQ7F,KAAK+D,UAAU,uBAGnBuF,EAAe,CACnBC,mBAAoBvJ,KAAK+D,UAAU,sCACnCyF,mBAAoBxJ,KAAK+D,UAAU,sCACnC0F,cAAezJ,KAAK+D,UAAU,kCAGhC,MAAO,CACL0D,SAAS,EACTF,mBAAoB,GACpB9C,cACA6E,eACA1B,KAAMkB,GAAe9I,KAAKgD,QAC1BsF,cAAetI,KAAKkJ,gBAGxB,UACElJ,KAAK0J,QAEPC,MAAO,CACL,WACE3J,KAAK0J,QAEP,cAAcE,GACZ5J,KAAKsI,cAAgBsB,GAEvB,YAAa,oBAEfC,SAAU,CACR,aACE,MAAyB,MAAlB7J,KAAK8G,UAEd,eACE,OAAO9G,KAAK6C,WACR7C,KAAK+D,UAAU,yBACf/D,KAAK+D,UAAU,4BAErB,cACE,OAAO/D,KAAK6C,WACR7C,KAAK+D,UAAU,sBACf/D,KAAK+D,UAAU,qBAErB,sBACE,GAAuB,WAAnB/D,KAAK4H,KAAK9D,KAAmB,CAC/B,MAAMgG,EAAmC,GAOzC,OANI9J,KAAKsJ,aAAaC,qBACpBO,EAASP,mBAAqBvJ,KAAKsJ,aAAaC,oBAE9CvJ,KAAKsJ,aAAaG,gBACpBK,EAASL,cAAgBzJ,KAAKsJ,aAAaG,eAEtCK,EAGT,OAAO9J,KAAKsJ,cAEd,kBACE,MAA0B,iBAAnBtJ,KAAK4H,KAAK9D,OAA4B9D,KAAK6C,cAAgB7C,KAAKsI,gBAEzE,sBACE,OAAOtI,KAAK6C,YAAiC,iBAAnB7C,KAAK4H,KAAK9D,MAEtC,kBACE,OAAO9D,KAAKsI,eAAiB,iBAE/B,mBACE,OAAItI,KAAKsI,cACAtI,KAAK+D,UAAU,kCAGjB/D,KAAK+D,UAAU,mCAG1B+B,QAAS,CACP,OACE9F,KAAKiH,sBACLjH,KAAK4H,KAAOkB,GAAe9I,KAAKgD,QAChChD,KAAKsI,cAAgBtI,KAAKkJ,cAErBlJ,KAAK6C,aAIV7C,KAAKyH,SAAU,EACf,gBAAWb,MAAc,CACvBC,OAAQ,mBACRC,SAAU9G,KAAK8G,WACdC,KAAM3C,IACPpE,KAAK4H,KAAO,CACV9G,KAAMsD,EAAOtD,MAAQ,GACrB0D,YAAaJ,EAAOI,aAAe,GACnCV,KAAMM,EAAON,MAAQ,eACrBY,YAAaN,EAAOM,aAAe,GACnCkE,MAAQxE,EAAOpB,QAAUoB,EAAOpB,OAAO,IAAO/B,OAAO+H,KAAKhJ,KAAKgD,QAAU,IAAI,IAAM,GACnF6B,eAAgBT,EAAOS,eAAiB,IAAIF,KAAK,MACjDC,SAAUR,EAAOQ,UAElBmF,QAAQ,KACT/J,KAAKyH,SAAU,MAGnB,iBAAiBuC,GACC,WAAZA,GAAwBhK,KAAK4H,KAAKlD,YAAYuF,SAAS,wBACzDjK,KAAK4H,KAAKlD,YAAc1E,KAAK4H,KAAKlD,YAAYwF,OAAQ1I,GAA4B,uBAAVA,IAG1D,WAAZwI,IACFhK,KAAKsI,cAAgB,KAGzB,eACOtI,KAAKoI,sBAIVpI,KAAKuH,mBAAqBvH,KAAK+D,UAAU,4BAA6B/D,KAAK4H,KAAK9G,MAAQd,KAAK8G,UAC7F,YAAOP,OAAOC,aAAaxG,KAAKyG,MAAM0D,oBAAoC,CACxExD,IAAK,KACH3G,KAAKyH,SAAU,EACf,gBAAWb,MAAM,CACfC,OAAQ,sBACRC,SAAU9G,KAAK8G,WACdC,KAAMC,IACK,OAARA,QAAQ,IAARA,KAAU9D,SACZlD,KAAKsI,cAAgBtB,EAAS9D,UAE/B6G,QAAQ,KACT/J,KAAKyH,SAAU,SAKvB,SAEE,GADAzH,KAAKiH,uBACAjH,KAAKoK,4BACR,OAGFpK,KAAKyH,SAAU,EACf,MAAM4C,EAAS,CACbxD,OAAQ7G,KAAK6C,WAAa,sBAAwB,sBAClD/B,KAAMd,KAAK4H,KAAK9G,KAAKwJ,OACrB9F,YAAaxE,KAAK4H,KAAKpD,YACvBV,KAAM9D,KAAK4H,KAAK9D,KAChByG,WAAYvK,KAAK4H,KAAKlD,YACtBkE,MAAO5I,KAAK4H,KAAKgB,MACjB4B,aAAcxK,KAAK4H,KAAK/C,cACxBD,OAAQ5E,KAAK4H,KAAKhD,OAAS,IAAM,KAG/B5E,KAAK6C,aACPwH,EAAOvD,SAAW9G,KAAK8G,UAGzB,gBAAWF,MAAMyD,GAAQtD,KAAMC,IAC7BhH,KAAKsI,cAAgBtB,EAAS9D,QAAU,GACxC,MAAMuH,EAAgBzK,KAAK6C,WACvB7C,KAAK+D,UAAU,sBAAuBiD,EAAS5C,OAAOtD,MACtDd,KAAK+D,UAAU,sBAAuBiD,EAAS5C,OAAOtD,MACpD4J,EAAgB1D,EAAS9D,OAC3BlD,KAAK+D,UAAU,2BACf,GACEgC,EAAU,CAAC0E,EAAeC,GAAeR,OAAOS,SAAShG,KAAK,KAEpE3E,KAAKiF,MAAM,QAAS,CAClBb,OAAQ4C,EAAS5C,OACjBlB,OAAQ8D,EAAS9D,QAAU,OAG7B,eAAU0H,WAAW,OAAD,wBACf,eAAUC,WAAWrJ,OAAK,IAC7BsJ,SAAU9D,EAAS5C,OAAOC,aAG5B+B,WAAW,KACTpG,KAAKkH,iBAAiB,qCAAqCnB,WAAkB,UAAW,cACvF,MACFgE,QAAQ,KACT/J,KAAKyH,SAAU,KAGnB,4BACE,IAAIT,GAAW,EACX+D,EAAe,GAsBnB,OArBK/K,KAAK4H,KAAK9G,KAAKwJ,OAGRtK,KAAK4H,KAAK9D,KAAKwG,OAGftK,KAAK4H,KAAKlD,YAAYP,OAGtBnE,KAAK4H,KAAKgB,MAAM0B,QAGhBtK,KAAK4H,KAAK/C,cAAcyF,QAAUtK,KAAK4H,KAAKlD,YAAYuF,SAAS,wBAC3EjD,GAAW,EACX+D,EAAe/K,KAAK+D,UAAU,8BAJ9BiD,GAAW,EACX+D,EAAe/K,KAAK+D,UAAU,uBAJ9BiD,GAAW,EACX+D,EAAe/K,KAAK+D,UAAU,8BAJ9BiD,GAAW,EACX+D,EAAe/K,KAAK+D,UAAU,sBAJ9BiD,GAAW,EACX+D,EAAe/K,KAAK+D,UAAU,sBAe3BiD,GAAY+D,GACf/K,KAAKgL,sCAAsCD,GAGtC/D,GAET,sBACE,wBAAmBV,OAAO,IAC1B,wBAAmBA,OAAO,eAE5B,iBAAiBP,EAAiBC,EAChClC,EAAsC,MACtC,MAAMmH,EAAyB,wBAAmB/E,KAAK,CACrDH,UACAC,UACAG,GAAI,GACJrC,KAAe,OAATA,EAAgBA,EAAO,UAE/BsC,WAAW,KACT,wBAAmBC,qBAAqB4E,IACvC,MAEL,sCAAsC3G,GACpC,MAAMyB,EAAU/F,KAAK+D,UAAU,2BAA4B,CAACO,IAC5DtE,KAAKkH,iBAAiBnB,EAAS,a,UCvRrC,GAAOsB,OAAS,GAChB,GAAOC,UAAY,kBAEJ,UCDA,gCAAgB,CAC7BxG,KAAM,iBACNsE,MAAO,CACL8F,eAAgB,CACdpH,KAAMuB,MACNC,UAAU,GAEZtC,OAAQ,CACNc,KAAM7C,OACNqE,UAAU,IAGdE,WAAY,CACV2F,iBAAA,EACAC,iBAAA,IAEF,OACE,MAAO,CACL/H,QAASrD,KAAKkL,gBAA8B,GAC5ChI,OAAQ,GACRmI,eAAgB,GAChBtI,eAAgB,KAGpB,UACE,mBAAM,IAAM,eAAU8H,WAAWrJ,MAAMsJ,SAAqBA,IAC1D9K,KAAKsL,UAAUR,KAGjB9K,KAAKsL,UAAU,eAAUT,WAAWrJ,MAAMsJ,WAE5ChF,QAAS,CACP,UAAUgF,GACHA,EAGM9K,KAAKqL,gBAAkBrL,KAAKqL,iBAAmBP,IACxD9K,KAAKkD,OAAS,GACdlD,KAAKqL,eAAiB,KAJtBrL,KAAKkD,OAAS,GACdlD,KAAKqL,eAAiB,IAMxBrL,KAAK+C,eAAiB+H,GAAY,IAEpC,eACE,eAAUF,WAAW,OAAD,wBACf,eAAUC,WAAWrJ,OAAK,IAC7BsJ,SAAU,OAEZ9K,KAAKkD,OAAS,GACdlD,KAAKqL,eAAiB,IAExB,WAAWvE,GACL9G,KAAKqL,iBAAmBvE,IAC1B9G,KAAKkD,OAAS,GACdlD,KAAKqL,eAAiB,IAGxB,eAAUT,WAAW,OAAD,wBACf,eAAUC,WAAWrJ,OAAK,IAC7BsJ,SAAUhE,MAGd,WACE,MAAMuD,EAAS,OAAH,UACP,eAAUQ,WAAWrJ,cAEnB6I,EAAOS,SACd9K,KAAKkD,OAAS,GACdlD,KAAKqL,eAAiB,GACtB,eAAUT,WAAWP,IAEvB,cAAckB,GACZ,MAAMC,EAAQxL,KAAKqD,QAAQoI,UACxBrH,GAAWA,EAAOC,YAAckH,EAAQnH,OAAOC,YAEnC,IAAXmH,EACFxL,KAAKqD,QAAQqI,KAAKH,EAAQnH,QAE1BpE,KAAKqD,QAAQsI,OAAOH,EAAO,EAAGD,EAAQnH,QAGxCpE,KAAKqD,QAAU,IAAIrD,KAAKqD,SAASuI,KAAK,CAACC,EAAMC,KAC3C,MAAMC,EAAWF,EAAKG,WAAa,IAAIC,KAAKJ,EAAKG,YAAYE,UAAY,EACnEC,EAAYL,EAAME,WAAa,IAAIC,KAAKH,EAAME,YAAYE,UAAY,EAE5E,OAAIC,IAAcJ,EACTI,EAAYJ,EAGdF,EAAK/K,KAAKsL,cAAcN,EAAMhL,QAEvCd,KAAKkD,OAASqI,EAAQrI,QAAU,GAChClD,KAAKqL,eAAiBE,EAAQrI,OAASqI,EAAQnH,OAAOC,UAAY,IAEpE,gBAAgByC,GACd9G,KAAKkD,OAAS,GACVlD,KAAKqL,iBAAmBvE,IAC1B9G,KAAKqL,eAAiB,IAExBrL,KAAKqD,QAAUrD,KAAKqD,QAAQ6G,OAAQ9F,GAAWA,EAAOC,YAAcyC,IAEtE,gBAAgBuF,GACd,MAAMb,EAAQxL,KAAKqD,QAAQoI,UACxBrH,GAAWA,EAAOC,YAAcgI,EAAchI,YAElC,IAAXmH,IAIJxL,KAAKqD,QAAQsI,OAAOH,EAAO,EAAGa,GAC9BrM,KAAKqD,QAAU,IAAIrD,KAAKqD,YAG5BwG,SAAU,CACR,aACE,QAAS7J,KAAK+C,mBCvHpB,GAAOsE,OAASA,EAED","file":"OAuth2.umd.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"CoreHome\", , \"CorePluginsAdmin\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"OAuth2\"] = factory(require(\"CoreHome\"), require(\"vue\"), require(\"CorePluginsAdmin\"));\n\telse\n\t\troot[\"OAuth2\"] = factory(root[\"CoreHome\"], root[\"Vue\"], root[\"CorePluginsAdmin\"]);\n})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"plugins/OAuth2/vue/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fae3\");\n","module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;","export * from \"-!../../../../../node_modules/@vue/cli-service/node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./List.vue?vue&type=style&index=0&id=9cba7004&scoped=true&lang=css\"","export * from \"-!../../../../../node_modules/@vue/cli-service/node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--1-1!./Edit.vue?vue&type=style&index=0&id=15c605de&scoped=true&lang=css\"","module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;","module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","\n\n\n","\n\n\n\n\n","\nimport { defineComponent, PropType } from 'vue';\nimport {\n AjaxHelper,\n ContentBlock,\n ContentTable,\n Matomo,\n NotificationType,\n NotificationsStore,\n} from 'CoreHome';\nimport { Client } from '../types';\n\nconst notificationId = 'oauth2clientlist';\n\nexport default defineComponent({\n name: 'Oauth2ClientList',\n props: {\n clients: {\n type: Array as PropType,\n required: true,\n },\n },\n emits: ['create', 'edit', 'deleted', 'updated'],\n components: {\n ContentBlock,\n },\n directives: {\n ContentTable,\n },\n data() {\n return {\n confirmDeleteLabel: '',\n confirmToggleLabel: '',\n typeOptions: {\n confidential: this.translate('OAuth2_AdminConfidential'),\n public: this.translate('OAuth2_AdminPublic'),\n } as Record,\n };\n },\n methods: {\n showNotification(message: string, context: NotificationType['context'],\n type: null|NotificationType['type'] = null) {\n const instanceId = NotificationsStore.show({\n message,\n context,\n id: notificationId,\n type: type !== null ? type : 'toast',\n });\n\n setTimeout(() => {\n NotificationsStore.scrollToNotification(instanceId);\n }, 200);\n },\n removeNotifications() {\n NotificationsStore.remove(notificationId);\n NotificationsStore.remove('ajaxHelper');\n },\n toggleClientStatus(client: Client) {\n this.confirmToggleLabel = client.active\n ? this.translate('OAuth2_AdminPauseConfirm', client.name || client.client_id)\n : this.translate('OAuth2_AdminResumeConfirm', client.name || client.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmToggleClient as HTMLElement, {\n yes: () => {\n AjaxHelper.fetch({\n method: 'OAuth2.setClientActive',\n clientId: client.client_id,\n active: client.active ? '0' : '1',\n }).then((response) => {\n if (response?.client) {\n this.removeNotifications();\n this.showNotification(\n response.client.active\n ? this.translate('OAuth2_AdminResumed', response.client.name || response.client.client_id)\n : this.translate('OAuth2_AdminPaused', response.client.name || response.client.client_id),\n 'success',\n );\n this.$emit('updated', response.client);\n }\n });\n },\n });\n },\n deleteClient(client: Client) {\n this.confirmDeleteLabel = this.translate('OAuth2_AdminDeleteConfirm', client.name || client.client_id);\n\n Matomo.helper.modalConfirm(this.$refs.confirmDeleteClient as HTMLElement, {\n yes: () => {\n AjaxHelper.fetch({\n method: 'OAuth2.deleteClient',\n clientId: client.client_id,\n }).then((response) => {\n if (response?.deleted) {\n this.removeNotifications();\n this.showNotification(this.translate('OAuth2_AdminDeleted', client.name), 'success');\n this.$emit('deleted', client.client_id);\n }\n });\n },\n });\n },\n },\n});\n","import { render } from \"./List.vue?vue&type=template&id=9cba7004&scoped=true\"\nimport script from \"./List.vue?vue&type=script&lang=ts\"\nexport * from \"./List.vue?vue&type=script&lang=ts\"\n\nimport \"./List.vue?vue&type=style&index=0&id=9cba7004&scoped=true&lang=css\"\nscript.render = render\nscript.__scopeId = \"data-v-9cba7004\"\n\nexport default script","\n\n\n\n\n","\nimport { defineComponent, PropType } from 'vue';\nimport {\n AjaxHelper,\n ContentBlock,\n MatomoUrl,\n Matomo,\n NotificationType,\n NotificationsStore,\n CopyToClipboard,\n} from 'CoreHome';\nimport { Field } from 'CorePluginsAdmin';\nimport { Client, ClientForm } from '../types';\n\nconst notificationId = 'oauth2clientedit';\n\nfunction getDefaultForm(scopes: Record): ClientForm {\n const firstScope = Object.keys(scopes || {})[0] || '';\n\n return {\n name: '',\n description: '',\n type: 'confidential',\n grant_types: ['authorization_code', 'client_credentials', 'refresh_token'],\n scope: firstScope,\n redirect_uris: '',\n active: true,\n };\n}\n\nexport default defineComponent({\n name: 'Oauth2ClientEdit',\n props: {\n clientId: {\n type: String,\n required: true,\n },\n initialSecret: {\n type: String,\n default: '',\n },\n scopes: {\n type: Object as PropType>,\n required: true,\n },\n },\n directives: {\n CopyToClipboard,\n },\n emits: ['cancel', 'saved'],\n components: {\n ContentBlock,\n Field,\n },\n data() {\n const typeOptions = {\n confidential: this.translate('OAuth2_AdminConfidential'),\n public: this.translate('OAuth2_AdminPublic'),\n };\n\n const grantOptions = {\n authorization_code: this.translate('OAuth2_AdminGrantAuthorizationCode'),\n client_credentials: this.translate('OAuth2_AdminGrantClientCredentials'),\n refresh_token: this.translate('OAuth2_AdminGrantRefreshToken'),\n };\n\n return {\n loading: false,\n confirmRotateLabel: '',\n typeOptions,\n grantOptions,\n form: getDefaultForm(this.scopes),\n visibleSecret: this.initialSecret,\n };\n },\n created() {\n this.init();\n },\n watch: {\n clientId() {\n this.init();\n },\n initialSecret(newSecret: string) {\n this.visibleSecret = newSecret;\n },\n 'form.type': 'onFormTypeChange',\n },\n computed: {\n isEditMode(): boolean {\n return this.clientId !== '0';\n },\n contentTitle(): string {\n return this.isEditMode\n ? this.translate('OAuth2_AdminEditTitle')\n : this.translate('OAuth2_AdminCreateTitle');\n },\n submitLabel(): string {\n return this.isEditMode\n ? this.translate('OAuth2_AdminUpdate')\n : this.translate('OAuth2_AdminSave');\n },\n visibleGrantOptions(): Record {\n if (this.form.type === 'public') {\n const filtered: Record = {};\n if (this.grantOptions.authorization_code) {\n filtered.authorization_code = this.grantOptions.authorization_code;\n }\n if (this.grantOptions.refresh_token) {\n filtered.refresh_token = this.grantOptions.refresh_token;\n }\n return filtered;\n }\n\n return this.grantOptions;\n },\n showSecretPanel(): boolean {\n return this.form.type === 'confidential' && (this.isEditMode || !!this.visibleSecret);\n },\n canRegenerateSecret(): boolean {\n return this.isEditMode && this.form.type === 'confidential';\n },\n displayedSecret(): string {\n return this.visibleSecret || '*************';\n },\n secretInlineHelp(): string {\n if (this.visibleSecret) {\n return this.translate('OAuth2_ClientSecretVisibleHelp');\n }\n\n return this.translate('OAuth2_ClientSecretMaskedHelp');\n },\n },\n methods: {\n init() {\n this.removeNotifications();\n this.form = getDefaultForm(this.scopes);\n this.visibleSecret = this.initialSecret;\n\n if (!this.isEditMode) {\n return;\n }\n\n this.loading = true;\n AjaxHelper.fetch({\n method: 'OAuth2.getClient',\n clientId: this.clientId,\n }).then((client) => {\n this.form = {\n name: client.name || '',\n description: client.description || '',\n type: client.type || 'confidential',\n grant_types: client.grant_types || [],\n scope: (client.scopes && client.scopes[0]) || Object.keys(this.scopes || {})[0] || '',\n redirect_uris: (client.redirect_uris || []).join('\\n'),\n active: !!client.active,\n };\n }).finally(() => {\n this.loading = false;\n });\n },\n onFormTypeChange(newType: string) {\n if (newType === 'public' && this.form.grant_types.includes('client_credentials')) {\n this.form.grant_types = this.form.grant_types.filter((value: string) => value !== 'client_credentials');\n }\n\n if (newType === 'public') {\n this.visibleSecret = '';\n }\n },\n rotateSecret() {\n if (!this.canRegenerateSecret) {\n return;\n }\n\n this.confirmRotateLabel = this.translate('OAuth2_AdminRotateConfirm', this.form.name || this.clientId);\n Matomo.helper.modalConfirm(this.$refs.confirmRotateClient as HTMLElement, {\n yes: () => {\n this.loading = true;\n AjaxHelper.fetch({\n method: 'OAuth2.rotateSecret',\n clientId: this.clientId,\n }).then((response) => {\n if (response?.secret) {\n this.visibleSecret = response.secret;\n }\n }).finally(() => {\n this.loading = false;\n });\n },\n });\n },\n submit() {\n this.removeNotifications();\n if (!this.checkRequiredFieldsAreSet()) {\n return;\n }\n\n this.loading = true;\n const params = {\n method: this.isEditMode ? 'OAuth2.updateClient' : 'OAuth2.createClient',\n name: this.form.name.trim(),\n description: this.form.description,\n type: this.form.type,\n grantTypes: this.form.grant_types,\n scope: this.form.scope,\n redirectUris: this.form.redirect_uris,\n active: this.form.active ? '1' : '0',\n } as Record;\n\n if (this.isEditMode) {\n params.clientId = this.clientId;\n }\n\n AjaxHelper.fetch(params).then((response) => {\n this.visibleSecret = response.secret || '';\n const clientMessage = this.isEditMode\n ? this.translate('OAuth2_AdminUpdated', response.client.name)\n : this.translate('OAuth2_AdminCreated', response.client.name);\n const secretMessage = response.secret\n ? this.translate('OAuth2_ClientSecretHelp')\n : '';\n const message = [clientMessage, secretMessage].filter(Boolean).join(' ');\n\n this.$emit('saved', {\n client: response.client,\n secret: response.secret || null,\n });\n\n MatomoUrl.updateHash({\n ...MatomoUrl.hashParsed.value,\n idClient: response.client.client_id,\n });\n\n setTimeout(() => {\n this.showNotification(`${message}`, 'success', 'transient');\n }, 50);\n }).finally(() => {\n this.loading = false;\n });\n },\n checkRequiredFieldsAreSet() {\n let response = true;\n let errorMessage = '';\n if (!this.form.name.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminName');\n } else if (!this.form.type.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminType');\n } else if (!this.form.grant_types.length) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminClientGrants');\n } else if (!this.form.scope.trim()) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminScope');\n } else if (!this.form.redirect_uris.trim() && this.form.grant_types.includes('authorization_code')) {\n response = false;\n errorMessage = this.translate('OAuth2_AdminRedirectUris');\n }\n\n if (!response && errorMessage) {\n this.showErrorFieldNotProvidedNotification(errorMessage);\n }\n\n return response;\n },\n removeNotifications() {\n NotificationsStore.remove(notificationId);\n NotificationsStore.remove('ajaxHelper');\n },\n showNotification(message: string, context: NotificationType['context'],\n type: null|NotificationType['type'] = null) {\n const notificationInstanceId = NotificationsStore.show({\n message,\n context,\n id: notificationId,\n type: type !== null ? type : 'toast',\n });\n setTimeout(() => {\n NotificationsStore.scrollToNotification(notificationInstanceId);\n }, 200);\n },\n showErrorFieldNotProvidedNotification(title: string) {\n const message = this.translate('OAuth2_ErrorXNotProvided', [title]);\n this.showNotification(message, 'error');\n },\n },\n});\n","import { render } from \"./Edit.vue?vue&type=template&id=15c605de&scoped=true\"\nimport script from \"./Edit.vue?vue&type=script&lang=ts\"\nexport * from \"./Edit.vue?vue&type=script&lang=ts\"\n\nimport \"./Edit.vue?vue&type=style&index=0&id=15c605de&scoped=true&lang=css\"\nscript.render = render\nscript.__scopeId = \"data-v-15c605de\"\n\nexport default script","\nimport { defineComponent, watch } from 'vue';\nimport { MatomoUrl } from 'CoreHome';\nimport Oauth2ClientList from './List.vue';\nimport Oauth2ClientEdit from './Edit.vue';\nimport { Client } from '../types';\n\nexport default defineComponent({\n name: 'Oauth2AdminApp',\n props: {\n initialClients: {\n type: Array as () => Client[],\n required: true,\n },\n scopes: {\n type: Object as () => Record,\n required: true,\n },\n },\n components: {\n Oauth2ClientList,\n Oauth2ClientEdit,\n },\n data() {\n return {\n clients: this.initialClients as Client[] || [],\n secret: '',\n secretClientId: '',\n editedClientId: '',\n };\n },\n created() {\n watch(() => MatomoUrl.hashParsed.value.idClient as string, (idClient) => {\n this.initState(idClient);\n });\n\n this.initState(MatomoUrl.hashParsed.value.idClient as string);\n },\n methods: {\n initState(idClient?: string) {\n if (!idClient) {\n this.secret = '';\n this.secretClientId = '';\n } else if (this.secretClientId && this.secretClientId !== idClient) {\n this.secret = '';\n this.secretClientId = '';\n }\n\n this.editedClientId = idClient || '';\n },\n createClient() {\n MatomoUrl.updateHash({\n ...MatomoUrl.hashParsed.value,\n idClient: '0',\n });\n this.secret = '';\n this.secretClientId = '';\n },\n editClient(clientId: string) {\n if (this.secretClientId !== clientId) {\n this.secret = '';\n this.secretClientId = '';\n }\n\n MatomoUrl.updateHash({\n ...MatomoUrl.hashParsed.value,\n idClient: clientId,\n });\n },\n showList() {\n const params = {\n ...MatomoUrl.hashParsed.value,\n };\n delete params.idClient;\n this.secret = '';\n this.secretClientId = '';\n MatomoUrl.updateHash(params);\n },\n onClientSaved(payload: { client: Client; secret: string|null }) {\n const index = this.clients.findIndex(\n (client) => client.client_id === payload.client.client_id,\n );\n if (index === -1) {\n this.clients.push(payload.client);\n } else {\n this.clients.splice(index, 1, payload.client);\n }\n\n this.clients = [...this.clients].sort((left, right) => {\n const leftTime = left.updated_at ? new Date(left.updated_at).getTime() : 0;\n const rightTime = right.updated_at ? new Date(right.updated_at).getTime() : 0;\n\n if (rightTime !== leftTime) {\n return rightTime - leftTime;\n }\n\n return left.name.localeCompare(right.name);\n });\n this.secret = payload.secret || '';\n this.secretClientId = payload.secret ? payload.client.client_id : '';\n },\n onClientDeleted(clientId: string) {\n this.secret = '';\n if (this.secretClientId === clientId) {\n this.secretClientId = '';\n }\n this.clients = this.clients.filter((client) => client.client_id !== clientId);\n },\n onClientUpdated(updatedClient: Client) {\n const index = this.clients.findIndex(\n (client) => client.client_id === updatedClient.client_id,\n );\n if (index === -1) {\n return;\n }\n\n this.clients.splice(index, 1, updatedClient);\n this.clients = [...this.clients];\n },\n },\n computed: {\n isEditMode() {\n return !!this.editedClientId;\n },\n },\n});\n","import { render } from \"./Manage.vue?vue&type=template&id=f7d6db3a\"\nimport script from \"./Manage.vue?vue&type=script&lang=ts\"\nexport * from \"./Manage.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script"],"sourceRoot":""} \ No newline at end of file diff --git a/vue/dist/umd.metadata.json b/vue/dist/umd.metadata.json index 6eb1c55..dce4477 100644 --- a/vue/dist/umd.metadata.json +++ b/vue/dist/umd.metadata.json @@ -1,6 +1,6 @@ { "dependsOn": [ - "CorePluginsAdmin", - "CoreHome" + "CoreHome", + "CorePluginsAdmin" ] } \ No newline at end of file diff --git a/vue/src/AdminApp.vue b/vue/src/AdminApp.vue index 8a411fb..e4d56d8 100644 --- a/vue/src/AdminApp.vue +++ b/vue/src/AdminApp.vue @@ -335,7 +335,7 @@ export default defineComponent({ if (response.deleted) { this.clients = this.clients.filter((c) => c.client_id !== client.client_id); - const message = this.translate('OAuth2_AdminDeleted', client.client_id); + const message = this.translate('OAuth2_AdminDeleted', client.name); this.showSuccessNotification('deleteClient', message); } }); diff --git a/vue/src/OAuthClients/Edit.vue b/vue/src/OAuthClients/Edit.vue new file mode 100644 index 0000000..488a878 --- /dev/null +++ b/vue/src/OAuthClients/Edit.vue @@ -0,0 +1,474 @@ + + + + + diff --git a/vue/src/OAuthClients/List.vue b/vue/src/OAuthClients/List.vue new file mode 100644 index 0000000..7b228dc --- /dev/null +++ b/vue/src/OAuthClients/List.vue @@ -0,0 +1,235 @@ + + + + + diff --git a/vue/src/OAuthClients/Manage.vue b/vue/src/OAuthClients/Manage.vue new file mode 100644 index 0000000..0a470bb --- /dev/null +++ b/vue/src/OAuthClients/Manage.vue @@ -0,0 +1,148 @@ + + + diff --git a/vue/src/index.ts b/vue/src/index.ts index b9af893..6920d2c 100644 --- a/vue/src/index.ts +++ b/vue/src/index.ts @@ -5,4 +5,4 @@ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -export { default as Oauth2AdminApp } from './AdminApp.vue'; +export { default as Oauth2AdminApp } from './OAuthClients/Manage.vue'; diff --git a/vue/src/types.ts b/vue/src/types.ts new file mode 100644 index 0000000..4122a26 --- /dev/null +++ b/vue/src/types.ts @@ -0,0 +1,26 @@ +export type Client = { + client_id: string; + name: string; + description?: string; + type: string; + grant_types: string[]; + scopes: string[]; + redirect_uris: string[]; + active: boolean; + owner_login?: string; + created_at?: string; + updated_at?: string; + last_used_at?: string|null; + secret?: string|null; + isLoading?: boolean|false; +}; + +export type ClientForm = { + name: string; + description: string; + type: string; + grant_types: string[]; + scope: string; + redirect_uris: string; + active: boolean; +};