You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2016/09/08 04:46:28 UTC

[11/50] [abbrv] ignite git commit: IGNITE-2388 Implemented ACL services and userbar modification on ACL.

IGNITE-2388 Implemented ACL services and userbar modification on ACL.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f1cdb871
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f1cdb871
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f1cdb871

Branch: refs/heads/ignite-3629
Commit: f1cdb871884c69c4d1c3a1073e694dccc3fcb634
Parents: 8e844d2
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Wed Aug 24 16:36:27 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 16:36:27 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/app.js         |  5 +--
 .../app/modules/navbar/userbar.directive.js     |  8 ++---
 .../frontend/app/modules/states/admin.state.js  |  3 +-
 .../app/modules/states/configuration.state.js   | 10 ++++--
 .../frontend/app/modules/states/errors.state.js | 37 +++++++++++++++++++
 .../frontend/app/modules/states/logout.state.js |  7 ++--
 .../app/modules/states/password.state.js        |  4 ++-
 .../app/modules/states/profile.state.js         |  3 +-
 .../frontend/app/modules/states/signin.state.js | 26 +++++---------
 .../app/modules/user/AclRoute.provider.js       | 38 ++++++++++++++++++++
 .../frontend/app/modules/user/permissions.js    | 28 +++++++++++++++
 .../frontend/app/modules/user/user.module.js    | 29 +++++++++++++--
 modules/web-console/frontend/app/vendor.js      |  1 +
 modules/web-console/frontend/package.json       |  1 +
 .../public/stylesheets/blocks/error.scss        | 31 ++++++++++++++++
 .../frontend/public/stylesheets/style.scss      |  1 +
 modules/web-console/frontend/views/403.jade     | 30 ++++++++++++++++
 modules/web-console/frontend/views/404.jade     | 30 ++++++++++++++++
 18 files changed, 257 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index 7340d7b..549081f 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -34,6 +34,7 @@ import './modules/states/password.state';
 import './modules/states/configuration.state';
 import './modules/states/profile.state';
 import './modules/states/admin.state';
+import './modules/states/errors.state';
 
 // ignite:modules
 import './modules/user/user.module';
@@ -158,6 +159,7 @@ angular
     'ignite-console.states.configuration',
     'ignite-console.states.profile',
     'ignite-console.states.admin',
+    'ignite-console.states.errors',
     // Common modules.
     'ignite-console.dialog',
     'ignite-console.navbar',
@@ -231,8 +233,7 @@ angular
             templateUrl: baseTemplate
         });
 
-    $urlRouterProvider.otherwise('/');
-
+    $urlRouterProvider.otherwise('/404');
     $locationProvider.html5Mode(true);
 }])
 .run(['$rootScope', '$state', 'MetaTags', 'gettingStarted', ($root, $state, $meta, gettingStarted) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/navbar/userbar.directive.js b/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
index b10d5ef..af70eb1 100644
--- a/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
+++ b/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
@@ -18,7 +18,7 @@
 export default ['igniteUserbar', [function() {
     return {
         restrict: 'A',
-        controller: ['$rootScope', 'IgniteUserbar', function($root, IgniteUserbar) {
+        controller: ['$rootScope', 'IgniteUserbar', 'AclService', function($root, IgniteUserbar, AclService) {
             const ctrl = this;
 
             ctrl.items = [
@@ -26,15 +26,15 @@ export default ['igniteUserbar', [function() {
                 {text: 'Getting started', click: 'gettingStarted.tryShow(true)'}
             ];
 
-            const _rebuildSettings = (event, user) => {
+            const _rebuildSettings = () => {
                 ctrl.items.splice(2);
 
-                if (!user.becomeUsed && user.admin)
+                if (AclService.can('admin_page'))
                     ctrl.items.push({text: 'Admin panel', sref: 'settings.admin'});
 
                 ctrl.items.push(...IgniteUserbar);
 
-                if (!user.becomeUsed)
+                if (AclService.can('logout'))
                     ctrl.items.push({text: 'Log out', sref: 'logout'});
             };
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/admin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/admin.state.js b/modules/web-console/frontend/app/modules/states/admin.state.js
index af1fbde..c3151e1 100644
--- a/modules/web-console/frontend/app/modules/states/admin.state.js
+++ b/modules/web-console/frontend/app/modules/states/admin.state.js
@@ -21,12 +21,13 @@ angular
 .module('ignite-console.states.admin', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('settings.admin', {
         url: '/admin',
         templateUrl: '/settings/admin.html',
+        onEnter: AclRoute.checkAccess('admin_page'),
         metaTags: {
             title: 'List of registered users'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/configuration.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration.state.js b/modules/web-console/frontend/app/modules/states/configuration.state.js
index fd9bd1c..7fd7541 100644
--- a/modules/web-console/frontend/app/modules/states/configuration.state.js
+++ b/modules/web-console/frontend/app/modules/states/configuration.state.js
@@ -32,16 +32,18 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
     // Services.
     .service('igniteConfigurationResource', ConfigurationResource)
     // Configure state provider.
-    .config(['$stateProvider', ($stateProvider) => {
+    .config(['$stateProvider', 'AclRouteProvider', ($stateProvider, AclRoute) => {
         // Setup the states.
         $stateProvider
             .state('base.configuration', {
                 url: '/configuration',
-                templateUrl: '/configuration/sidebar.html'
+                templateUrl: '/configuration/sidebar.html',
+                abstract: true
             })
             .state('base.configuration.clusters', {
                 url: '/clusters',
                 templateUrl: '/configuration/clusters.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -52,6 +54,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.caches', {
                 url: '/caches',
                 templateUrl: '/configuration/caches.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -62,6 +65,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.domains', {
                 url: '/domains',
                 templateUrl: '/configuration/domains.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -72,6 +76,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.igfs', {
                 url: '/igfs',
                 templateUrl: '/configuration/igfs.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -82,6 +87,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.summary', {
                 url: '/summary',
                 templateUrl: '/configuration/summary.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 controller: ConfigurationSummaryCtrl,
                 controllerAs: 'ctrl',
                 metaTags: {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/errors.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/errors.state.js b/modules/web-console/frontend/app/modules/states/errors.state.js
new file mode 100644
index 0000000..df31f57
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/errors.state.js
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+import templateNotFoundPage from '../../../views/404.jade';
+import templateNotAuthorizedPage from '../../../views/403.jade';
+
+angular
+    .module('ignite-console.states.errors', [
+        'ui.router'
+    ])
+    .config(['$stateProvider', 'AclRouteProvider', function($stateProvider) {
+        // set up the states
+        $stateProvider
+            .state('404', {
+                url: '/404',
+                templateUrl: templateNotFoundPage
+            })
+            .state('403', {
+                url: '/403',
+                templateUrl: templateNotAuthorizedPage
+            });
+    }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/logout.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/logout.state.js b/modules/web-console/frontend/app/modules/states/logout.state.js
index 7f24a45..42795ea 100644
--- a/modules/web-console/frontend/app/modules/states/logout.state.js
+++ b/modules/web-console/frontend/app/modules/states/logout.state.js
@@ -21,14 +21,13 @@ angular
 .module('ignite-console.states.logout', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('logout', {
         url: '/logout',
-        controller: ['Auth', function(Auth) {
-            Auth.logout();
-        }],
+        onEnter: AclRoute.checkAccess('logout'),
+        controller: ['Auth', (Auth) => Auth.logout()],
         metaTags: {
             title: 'Logout'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/password.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/password.state.js b/modules/web-console/frontend/app/modules/states/password.state.js
index 48d01df..2eb030c 100644
--- a/modules/web-console/frontend/app/modules/states/password.state.js
+++ b/modules/web-console/frontend/app/modules/states/password.state.js
@@ -21,7 +21,7 @@ angular
 .module('ignite-console.states.password', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('password', {
@@ -32,6 +32,7 @@ angular
     .state('password.reset', {
         url: '/reset?{token}',
         templateUrl: '/reset.html',
+        onEnter: AclRoute.checkAccess('login'),
         metaTags: {
             title: 'Reset password'
         }
@@ -39,6 +40,7 @@ angular
     .state('password.send', {
         url: '/send',
         templateUrl: '/reset.html',
+        onEnter: AclRoute.checkAccess('login'),
         metaTags: {
             title: 'Password Send'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/profile.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/profile.state.js b/modules/web-console/frontend/app/modules/states/profile.state.js
index 8b6cdfe..9c31340 100644
--- a/modules/web-console/frontend/app/modules/states/profile.state.js
+++ b/modules/web-console/frontend/app/modules/states/profile.state.js
@@ -21,12 +21,13 @@ angular
 .module('ignite-console.states.profile', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('settings.profile', {
         url: '/profile',
         templateUrl: '/settings/profile.html',
+        onEnter: AclRoute.checkAccess('profile'),
         metaTags: {
             title: 'User profile'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/signin.state.js b/modules/web-console/frontend/app/modules/states/signin.state.js
index a23a496..42175cf 100644
--- a/modules/web-console/frontend/app/modules/states/signin.state.js
+++ b/modules/web-console/frontend/app/modules/states/signin.state.js
@@ -24,30 +24,20 @@ angular
     // services
     'ignite-console.user'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider) {
     // set up the states
     $stateProvider
     .state('signin', {
         url: '/',
         templateUrl,
-        metaTags: {
-        }
-    });
-}])
-.run(['$rootScope', '$state', 'Auth', 'IgniteBranding', function($root, $state, Auth, branding) {
-    $root.$on('$stateChangeStart', function(event, toState) {
-        if (toState.name === branding.termsState)
-            return;
-
-        if (!Auth.authorized && (toState.name !== 'signin' && !_.startsWith(toState.name, 'password.'))) {
-            event.preventDefault();
+        onEnter: ['$state', 'Auth', 'AclService', ($state, Auth, AclService) => {
+            if (Auth.authorized)
+                $state.go('base.configuration.clusters');
 
-            $state.go('signin');
-        }
-        else if (Auth.authorized && toState.name === 'signin') {
-            event.preventDefault();
-
-            $state.go('base.configuration.clusters');
+            if (!AclService.can('login'))
+                $state.go('403');
+        }],
+        metaTags: {
         }
     });
 }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/AclRoute.provider.js b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
new file mode 100644
index 0000000..cfd9da1
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default [() => {
+    class AclRoute {
+        static checkAccess = (permissions, failState) => {
+            failState = failState || '403';
+
+            return ['$state', 'AclService', 'Auth', ($state, AclService) => {
+                if (AclService.can(permissions))
+                    return;
+
+                return $state.go(failState);
+            }];
+        }
+    }
+
+    return {
+        checkAccess: AclRoute.checkAccess,
+        $get: () => {
+            return AclRoute;
+        }
+    };
+}];

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/user/permissions.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/permissions.js b/modules/web-console/frontend/app/modules/user/permissions.js
new file mode 100644
index 0000000..ef10884
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/user/permissions.js
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const guest = ['login', 'terms'];
+const becomed = ['profile', 'configuration', 'query', 'terms'];
+const user = becomed.concat(['logout']);
+const admin = user.concat(['admin_page']);
+
+export default {
+    guest,
+    user,
+    admin,
+    becomed
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/user/user.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/user.module.js b/modules/web-console/frontend/app/modules/user/user.module.js
index 2387f20..a480f97 100644
--- a/modules/web-console/frontend/app/modules/user/user.module.js
+++ b/modules/web-console/frontend/app/modules/user/user.module.js
@@ -16,13 +16,38 @@
  */
 
 import angular from 'angular';
+import aclData from './permissions';
 
 import Auth from './Auth.service';
 import User from './User.service';
+import AclRouteProvider from './AclRoute.provider';
 
 angular
 .module('ignite-console.user', [
-
+    'mm.acl',
+    'ignite-console.config'
 ])
 .service(...Auth)
-.service(...User);
+.service(...User)
+.provider('AclRoute', AclRouteProvider)
+.run(['$rootScope', 'AclService', ($root, AclService) => {
+    AclService.setAbilities(aclData);
+    AclService.attachRole('guest');
+
+    $root.$on('user', (event, user) => {
+        if (!user)
+            return;
+
+        AclService.flushRoles();
+
+        let role = 'user';
+
+        if (user.admin)
+            role = 'admin';
+
+        if (user.becomeUsed)
+            role = 'becomed';
+
+        AclService.attachRole(role);
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/vendor.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/vendor.js b/modules/web-console/frontend/app/vendor.js
index a8eeea7..0322887 100644
--- a/modules/web-console/frontend/app/vendor.js
+++ b/modules/web-console/frontend/app/vendor.js
@@ -17,6 +17,7 @@
 
 import 'jquery';
 import 'angular';
+import 'angular-acl';
 import 'angular-animate';
 import 'angular-sanitize';
 import 'angular-strap';

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/package.json b/modules/web-console/frontend/package.json
index 9bc6987..5814522 100644
--- a/modules/web-console/frontend/package.json
+++ b/modules/web-console/frontend/package.json
@@ -30,6 +30,7 @@
   ],
   "dependencies": {
     "angular": "^1.5.5",
+    "angular-acl": "^0.1.7",
     "angular-animate": "^1.5.5",
     "angular-aria": "^1.5.5",
     "angular-cookies": "^1.5.5",

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/public/stylesheets/blocks/error.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/blocks/error.scss b/modules/web-console/frontend/public/stylesheets/blocks/error.scss
new file mode 100644
index 0000000..20f83a8
--- /dev/null
+++ b/modules/web-console/frontend/public/stylesheets/blocks/error.scss
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.error-page {
+    text-align: center;
+    min-height: 300px;
+
+    &__title {
+        margin-top: 100px;
+        font-weight: 200;
+    }
+
+    &__description {
+        margin-top: 30px;
+        font-weight: 500;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index 994595a..4db7127 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -20,6 +20,7 @@
 @import "./variables";
 @import "~roboto-font/css/fonts.css";
 @import "./../../app/directives/information/information.scss";
+@import "./blocks/error";
 
 hr {
     margin: 20px 0;

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/views/403.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/403.jade b/modules/web-console/frontend/views/403.jade
new file mode 100644
index 0000000..1a1cc04
--- /dev/null
+++ b/modules/web-console/frontend/views/403.jade
@@ -0,0 +1,30 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+header#header.header
+    table.container
+        tr
+            td.col-xs-3.col-sm-3.col-md-2
+                ignite-header-logo
+            td
+                ignite-header-title
+
+.error-page
+    .container
+        h1.error-page__title 403
+        h2.error-page__description You not authorized
+
+include includes/footer

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/views/404.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/404.jade b/modules/web-console/frontend/views/404.jade
new file mode 100644
index 0000000..3533905
--- /dev/null
+++ b/modules/web-console/frontend/views/404.jade
@@ -0,0 +1,30 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+header#header.header
+    table.container
+        tr
+            td.col-xs-3.col-sm-3.col-md-2
+                ignite-header-logo
+            td
+                ignite-header-title
+
+.error-page
+    .container
+        h1.error-page__title 404
+        h2.error-page__description Page not found
+
+include includes/footer