Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
5.0.2 - 2026-04-27
- Added code to show scope in the list view

5.0.1 - 2026-04-17
- Fixes README.md

Expand Down
16 changes: 16 additions & 0 deletions OAuth2.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Piwik\Db;
use Piwik\DbHelper;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\Plugin;
use Piwik\Plugins\OAuth2\Access\OAuth2Access;
use Piwik\Plugins\OAuth2\Auth\Oauth2Auth;
Expand All @@ -27,6 +28,17 @@ class OAuth2 extends Plugin
public const OAUTH2_PRIVATE_OPTION_KEY = 'oauth2_private';
public const OAUTH2_PUBLIC_OPTION_KEY = 'oauth2_public';
public const OAUTH2_ENCRYPTION_OPTION_KEY = 'oauth2_encryption';

public static function getScopeDescriptions(): array
{
return [
'matomo:read' => Piwik::translate('OAuth2_ScopeReadDescription'),
'matomo:write' => Piwik::translate('OAuth2_ScopeWriteDescription'),
'matomo:admin' => Piwik::translate('OAuth2_ScopeAdminDescription'),
'matomo:superuser' => Piwik::translate('OAuth2_ScopeSuperUserDescription'),
];
}

public function registerEvents()
{
return [
Expand Down Expand Up @@ -155,6 +167,10 @@ public function getClientSideTranslationKeys(&$translationKeys)
$translationKeys[] = 'OAuth2_ClientSecretVisibleHelp';
$translationKeys[] = 'OAuth2_AdminDescriptionPlaceholder';
$translationKeys[] = 'OAuth2_AdminRotatedNotification';
$translationKeys[] = 'OAuth2_ScopeSuperUserShort';
$translationKeys[] = 'UsersManager_PrivView';
$translationKeys[] = 'UsersManager_PrivWrite';
$translationKeys[] = 'UsersManager_PrivAdmin';
}

public function getTablesInstalled(&$allTablesInstalled)
Expand Down
8 changes: 2 additions & 6 deletions Repositories/ScopeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Matomo\Dependencies\Oauth2\League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use Piwik\Piwik;
use Piwik\Plugins\OAuth2\Entities\ClientEntity;
use Piwik\Plugins\OAuth2\OAuth2;
use Piwik\Plugins\OAuth2\Entities\ScopeEntity;
use Piwik\Plugins\OAuth2\SystemSettings;

Expand All @@ -29,12 +30,7 @@ public function __construct(SystemSettings $settings)

public static function getScopeDescriptions(): array
{
return [
'matomo:read' => Piwik::translate('OAuth2_ScopeReadDescription'),
'matomo:write' => Piwik::translate('OAuth2_ScopeWriteDescription'),
'matomo:admin' => Piwik::translate('OAuth2_ScopeAdminDescription'),
'matomo:superuser' => Piwik::translate('OAuth2_ScopeSuperUserDescription'),
];
return OAuth2::getScopeDescriptions();
}

public function getScopeEntityByIdentifier(string $identifier): ?ScopeEntityInterface
Expand Down
3 changes: 1 addition & 2 deletions SystemSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
namespace Piwik\Plugins\OAuth2;

use Piwik\Piwik;
use Piwik\Plugins\OAuth2\Repositories\ScopeRepository;
use Piwik\Settings\FieldConfig;
use Piwik\Settings\Plugin\SystemSettings as BaseSystemSettings;
use Piwik\Settings\Setting;
Expand Down Expand Up @@ -73,7 +72,7 @@ protected function init()
$field->title = Piwik::translate('OAuth2_SystemSettingOAuthEnableRefreshTokenTitle');
});

$scopes = ScopeRepository::getScopeDescriptions();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the cause of fatal error on activation, the required vendor libraries are not loaded by this time.

$scopes = OAuth2::getScopeDescriptions();
$defaultScopes = $scopes;
unset($defaultScopes['matomo:superuser']);
$this->defaultScopes = $this->makeSetting('defaultScopes', array_keys($defaultScopes), FieldConfig::TYPE_ARRAY, function (FieldConfig $field) use ($scopes) {
Expand Down
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"ScopeWriteDescription": "Matomo write level access",
"ScopeAdminDescription": "Matomo admin level access",
"ScopeSuperUserDescription": "Matomo superuser level access",
"ScopeSuperUserShort": "Superuser",
"SystemSettingOAuthAccessTokenLifetimeTitle": "Access token lifetime (seconds)",
"SystemSettingOAuthAccessTokenLifetimeDescription": "Define how long an access token remains valid after it is issued.",
"SystemSettingOAuthRefreshTokenLifetimeTitle": "Refresh token lifetime (seconds)",
Expand Down
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "OAuth2",
"description": "Provide secure access to the Matomo API using scoped permissions. No static credentials.",
"version": "5.0.1",
"version": "5.0.2",
"theme": false,
"require": {
"php": ">=8.1.0",
Expand Down
6 changes: 5 additions & 1 deletion stylesheets/oauth2.less
Comment thread
lachiebol marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#content.admin:has(.oauth2-admin) {
max-width: unset !important;
}

#oauth2AuthorizePage {
display: flex;
width: 100%;
Expand Down Expand Up @@ -161,4 +165,4 @@
#footerLinks {
margin-top: 1rem;
}
}
}
Binary file modified tests/UI/expected-ui-screenshots/OAuth2Admin_admin_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/UI/expected-ui-screenshots/OAuth2Admin_system_settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion vue/dist/OAuth2.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 62 additions & 28 deletions vue/dist/OAuth2.umd.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion vue/dist/OAuth2.umd.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion vue/dist/OAuth2.umd.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion vue/dist/OAuth2.umd.min.js.map

Large diffs are not rendered by default.

44 changes: 42 additions & 2 deletions vue/src/OAuthClients/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<th>{{ translate('OAuth2_AdminName') }}</th>
<th>{{ translate('OAuth2_AdminClientType') }}</th>
<th>{{ translate('OAuth2_AdminClientGrants') }}</th>
<th>{{ translate('OAuth2_AdminScope') }}</th>
<th>{{ translate('OAuth2_AdminClientStatus') }}</th>
<th>{{ translate('OAuth2_AdminClientId') }}</th>
<th>{{ translate('OAuth2_AdminClientRedirects') }}</th>
Expand All @@ -61,7 +62,15 @@
{{ client.name }}
</td>
<td>{{ typeOptions[client.type] }}</td>
<td>{{ (client.grant_types || []).join(', ') }}</td>
<td>
<div
v-for="grantType in (client.grant_types || [])"
:key="grantType"
>
{{ getGrantTypeLabel(grantType) }}
</div>
</td>
<td>{{ getScopeLabel(client) }}</td>
<td>
<span>
{{
Expand Down Expand Up @@ -108,7 +117,7 @@
</tbody>
<tbody v-else>
<tr>
<td colspan="8">{{ translate('OAuth2_AdminNoClients') }}</td>
<td colspan="9">{{ translate('OAuth2_AdminNoClients') }}</td>
</tr>
</tbody>
</table>
Expand Down Expand Up @@ -156,6 +165,10 @@ export default defineComponent({
type: Array as PropType<Client[]>,
required: true,
},
scopes: {
type: Object as PropType<Record<string, string>>,
required: true,
},
},
emits: ['create', 'edit', 'deleted', 'updated'],
components: {
Expand All @@ -172,9 +185,24 @@ export default defineComponent({
confidential: this.translate('OAuth2_AdminConfidential'),
public: this.translate('OAuth2_AdminPublic'),
} as Record<string, string>,
grantTypeOptions: {
authorization_code: this.translate('OAuth2_AdminGrantAuthorizationCode'),
client_credentials: this.translate('OAuth2_AdminGrantClientCredentials'),
refresh_token: this.translate('OAuth2_AdminGrantRefreshToken'),
} as Record<string, string>,
};
},
methods: {
getShortScopeLabel(scope: string) {
const shortScopeLabels = {
'matomo:read': this.translate('UsersManager_PrivView'),
'matomo:write': this.translate('UsersManager_PrivWrite'),
'matomo:admin': this.translate('UsersManager_PrivAdmin'),
'matomo:superuser': this.translate('OAuth2_ScopeSuperUserShort'),
} as Record<string, string>;

return shortScopeLabels[scope] || this.scopes[scope] || scope;
},
showNotification(message: string, context: NotificationType['context'],
type: null|NotificationType['type'] = null) {
const instanceId = NotificationsStore.show({
Expand All @@ -192,6 +220,18 @@ export default defineComponent({
NotificationsStore.remove(notificationId);
NotificationsStore.remove('ajaxHelper');
},
getScopeLabel(client: Client) {
const scope = client.scopes?.[0];

if (!scope) {
return '';
}

return this.getShortScopeLabel(scope);
},
getGrantTypeLabel(grantType: string) {
return this.grantTypeOptions[grantType] || grantType;
},
toggleClientStatus(client: Client) {
const safeClientName = Matomo.helper.htmlEntities(client.name || client.client_id);
this.confirmToggleLabel = client.active
Expand Down
1 change: 1 addition & 0 deletions vue/src/OAuthClients/Manage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<Oauth2ClientList
v-if="!isEditMode"
:clients="clients"
:scopes="scopes"
@create="createClient"
@edit="editClient"
@deleted="onClientDeleted"
Expand Down
Loading