keycloak-memoizeit

Merge branch 'KEYCLOAK-113' of https://github.com/ammendonca/keycloak

11/5/2013 8:12:00 AM

Details

diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
index 4c8d2c2..7025d2e 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
@@ -4,29 +4,31 @@ var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.loaders
 var resourceRequests = 0;
 
 module.config([ '$routeProvider', function($routeProvider) {
-	
-	$routeProvider
-
-	.when('/create/realm', {
-		templateUrl : 'partials/realm-detail.html',
-		resolve : {
-			realm : function(RealmLoader) {
-				return {};
-			}
-		},
-		controller : 'RealmDetailCtrl'
-	}).when('/realms/:realm', {
-		templateUrl : 'partials/realm-detail.html',
-		resolve : {
-			realm : function(RealmLoader) {
-				return RealmLoader();
-			}
-		},
-		controller : 'RealmDetailCtrl'
-	}).when('/realms', {
-		templateUrl : 'partials/realm-list.html',
-		controller : 'RealmListCtrl'
-	}).when('/realms/:realm/token-settings', {
+
+    $routeProvider
+        .when('/create/realm', {
+            templateUrl : 'partials/realm-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return {};
+                }
+            },
+            controller : 'RealmDetailCtrl'
+        })
+        .when('/realms/:realm', {
+            templateUrl : 'partials/realm-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmDetailCtrl'
+        })
+        .when('/realms', {
+            templateUrl : 'partials/realm-list.html',
+            controller : 'RealmListCtrl'
+        })
+        .when('/realms/:realm/token-settings', {
             templateUrl : 'partials/realm-tokens.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -34,7 +36,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'RealmTokenDetailCtrl'
-        }).when('/realms/:realm/social-settings', {
+        })
+        .when('/realms/:realm/social-settings', {
             templateUrl : 'partials/realm-social.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -52,18 +55,28 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'RealmRequiredCredentialsCtrl'
         })
-	.when('/create/user/:realm', {
-		templateUrl : 'partials/user-detail.html',
-		resolve : {
-			realm : function(RealmLoader) {
-				return RealmLoader();
-			},
-			user : function() {
-				return {};
-			}
-		},
-		controller : 'UserDetailCtrl'
-	}).when('/realms/:realm/users/:user', {
+        .when('/realms/:realm/smtp-settings', {
+            templateUrl : 'partials/realm-smtp.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmSMTPSettingsCtrl'
+        })
+        .when('/create/user/:realm', {
+            templateUrl : 'partials/user-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function() {
+                    return {};
+                }
+            },
+            controller : 'UserDetailCtrl'
+        })
+        .when('/realms/:realm/users/:user', {
             templateUrl : 'partials/user-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -74,7 +87,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'UserDetailCtrl'
-        }).when('/realms/:realm/users/:user/role-mappings', {
+        })
+        .when('/realms/:realm/users/:user/role-mappings', {
             templateUrl : 'partials/role-mappings.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -91,15 +105,16 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'UserRoleMappingCtrl'
-        }).when('/realms/:realm/users', {
-		templateUrl : 'partials/user-list.html',
-		resolve : {
-			realm : function(RealmLoader) {
-				return RealmLoader();
-			}
-        },
-		controller : 'UserListCtrl'
-	})
+        })
+        .when('/realms/:realm/users', {
+            templateUrl : 'partials/user-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'UserListCtrl'
+        })
 
         .when('/create/role/:realm', {
             templateUrl : 'partials/role-detail.html',
@@ -112,7 +127,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'RoleDetailCtrl'
-        }).when('/realms/:realm/roles/:role', {
+        })
+        .when('/realms/:realm/roles/:role', {
             templateUrl : 'partials/role-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -123,7 +139,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'RoleDetailCtrl'
-        }).when('/realms/:realm/roles', {
+        })
+        .when('/realms/:realm/roles', {
             templateUrl : 'partials/role-list.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -150,7 +167,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationRoleDetailCtrl'
-        }).when('/realms/:realm/applications/:application/roles/:role', {
+        })
+        .when('/realms/:realm/applications/:application/roles/:role', {
             templateUrl : 'partials/application-role-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -164,7 +182,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationRoleDetailCtrl'
-        }).when('/realms/:realm/applications/:application/credentials', {
+        })
+        .when('/realms/:realm/applications/:application/credentials', {
             templateUrl : 'partials/application-credentials.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -175,7 +194,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationCredentialsCtrl'
-        }).when('/realms/:realm/applications/:application/roles', {
+        })
+        .when('/realms/:realm/applications/:application/roles', {
             templateUrl : 'partials/application-role-list.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -189,7 +209,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationRoleListCtrl'
-        }).when('/realms/:realm/applications/:application/scope-mappings', {
+        })
+        .when('/realms/:realm/applications/:application/scope-mappings', {
             templateUrl : 'partials/application-scope-mappings.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -208,8 +229,6 @@ module.config([ '$routeProvider', function($routeProvider) {
             controller : 'ApplicationScopeMappingCtrl'
         })
 
-
-
         .when('/create/application/:realm', {
             templateUrl : 'partials/application-detail.html',
             resolve : {
@@ -224,7 +243,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationDetailCtrl'
-        }).when('/realms/:realm/applications/:application', {
+        })
+        .when('/realms/:realm/applications/:application', {
             templateUrl : 'partials/application-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -238,7 +258,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationDetailCtrl'
-        }).when('/realms/:realm/applications', {
+        })
+        .when('/realms/:realm/applications', {
             templateUrl : 'partials/application-list.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -250,33 +271,33 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'ApplicationListCtrl'
         })
-	.otherwise({
-		templateUrl : 'partials/home.html'
-	});
+        .otherwise({
+            templateUrl : 'partials/home.html'
+        });
 } ]);
 
 module.config(function($httpProvider) {
-	$httpProvider.responseInterceptors.push('errorInterceptor');
+    $httpProvider.responseInterceptors.push('errorInterceptor');
 
-	var spinnerFunction = function(data, headersGetter) {
-		if (resourceRequests == 0) {
-			$('#loading').show();
-		}
-		resourceRequests++;
-		return data;
-	};
-	$httpProvider.defaults.transformRequest.push(spinnerFunction);
+    var spinnerFunction = function(data, headersGetter) {
+        if (resourceRequests == 0) {
+            $('#loading').show();
+        }
+        resourceRequests++;
+        return data;
+    };
+    $httpProvider.defaults.transformRequest.push(spinnerFunction);
 
-	$httpProvider.responseInterceptors.push('spinnerInterceptor');
+    $httpProvider.responseInterceptors.push('spinnerInterceptor');
 
 });
 
 module.factory('errorInterceptor', function($q, $window, $rootScope, $location, Auth) {
-	return function(promise) {
-		return promise.then(function(response) {
-			$rootScope.httpProviderError = null;
-			return response;
-		}, function(response) {
+    return function(promise) {
+        return promise.then(function(response) {
+            $rootScope.httpProviderError = null;
+            return response;
+        }, function(response) {
             if (response.status == 401) {
                 console.log('session timeout?');
                 Auth.loggedIn = false;
@@ -284,28 +305,28 @@ module.factory('errorInterceptor', function($q, $window, $rootScope, $location, 
             } else {
                 $rootScope.httpProviderError = response.status;
             }
-			return $q.reject(response);
-		});
-	};
+            return $q.reject(response);
+        });
+    };
 });
 
 module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) {
-	return function(promise) {
-		return promise.then(function(response) {
-			resourceRequests--;
-			if (resourceRequests == 0) {
-				$('#loading').hide();
-			}
-			return response;
-		}, function(response) {
-			resourceRequests--;
-			if (resourceRequests == 0) {
-				$('#loading').hide();
-			}
-
-			return $q.reject(response);
-		});
-	};
+    return function(promise) {
+        return promise.then(function(response) {
+            resourceRequests--;
+            if (resourceRequests == 0) {
+                $('#loading').hide();
+            }
+            return response;
+        }, function(response) {
+            resourceRequests--;
+            if (resourceRequests == 0) {
+                $('#loading').hide();
+            }
+
+            return $q.reject(response);
+        });
+    };
 });
 
 // collapsable form fieldsets
@@ -354,80 +375,80 @@ module.directive('collapsed', function() {
 
 
 module.directive('kcInput', function() {
-	var d = {
-		scope : true,
-		replace : false,
-		link : function(scope, element, attrs) {
-			var form = element.children('form');
-			var label = element.children('label');
-			var input = element.children('input');
-
-			var id = form.attr('name') + '.' + input.attr('name');
-
-			element.attr('class', 'control-group');
-
-			label.attr('class', 'control-label');
-			label.attr('for', id);
-
-			input.wrap('<div class="controls"/>');
-			input.attr('id', id);
-
-			if (!input.attr('placeHolder')) {
-				input.attr('placeHolder', label.text());
-			}
-
-			if (input.attr('required')) {
-				label.append(' <span class="required">*</span>');
-			}
-		}
-	};
-	return d;
+    var d = {
+        scope : true,
+        replace : false,
+        link : function(scope, element, attrs) {
+            var form = element.children('form');
+            var label = element.children('label');
+            var input = element.children('input');
+
+            var id = form.attr('name') + '.' + input.attr('name');
+
+            element.attr('class', 'control-group');
+
+            label.attr('class', 'control-label');
+            label.attr('for', id);
+
+            input.wrap('<div class="controls"/>');
+            input.attr('id', id);
+
+            if (!input.attr('placeHolder')) {
+                input.attr('placeHolder', label.text());
+            }
+
+            if (input.attr('required')) {
+                label.append(' <span class="required">*</span>');
+            }
+        }
+    };
+    return d;
 });
 
 module.directive('kcEnter', function() {
-	return function(scope, element, attrs) {
-		element.bind("keydown keypress", function(event) {
-			if (event.which === 13) {
-				scope.$apply(function() {
-					scope.$eval(attrs.kcEnter);
-				});
-
-				event.preventDefault();
-			}
-		});
-	};
+    return function(scope, element, attrs) {
+        element.bind("keydown keypress", function(event) {
+            if (event.which === 13) {
+                scope.$apply(function() {
+                    scope.$eval(attrs.kcEnter);
+                });
+
+                event.preventDefault();
+            }
+        });
+    };
 });
 
 
 module.filter('remove', function() {
-	return function(input, remove, attribute) {
-		if (!input || !remove) {
-			return input;
-		}
-
-		var out = [];
-		for ( var i = 0; i < input.length; i++) {
-			var e = input[i];
-
-			for (var j = 0; j < remove.length; j++) {
-				if (attribute) {
-					if (remove[j][attribute] == e[attribute]) {
-						e = null;
-						break;
-					}
-				} else {
-					if (remove[j] == e) {
-						e = null;
-						break;
-					}
-				}
-			}
-
-			if (e != null) {
-				out.push(e);
-			}
-		}
-
-		return out;
-	};
+    return function(input, remove, attribute) {
+        if (!input || !remove) {
+            return input;
+        }
+
+        var out = [];
+        for ( var i = 0; i < input.length; i++) {
+            var e = input[i];
+
+            for (var j = 0; j < remove.length; j++) {
+                if (attribute) {
+                    if (remove[j][attribute] == e[attribute]) {
+                        e = null;
+                        break;
+                    }
+                } else {
+                    if (remove[j] == e) {
+                        e = null;
+                        break;
+                    }
+                }
+            }
+
+            if (e != null) {
+                out.push(e);
+            }
+        }
+
+        return out;
+    };
 });
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index 1b4a4f5..fa11a54 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -453,3 +453,38 @@ module.controller('RoleDetailCtrl', function($scope, realm, role, Role, $locatio
         });
     };
 });
+
+module.controller('RealmSMTPSettingsCtrl', function($scope, Current, Realm, realm, $http, $location, Dialog, Notifications) {
+    $scope.realm = {
+        id : realm.id, realm : realm.realm, social : realm.social,
+        smtpServer: realm.smtpServer
+    };
+
+    var oldCopy = angular.copy($scope.realm);
+    $scope.changed = false;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        if ($scope.realmForm.$valid) {
+            var realmCopy = angular.copy($scope.realm);
+            $scope.changed = false;
+            Realm.update(realmCopy, function () {
+                $location.url("/realms/" + realm.id + "/smtp-settings");
+                Notifications.success("Your changes have been saved to the realm.");
+            });
+        } else {
+            $scope.realmForm.showErrors = true;
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.realm = angular.copy(oldCopy);
+        $scope.changed = false;
+        $scope.realmForm.showErrors = false;
+    };
+});
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-credentials.html
index 1d4d9ff..0f9f849 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-credentials.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-credentials.html
@@ -9,6 +9,7 @@
                     <li><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
index 1567a2f..69eabd1 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
@@ -9,6 +9,7 @@
                     <li><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-smtp.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-smtp.html
new file mode 100755
index 0000000..b3e6d80
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-smtp.html
@@ -0,0 +1,121 @@
+<div id="wrapper" class="container">
+    <div class="row">
+        <div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
+        <div id="content-area" class="col-md-9" role="main">
+            <div class="top-nav" data-ng-hide="createRealm">
+                <ul class="rcue-tabs">
+                    <li><a href="#/realms/{{realm.id}}">General</a></li>
+                    <li data-ng-show="realm.social"><a href="#/realms/{{realm.id}}/social-settings">Social</a></li>
+                    <li><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
+                    <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
+                    <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
+                </ul>
+            </div>
+            <div id="content">
+                <ol class="breadcrumb">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}">Settings</a></li>
+                    <li class="active">SMTP Configuration</li>
+                </ol>
+                <h2><span>{{realm.realm}}</span> SMTP Settings</h2>
+                <form name="realmForm" novalidate>
+                    <fieldset>
+                        <legend uncollapsed><span class="text">Required Settings</span></legend>
+                        <div class="form-group clearfix">
+                            <label for="smtpHost" class="control-label">Host <span class="required">*</span></label>
+                            <div class="controls">
+                                <input id="smtpHost" type="text" ng-model="realm.smtpServer.host" placeholder="SMTP Host" required>
+                            </div>
+                        </div>
+                        <div class="form-group clearfix">
+                            <label for="smtpPort" class="control-label">Port <span class="required">*</span></label>
+                            <div class="controls">
+                                <input id="smtpPort" type="text" ng-model="realm.smtpServer.port" placeholder="SMTP Port (defaults to 25)" required>
+                            </div>
+                        </div>
+                        <div class="form-group clearfix">
+                            <label for="smtpFrom" class="control-label">From <span class="required">*</span></label>
+                            <div class="controls">
+                                <input id="smtpFrom" type="email" ng-model="realm.smtpServer.from" placeholder="SMTP From" required>
+                            </div>
+                        </div>
+                        <div class="form-group clearfix">
+                            <label for="smtpSSL" class="control-label">Enable SSL</label>
+                            <div class="onoffswitch">
+                                <input type="checkbox" data-ng-model="realm.smtpServer.ssl.enable" class="onoffswitch-checkbox" name="smtpSSL" id="smtpSSL">
+                                <label for="smtpSSL" class="onoffswitch-label">
+                                        <span class="onoffswitch-inner">
+                                            <span class="onoffswitch-active">ON</span>
+                                            <span class="onoffswitch-inactive">OFF</span>
+                                        </span>
+                                    <span class="onoffswitch-switch"></span>
+                                </label>
+                            </div>
+                        </div>
+                    </fieldset>
+                    <fieldset>
+                        <legend collapsed><span class="text">Authentication</span></legend>
+                        <div class="form-group clearfix">
+                            <label for="smtpAuth" class="control-label">Enabled</label>
+                            <div class="onoffswitch">
+                                <input type="checkbox" data-ng-model="realm.smtpServer.auth" class="onoffswitch-checkbox" name="smtpAuth" id="smtpAuth">
+                                <label for="smtpAuth" class="onoffswitch-label">
+                                        <span class="onoffswitch-inner">
+                                            <span class="onoffswitch-active">ON</span>
+                                            <span class="onoffswitch-inactive">OFF</span>
+                                        </span>
+                                    <span class="onoffswitch-switch"></span>
+                                </label>
+                            </div>
+                        </div>
+                        <div class="form-group clearfix">
+                            <label for="smtpUsername" class="control-label">Username <span class="required" ng-show="realm.smtpServer.auth">*</span></label>
+                            <div class="controls">
+                                <input id="smtpUsername" type="text" ng-model="realm.smtpServer.user" placeholder="Login Username" ng-disabled="!realm.smtpServer.auth" ng-required="realm.smtpServer.auth">
+                            </div>
+                        </div>
+                        <div class="form-group clearfix">
+                            <label for="smtpPassword" class="control-label">Password <span class="required" ng-show="realm.smtpServer.auth">*</span></label>
+                            <div class="controls">
+                                <input id="smtpPassword" type="password" ng-model="realm.smtpServer.password" placeholder="Login Password" ng-disabled="!realm.smtpServer.auth" ng-required="realm.smtpServer.auth">
+                            </div>
+                        </div>
+                    </fieldset>
+<!--
+                    <fieldset class="border-top">
+                        <div class="form-group clearfix" ng-repeat="(name, setting) in smtpSettings | orderBy: setting.required">
+                            <label for="{{name}}" class="control-label">{{name.replace('mail.smtp.','')}} <span class="required" data-ng-show="setting.required">*</span></label>
+
+                            <div ng-show="setting.type == 'boolean'" class="onoffswitch">
+                                <input type="checkbox" data-ng-model="realm.smtp[name]" class="onoffswitch-checkbox" name="{{name}}" id="{{name}}">
+                                <label for="{{name}}" class="onoffswitch-label">
+                                        <span class="onoffswitch-inner">
+                                            <span class="onoffswitch-active">ON</span>
+                                            <span class="onoffswitch-inactive">OFF</span>
+                                        </span>
+                                    <span class="onoffswitch-switch"></span>
+                                </label>
+                            </div>
+                            <div ng-show="setting.type == 'String'" class="controls">
+                                <input id="{{name}}" type="text" ng-model="realm.smtp[name]" placeholder="SMTP {{name}} / {{ setting.required }}">
+                            </div>
+                            <div ng-show="setting.type == 'int'" class="controls">
+                                <input id="{{name}}" type="number" ng-model="realm.smtp[name]" placeholder="SMTP {{name}} / {{ setting.required }}">
+                            </div>
+                        </div>
+                    </fieldset>
+-->
+                   <div class="form-actions">
+                        <button type="submit" data-ng-click="save()" class="primary" data-ng-show="changed">Save
+                        </button>
+                        <button type="submit" data-ng-click="reset()" data-ng-show="changed">Clear changes
+                        </button>
+                    </div>
+
+                </form>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-social.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-social.html
index 3844c6b..a046cc5 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-social.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-social.html
@@ -9,6 +9,7 @@
                     <li><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html
index 53b405e..4092a90 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html
@@ -9,6 +9,7 @@
                     <li><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-detail.html
index 78eeda7..e9ee0c0 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-detail.html
@@ -9,6 +9,7 @@
                     <li class="active"><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html
index 69fbdcd..b1ae532 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html
@@ -9,6 +9,7 @@
                     <li class="active"><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
+                    <li><a href="#/realms/{{realm.id}}/smtp-settings">SMTP</a></li>
                 </ul>
             </div>
             <div id="content">