Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117752885
D2524.1775191682.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
D2524.1775191682.diff
View Options
diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -188,7 +188,7 @@
isLoading() {
return isLoading > 0
},
- errorPage(code, msg) {
+ errorPage(code, msg, hint) {
// Until https://github.com/vuejs/vue-router/issues/977 is implemented
// we can't really use router to display error page as it has two side
// effects: it changes the URL and adds the error page to browser history.
@@ -203,8 +203,11 @@
}
if (!msg) msg = map[code] || "Unknown Error"
+ if (!hint) hint = ''
- const error_page = `<div id="error-page" class="error-page"><div class="code">${code}</div><div class="message">${msg}</div></div>`
+ const error_page = '<div id="error-page" class="error-page">'
+ + `<div class="code">${code}</div><div class="message">${msg}</div><div class="hint">${hint}</div>`
+ + '</div>'
$('#error-page').remove()
$('#app').append(error_page)
diff --git a/src/resources/js/routes-user.js b/src/resources/js/routes-user.js
--- a/src/resources/js/routes-user.js
+++ b/src/resources/js/routes-user.js
@@ -31,25 +31,25 @@
path: '/distlist/:list',
name: 'distlist',
component: DistlistInfoComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'distlists' }
},
{
path: '/distlists',
name: 'distlists',
component: DistlistListComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'distlists' }
},
{
path: '/domain/:domain',
name: 'domain',
component: DomainInfoComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'domains' }
},
{
path: '/domains',
name: 'domains',
component: DomainListComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'domains' }
},
{
path: '/login',
@@ -100,19 +100,19 @@
path: '/user/:user',
name: 'user',
component: UserInfoComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'users' }
},
{
path: '/users',
name: 'users',
component: UserListComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'users' }
},
{
path: '/wallet',
name: 'wallet',
component: WalletComponent,
- meta: { requiresAuth: true }
+ meta: { requiresAuth: true, perm: 'wallets' }
},
{
name: '404',
diff --git a/src/resources/themes/app.scss b/src/resources/themes/app.scss
--- a/src/resources/themes/app.scss
+++ b/src/resources/themes/app.scss
@@ -35,8 +35,10 @@
top: 0;
height: 100%;
width: 100%;
+ align-content: center;
align-items: center;
display: flex;
+ flex-wrap: wrap;
justify-content: center;
color: #636b6f;
z-index: 10;
@@ -53,6 +55,12 @@
font-size: 18px;
padding: 0 15px;
}
+
+ .hint {
+ margin-top: 3em;
+ text-align: center;
+ width: 100%;
+ }
}
.app-loader {
diff --git a/src/resources/vue/App.vue b/src/resources/vue/App.vue
--- a/src/resources/vue/App.vue
+++ b/src/resources/vue/App.vue
@@ -1,5 +1,5 @@
<template>
- <router-view v-if="!isLoading && !routerReloading" :key="key" @hook:mounted="childMounted"></router-view>
+ <router-view v-if="!isLoading && !routerReloading && key" :key="key" @hook:mounted="childMounted"></router-view>
</template>
<script>
@@ -12,6 +12,14 @@
},
computed: {
key() {
+ // Display 403 error page if the current user has no permission to a specified page
+ // Note that it's the only place I found that allows us to do this.
+ if (this.$route.meta.perm && !this.checkPermission(this.$route.meta.perm)) {
+ // Returning false here will block the page component from execution,
+ // as we're using the key in v-if condition on the router-view above
+ return false
+ }
+
// The 'key' property is used to reload the Page component
// whenever a route changes. Normally vue does not do that.
return this.$route.name == '404' ? this.$route.path : 'static'
@@ -41,6 +49,17 @@
}
},
methods: {
+ checkPermission(type) {
+ if (this.$root.hasPermission(type)) {
+ return true
+ }
+
+ const hint = type == 'wallets' ? "Only account owners can access a wallet." : ''
+
+ this.$root.errorPage(403, null, hint)
+
+ return false
+ },
childMounted() {
this.$root.updateBodyClass()
this.getFAQ()
diff --git a/src/resources/vue/Distlist/Info.vue b/src/resources/vue/Distlist/Info.vue
--- a/src/resources/vue/Distlist/Info.vue
+++ b/src/resources/vue/Distlist/Info.vue
@@ -56,11 +56,6 @@
}
},
created() {
- if (!this.$root.hasPermission('distlists')) {
- this.$root.errorPage(404)
- return
- }
-
this.list_id = this.$route.params.list
if (this.list_id != 'new') {
diff --git a/src/resources/vue/Distlist/List.vue b/src/resources/vue/Distlist/List.vue
--- a/src/resources/vue/Distlist/List.vue
+++ b/src/resources/vue/Distlist/List.vue
@@ -43,13 +43,6 @@
}
},
created() {
- // TODO: Find a way to do this in some more global way. Note that it cannot
- // be done in the vue-router, but maybe the app component?
- if (!this.$root.hasPermission('distlists')) {
- this.$root.errorPage(404)
- return
- }
-
this.$root.startLoading()
axios.get('/api/v4/groups')
diff --git a/src/tests/Browser.php b/src/tests/Browser.php
--- a/src/tests/Browser.php
+++ b/src/tests/Browser.php
@@ -76,9 +76,9 @@
/**
* Assert specified error page is displayed.
*/
- public function assertErrorPage(int $error_code)
+ public function assertErrorPage(int $error_code, string $hint = '')
{
- $this->with(new Error($error_code), function ($browser) {
+ $this->with(new Error($error_code, $hint), function ($browser) {
// empty, assertions will be made by the Error component itself
});
diff --git a/src/tests/Browser/Components/Error.php b/src/tests/Browser/Components/Error.php
--- a/src/tests/Browser/Components/Error.php
+++ b/src/tests/Browser/Components/Error.php
@@ -8,6 +8,7 @@
class Error extends BaseComponent
{
protected $code;
+ protected $hint;
protected $message;
protected $messages_map = [
400 => "Bad request",
@@ -18,9 +19,10 @@
500 => "Internal server error",
];
- public function __construct($code)
+ public function __construct($code, $hint = '')
{
$this->code = $code;
+ $this->hint = $hint;
$this->message = $this->messages_map[$code];
}
@@ -46,6 +48,12 @@
$browser->waitFor($this->selector())
->assertSeeIn('@code', $this->code);
+ if ($this->hint) {
+ $browser->assertSeeIn('@hint', $this->hint);
+ } else {
+ $browser->assertMissing('@hint');
+ }
+
$message = $browser->text('@message');
PHPUnit::assertSame(strtolower($message), strtolower($this->message));
}
@@ -62,6 +70,7 @@
return [
'@code' => "$selector .code",
'@message' => "$selector .message",
+ '@hint' => "$selector .hint",
];
}
}
diff --git a/src/tests/Browser/DistlistTest.php b/src/tests/Browser/DistlistTest.php
--- a/src/tests/Browser/DistlistTest.php
+++ b/src/tests/Browser/DistlistTest.php
@@ -76,7 +76,7 @@
// Test that Distribution lists page is not accessible without the 'distlist' entitlement
$this->browse(function (Browser $browser) {
$browser->visit('/distlists')
- ->assertErrorPage(404);
+ ->assertErrorPage(403);
});
// Create a single group, add beta+distlist entitlements
@@ -111,7 +111,7 @@
// Test that the page is not available accessible without the 'distlist' entitlement
$this->browse(function (Browser $browser) {
$browser->visit('/distlist/new')
- ->assertErrorPage(404);
+ ->assertErrorPage(403);
});
// Add beta+distlist entitlements
diff --git a/src/tests/Browser/Pages/Home.php b/src/tests/Browser/Pages/Home.php
--- a/src/tests/Browser/Pages/Home.php
+++ b/src/tests/Browser/Pages/Home.php
@@ -64,7 +64,8 @@
$wait_for_dashboard = false,
$config = []
) {
- $browser->type('@email-input', $username)
+ $browser->clearToasts()
+ ->type('@email-input', $username)
->type('@password-input', $password);
if ($username == 'ned@kolab.org') {
diff --git a/src/tests/Browser/UserProfileTest.php b/src/tests/Browser/UserProfileTest.php
--- a/src/tests/Browser/UserProfileTest.php
+++ b/src/tests/Browser/UserProfileTest.php
@@ -164,7 +164,6 @@
->on(new Home())
->submitLogon('profile-delete@kolabnow.com', 'simple123', true)
->on(new Dashboard())
- ->clearToasts()
->assertSeeIn('@links .link-profile', 'Your profile')
->click('@links .link-profile')
->on(new UserProfile())
diff --git a/src/tests/Browser/UsersTest.php b/src/tests/Browser/UsersTest.php
--- a/src/tests/Browser/UsersTest.php
+++ b/src/tests/Browser/UsersTest.php
@@ -508,11 +508,8 @@
$browser->visit('/logout')
->on(new Home())
->submitLogon('jack@kolab.org', 'simple123', true)
- ->visit(new UserList())
- ->whenAvailable('@table', function (Browser $browser) {
- $browser->assertElementsCount('tbody tr', 0)
- ->assertSeeIn('tfoot td', 'There are no users in this account.');
- });
+ ->visit('/users')
+ ->assertErrorPage(403);
});
// Test that controller user (Ned) can see all the users
diff --git a/src/tests/Browser/WalletTest.php b/src/tests/Browser/WalletTest.php
--- a/src/tests/Browser/WalletTest.php
+++ b/src/tests/Browser/WalletTest.php
@@ -257,4 +257,20 @@
});
});
}
+
+ /**
+ * Test that non-controller user has no access to wallet
+ */
+ public function testAccessDenied(): void
+ {
+ $this->browse(function (Browser $browser) {
+ $browser->visit('/logout')
+ ->on(new Home())
+ ->submitLogon('jack@kolab.org', 'simple123', true)
+ ->on(new Dashboard())
+ ->assertMissing('@links .link-wallet')
+ ->visit('/wallet')
+ ->assertErrorPage(403, "Only account owners can access a wallet.");
+ });
+ }
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 3, 4:48 AM (2 d, 16 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18817347
Default Alt Text
D2524.1775191682.diff (11 KB)
Attached To
Mode
D2524: Introduce a unified mechanism for permissions checking in the UI
Attached
Detach File
Event Timeline