Author: ivol37 at gmail.com
Date: Thu Dec 23 15:23:17 2010
New Revision: 543

Log:
[AMDATU-222] Finished UserAdmin gadget. Added (temporary) basic security check 
(user must be logged in and has role Administrators), did some bugfixing and 
moved language labels to a separate resource file.

Added:
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/util.js
   trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/labels/
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/labels/useradmin_ALL_ALL.xml
Modified:
   
trunk/amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/jsp/UserAdminGadget.jsp
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/tabs.css
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/useradmin.css
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/select_role.js
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/tabs.js
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin_rest.js
   trunk/amdatu-authorization/useradmin-rest/pom.xml
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java

Modified: 
trunk/amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
      (original)
+++ 
trunk/amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
      Thu Dec 23 15:23:17 2010
@@ -41,6 +41,9 @@
 import org.osgi.service.log.LogService;
 
 public class TokenProviderImpl implements TokenProvider {
+    // Name the authorization header when a token is passed in the 
"Authorization" header of a HTTP request
+    public final static String AUTHORIZATION_HEADER = "Amdatu";
+    
     // Service dependencies
     private volatile LogService m_logService;
 
@@ -244,6 +247,8 @@
     }
     
     public String getTokenFromRequest(HttpServletRequest request) {
+        // Use case 1: The token is send along in a cookie with the request. 
The cookie is send
+        // automatically when a request is send directly from the end users 
browser to the Amdatu server.
         if (request.getCookies() != null) {
             for (Cookie cookie : request.getCookies()) {
                 if (TokenProvider.TOKEN_COOKIE_NAME.equals(cookie.getName())) {
@@ -251,6 +256,16 @@
                 }
             }
         }
+        
+        // Use case 2: When requests are not send from a browser (for example 
calls to gadgets.ui.makeRequest
+        // proxied via an openSocial container) the token can be send in the 
Authorization header (like Basic 
+        // and Digest HTTP authentication).
+        String authHeader = request.getHeader("Authorization");
+        if (authHeader != null && !authHeader.isEmpty()) {
+            if (authHeader.startsWith(AUTHORIZATION_HEADER + " ")) {
+                return authHeader.substring(authHeader.indexOf(" ") + 1);
+            }
+        }
         return null;
     }
 }

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/jsp/UserAdminGadget.jsp
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/jsp/UserAdminGadget.jsp
      (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/jsp/UserAdminGadget.jsp
      Thu Dec 23 15:23:17 2010
@@ -12,14 +12,17 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <Module>
   <ModulePrefs 
-    title="Amdatu Role Admin Gadget" 
-    description="Role and Group management"
-    author="Ivo Ladage-van Doorn"
-    screenshot="${gadgetBaseUrl}/static/images/useradmin.png"
-    icon="${gadgetBaseUrl}/static/images/useradmin.png" 
-    height="400">
+      title="Amdatu Role Admin Gadget" 
+      description="Role and Group management"
+      author="Ivo Ladage-van Doorn"
+      screenshot="${gadgetBaseUrl}/static/images/useradmin.png"
+      icon="${gadgetBaseUrl}/static/images/useradmin.png" 
+      height="400">
+      
     <Require feature="osapi"/>       
     <Require feature="dynamic-height"/>
+    
+    <Locale messages="${gadgetBaseUrl}/static/labels/useradmin_ALL_ALL.xml" />
   </ModulePrefs>
   <Content type="html">
     <![CDATA[
@@ -32,13 +35,15 @@
     <script type="text/javascript" 
src="${jsBaseUrl}/useradmin_rest.js"></script>
     <script type="text/javascript" src="${jsBaseUrl}/tabs.js"></script>
     <script type="text/javascript" src="${jsBaseUrl}/select_role.js"></script>
+    <script type="text/javascript" src="${jsBaseUrl}/util.js"></script>
+    <script type="text/javascript" src="${jsBaseUrl}/useradmin.js"></script>
     
     <p>
       <div id="container">
         <ul class="menu">
-          <li id="users_tab" class="active">Users</li>
-          <li id="groups_tab">Groups</li>
-          <li id="members_tab" style="display:none;visibility:hidden">Select 
role to add</li>
+          <li id="users_tab" class="active">__MSG_users__</li>
+          <li id="groups_tab">__MSG_groups__</li>
+          <li id="members_tab" 
style="display:none;visibility:hidden">__MSG_members__</li>
         </ul>
         
         <span class="clear"></span>
@@ -46,17 +51,17 @@
         <div class="content users_tab">
           <div id="user"></div><br/>
           
-          <input type="button" value="Add user" id="add_user_button" 
onclick="javascript:showNewRole();"/>
+          <input type="button" value="__MSG_add_user__" id="add_user_button" 
onclick="javascript:showNewRole();"/>
 
           <fieldset id="user_details" style="display:none;visibility:hidden">
-            <legend id="user_details_legend">Details</legend>
+            <legend id="user_details_legend">__MSG_details__</legend>
               <table width="95%">
-                <tr><td>Username</td><td><input type="edit" id="user_name" 
value="" disabled="disabled" 
onkeyup="javascript:validateNonEmpty('user_name');"/></td></tr>
-                <tr><td id="password_label">New password</td><td><input 
type="password" id="password" value="" 
onkeyup="javascript:validateNonEmpty('password');"/></td></tr>
-                <tr><td valign="top">Implied roles</td><td 
id="implied_roles"></td></tr>
+                <tr><td>__MSG_username__</td><td><input type="edit" 
id="user_name" value="" disabled="disabled" 
onkeyup="javascript:validateNonEmpty('user_name', 'password');"/></td></tr>
+                <tr><td 
id="password_label">__MSG_new_password__</td><td><input type="password" 
id="password" value="" onkeyup="javascript:validateNonEmpty('user_name', 
'password');"/></td></tr>
+                <tr id="implied_roles_row"><td>__MSG_implied_roles__</td><td 
id="implied_roles"></td></tr>
               </table>
-              <input type="submit" id="user_save" value="Save" 
onclick="javascript:saveRole();" disabled="disabled"/>
-              <input type="button" value="Cancel" 
onclick="javascript:showAddButton();"/>
+              <input type="submit" id="user_save" value="__MSG_save__" 
onclick="javascript:saveRole();" disabled="disabled"/>
+              <input type="button" value="__MSG_cancel__" 
onclick="javascript:showAddButton();"/>
               <input type="hidden" id="user_method" value="update"/>
               <div id="user_message"></div>
           </fieldset>          
@@ -65,17 +70,17 @@
         <div class="content groups_tab">
           <div id="group"></div><br/>
           
-          <input type="button" value="Add group" id="add_group_button" 
onclick="javascript:showNewRole();"/>
+          <input type="button" value="__MSG_add_group__" id="add_group_button" 
onclick="javascript:showNewRole();"/>
           
           <fieldset id="group_details" style="display:none;visibility:hidden">
-            <legend id="group_details_legend">Details</legend>
+            <legend id="group_details_legend">__MSG_details__</legend>
               <table width="95%">
-                <tr><td>Group name</td><td><input type="edit" id="group_name" 
value="" disabled="disabled" 
onkeyup="javascript:validateNonEmpty('group_name');"/></td></tr>
-                <tr id="required_members_row"><td valign="top">Required 
members</td><td valign="top" id="required_members"></td></tr>
-                <tr id="basic_members_row"><td valign="top">Basic 
members</td><td valign="top" id="basic_members"></td></tr>
+                <tr><td>__MSG_group_name__</td><td><input type="edit" 
id="group_name" value="" disabled="disabled" 
onkeyup="javascript:validateNonEmpty('group_name');"/></td></tr>
+                <tr 
id="required_members_row"><td>__MSG_required_members__</td><td 
id="required_members"></td></tr>
+                <tr id="basic_members_row"><td>__MSG_basic_members__</td><td 
id="basic_members"></td></tr>
               </table>
-              <input type="submit" id="group_save" value="Save" 
onclick="javascript:saveRole();" disabled="disabled"/>
-              <input type="button" value="Cancel" 
onclick="javascript:showAddButton();"/>
+              <input type="submit" id="group_save" value="__MSG_save__" 
onclick="javascript:saveRole();" disabled="disabled"/>
+              <input type="button" value="__MSG_cancel__" 
onclick="javascript:showAddButton();"/>
               <input type="hidden" id="group_method" value="update"/>
               <div id="group_message"></div>
           </fieldset>
@@ -89,369 +94,9 @@
     </p>
     
     <script type="text/javascript"> 
-      var restUrl = "${restUrl}/users/users?maxResults=5";
-      var currentUrl;
-      var currentUsersUrl;
-      var currentGroupsUrl;
-      var selectedRole;
-      var addToBasicMembers;
-      
-      // Callback function invoked when roles have been loaded
-      function onRolesLoaded(response) {
-        var jsonData = response.data["searchresult"];
-        var pageStartIndex = jsonData["pageStartIndex"];
-        var pageEndIndex = jsonData["pageEndIndex"];
-        var resultCount = jsonData["resultCount"];
-        var pageCount = jsonData["pageCount"];
-        
-        var links = jsonData["links"];
-        for (i=0; i<links.length; i++) {
-          if (links[i]["rel"] == "Start") {
-             var start = getNavigationLink("start.gif", links[i]["href"], 
"onRolesLoaded");
-          } else if (links[i]["rel"] == "Prev") {
-             var prev = getNavigationLink("previous.gif", links[i]["href"], 
"onRolesLoaded");
-          } else if (links[i]["rel"] == "Next") {
-             var next = getNavigationLink("next.gif", links[i]["href"], 
"onRolesLoaded");
-          } else if (links[i]["rel"] == "End") {
-             var end = getNavigationLink("end.gif", links[i]["href"], 
"onRolesLoaded");
-          } else if (links[i]["rel"] == "Alternate") {
-             currentUrl = "${baseUrl}" + links[i]["href"];
-             if (currentView == "user") {
-              currentUsersUrl = currentUrl;
-             } else {
-              currentGroupsUrl = currentUrl;
-             }
-          } 
-        }
-        
-        var html = "";
-        
-        // First add the table header
-        var roles = ensureArray(jsonData["roles"]);
-        if (roles) {
-          html += "<table class='stripeMe'>";
-          html += "<tr><th width='80%'>" + currentView + " name</th><th 
width='20%'>Delete</th></tr>";    
-          for (i=0; i<roles.length; i++) {
-            var role = roles[i];
-            var link = role["link"].href;
-            var editRole = " onclick=\"javascript:editRole('" + escape(link) + 
"');\"";
-            var deleteRole = " onclick=\"javascript:confirmDeleteRole('" + 
escape(link) + "', '" + escape(role["name"]) + "');\"";
-            html += "<tr><td><a href='#'" + editRole + ">" + role["name"] + 
"</a></td>";
-            html += "<td align='center'><a href='#'><img 
src='/gadget/useradmin/static/images/remove.gif'" + deleteRole + 
"/></a></td></tr>";
-          }
-          html += "</table></center></p>";
-        }
-        html += "<p><center><table><tr>";
-        html += "<td>" + start + "</td>";
-        html += "<td>" + prev + "</td>";
-        html += "<td><center>Displaying results <b>" + pageStartIndex + "-" + 
pageEndIndex + "<b> of <b>" + resultCount + "</b></center></td>";
-        html += "<td>" + next + "</td>";
-        html += "<td>" + end + "</td></table>"; 
-        
-        var resultDiv;
-        if (currentView == "user") {
-          resultDiv = document.getElementById("user");
-        } else {
-          resultDiv = document.getElementById("group");
-        }
-        resultDiv.innerHTML = html;
-        
-        // make the table zebra-style
-        $(".stripeMe tr").mouseover(function() {$(this).addClass("over");});
-        $(".stripeMe tr").mouseout(function() {$(this).removeClass("over");});
-        $(".stripeMe tr:even").addClass("alt");
-
-        gadgets.window.adjustHeight();
-      }          
-      
-      // Callback function invoked when one specific role details have been 
loaded
-      function onRoleLoaded(response) {
-        if (response.rc == 200) {
-          var role = response.data["roles"];  
-          document.getElementById(currentView + '_name').value = role["name"];
-          if (currentView == "user") {
-            var roles = ensureArray(role["impliedRoles"]);
-            var html = "<table><tbody>";
-            for (i=0; i<roles.length; i++) {
-              html += "<tr><td>" + roles[i] + "</td></tr>";
-            }
-            html += "</table>";
-            document.getElementById('implied_roles').innerHTML = html;
-          } else {
-            selectedRole = role["name"];
-            var requiredMembers = ensureArray(role["requiredMembers"]);
-            var html = "<table><tbody>";
-            html += renderMembers(requiredMembers);
-            html += "<tr><td><input type='button' value='Add' 
onclick='javascript:showAddMember(false);'/></td>";
-            html += "</table>";
-            document.getElementById('required_members').innerHTML = html;
-            
-            var basicMembers = ensureArray(role["basicMembers"]);
-            html = "<table><tbody>";
-            html += renderMembers(basicMembers);
-            html += "<tr><td><input type='button' value='Add' 
onclick='javascript:showAddMember(true);'/></td></tr>";
-            html += "</table>";
-            document.getElementById('basic_members').innerHTML = html;
-          }
-          gadgets.window.adjustHeight();
-         } else if (response.rc == 404) {
-          showError("Role could not be found.");
-        } else {
-          showError(response.errors);
-        }   
-      }
-      
-      function renderMembers(members) {
-        var html = "";
-        for (i=0; i<members.length; i++) {
-          var name = members[i]["name"];
-          html += "<tr><td>" + name + "</td>";
-          var deleteMember = " onclick=\"javascript:confirmDeleteMember('" + 
escape(name) + "');\"";
-          html += "<td><a href='#'><img 
src='/gadget/useradmin/static/images/remove.gif'" + deleteMember + 
"/></td></tr>";
-        }
-        return html;
-      }
-      
-      // Callback function invoked when the password of the user has been 
changed
-      function onPasswordChanged(response) {
-        if (response.rc == 200) {
-          showInfo('Password changed successfully');
-        } else if (response.rc == 404) {
-          showError("Role to update credential for could not be found.");
-        } else {
-          showError(response.errors);
-        } 
-      }
-      
-      // Callback function invoked when the the role has been removed
-      function onRoleDeleted(response) {
-        if (response.rc == 200) {
-          // Role added successfully
-          loadRoles(currentUrl, onRolesLoaded);
-          gadgets.window.adjustHeight();
-        } else if (response.rc == 304) {
-          alert("Role to delete could not be found.");
-        } else {
-          alert("An error occurred while removing role: " + response.errors);
-        } 
-      }
-      
-      function onRoleAdded(response) {
-        if (response.rc == 200) {
-          // Role added successfully
-          showInfo('Role added successfully');
-          loadRoles(currentUrl, onRolesLoaded);
-          gadgets.window.adjustHeight();
-        } else if (response.rc == 304) {
-          showError("A user with this name already exists.");
-        } else {
-          showError(response.errors);
-        }    
-      }
-      
-      function onMemberAdded(response) {
-        if (response.rc == 200) {
-          // Role added successfully
-          showInfo('Member added successfully');
-          var url = escape("${restUrl}/groups/groups/" + 
encodeURIComponent(selectedRole));
-          loadRole(url, onRoleLoaded);
-          gadgets.window.adjustHeight();
-        } else if (response.rc == 304) {
-          showError("Member was already assigned to this role.");
-        } else {
-          showError(response.errors);
-        }    
-      }
-      
-      function onMemberRemoved(response) {
-        if (response.rc == 200) {
-          // Member removed successfully
-          showInfo('Member removed successfully');
-          var url = escape("${restUrl}/groups/groups/" + 
encodeURIComponent(selectedRole));
-          loadRole(url, onRoleLoaded);
-          gadgets.window.adjustHeight();
-        } else if (response.rc == 304) {
-          showError("Member was already removed from this group.");
-        } else {
-          showError(response.errors);
-        }    
-      }
-      
-      function showAddMember(addToBasic) {
-        // Show select role popup
-        addToBasicMembers = addToBasic;
-        show('members_tab');
-        switchToMembersTab();
-        switchToMembersView();
-      }
-      
-      function confirmDeleteMember(role) {
-        var removeFromRole = encodeURIComponent(selectedRole);
-        var removeRole = encodeURIComponent(unescape(role));
-        var url = "${baseUrl}/rest/services/groups/groups/" + removeFromRole + 
"/members/" + removeRole;
-        deleteMember(url, onMemberRemoved);
-      }
-      
-      function onAddMember(role) {
-        var addToRole = encodeURIComponent(selectedRole);
-        var addRole = encodeURIComponent(unescape(role));
-        if (addToBasicMembers) {
-          var url = "${baseUrl}/rest/services/groups/groups/" + addToRole + 
"/basicmembers/" + addRole;
-        } else {
-          var url = "${baseUrl}/rest/services/groups/groups/" + addToRole + 
"/requiredmembers/" + addRole;
-        }
-        addMember(url, onMemberAdded);
-      }
-      
-      function saveRole() {
-        var method = document.getElementById(currentView + "_method").value;
-        var name = encodeURIComponent(document.getElementById(currentView + 
"_name").value);
-        
-        if (currentView == "user") {
-          var newpassword = document.getElementById('password').value
-          var url = "${baseUrl}/rest/services/users/users/" + name;
-          if (method == "update") {
-            url += "/credentials/password";
-            updatePassword(url, onPasswordChanged, newpassword);
-          } else {
-            addRole(url, onRoleAdded);
-          }
-        } else {
-          var url = "${baseUrl}/rest/services/groups/groups/" + name;
-          addRole(url, onRoleAdded);
-        }
-      }
-      
-      function validateNonEmpty(fieldId) {
-        if (document.getElementById(fieldId).value != "") {
-          document.getElementById(currentView + "_save").disabled = "";
-        } else {
-          document.getElementById(currentView + "_save").disabled = "disabled";
-        }
-      }
-      
-      function getNavigationLink(image, href, callback) {
-        var result = "<a href='#'><img src='${imgBaseUrl}/" + image + "' 
onClick='javascript:loadRoles(\"${baseUrl}" + href + "\", " + callback + 
")'/></a>";
-        return result;
-      }
-      
-      function editRole(link) {
-        loadRole(escape('${baseUrl}' + unescape(link)), onRoleLoaded);
-        showEditRole();
-      }
-      
-      function confirmDeleteRole(link, name) {
-        if (confirm('Are you sure you want to delete "' + unescape(name) + 
'"?')) {
-          deleteRole(escape('${baseUrl}' + unescape(link)), onRoleDeleted);
-        }
-      }
-      
-      function showInfo(msg) {
-        if (msg != "") {
-          document.getElementById(currentView + '_message').innerHTML = 
"<p><font color='green'>" + msg + "</font></p>";
-        } else {
-          document.getElementById(currentView + '_message').innerHTML = "";
-        }
-        gadgets.window.adjustHeight();
-      }
-      
-      function showError(msg) {
-        if (msg != "") {
-          document.getElementById(currentView + '_message').innerHTML = 
"<p><font color='red'>" + msg + "</font></p>";
-        } else {
-          document.getElementById(currentView + '_message').innerHTML = "";
-        }
-        gadgets.window.adjustHeight();
-      }
-      
-      function showAddButton() {
-        show('add_' + currentView + '_button');
-        hide(currentView + '_details');
-        gadgets.window.adjustHeight();
-      }
-      
-      function showNewRole() {
-        document.getElementById(currentView + '_details_legend').innerHTML = 
"New " + currentView;
-        document.getElementById(currentView + '_name').value = "";
-        document.getElementById(currentView + '_name').disabled = "";
-        document.getElementById(currentView + '_method').value = "add";
-        
-        if (currentView == "user") {
-          document.getElementById('password_label').innerHTML = "Password";
-          document.getElementById('password').value = "";
-        } else if (currentView == "group") {
-          hide('required_members_row');
-          hide('basic_members_row');
-        }
-        showError("");
-        show(currentView + '_details');
-        hide('add_' + currentView + '_button');
-        gadgets.window.adjustHeight();
-      }
-      
-      function showEditRole() {
-        document.getElementById(currentView + '_details_legend').innerHTML = 
currentView + " details";
-        document.getElementById(currentView + '_name').disabled = "disabled";
-        document.getElementById(currentView + '_method').value = "update";
- 
-        if (currentView == "user") {
-          document.getElementById('password_label').innerHTML = "New password";
-        } else if (currentView == "group") {
-          show('required_members_row');
-          show('basic_members_row');
-        }
-        
-        showError("");
-        show(currentView + '_details');
-        hide('add_' + currentView + '_button');
-        gadgets.window.adjustHeight();
-      }
-      
-      function show(id) {
-        var obj = document.getElementById(id);
-        obj.style.visibility = "";
-        obj.style.display = "";
-      }
-      
-      function hide(id) {
-        var obj = document.getElementById(id);
-        obj.style.visibility = "hidden";
-        obj.style.display = "none";
-      }
-      
-      function switchToUsersView() {
-        restUrl = "${restUrl}/users/users?maxResults=5";
-        currentUrl = currentUsersUrl;
-        loadRoles(restUrl, onRolesLoaded);
-      }
-      
-      function switchToGroupsView() {
-        restUrl = "${restUrl}/groups/groups?maxResults=5";
-        currentUrl = currentGroupsUrl;
-        loadRoles(restUrl, onRolesLoaded);
-      }
-      
-      function switchToMembersView() {
-        restUrl = "${restUrl}/roles/roles?maxResults=10";
-        loadRoles(restUrl, onRolesLoadedForSelection);
-      }
-      
-      function ensureArray(input) {
-        // check if this result is an array
-        if (jQuery.isArray(input)) {
-          return input;
-        }
-        var result = [];
-        if (input != null) {
-          result.push(input);
-        }
-        return result;
-      }
-      
-      $(document).ready(function(){
-        loadRoles(restUrl, onRolesLoaded);
-      });
-      
+      var baseUrl ="${baseUrl}";
+      var restUrl = "${restUrl}";
+      var imgBaseUrl = "${imgBaseUrl}";
     </script>
     ]]>
   </Content>

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/tabs.css
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/tabs.css
  (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/tabs.css
  Thu Dec 23 15:23:17 2010
@@ -1,6 +1,6 @@
 @CHARSET "UTF-8";
 /******* GENERAL RESET *******/
-html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, 
blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em,
+html, body, div, span, applet, object, iframe, p, blockquote, pre, a, abbr, 
acronym, address, big, cite, code, del, dfn, em,
 font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, 
dt, dd, ol, ul, li {
 border:0pt none;
 margin:0pt;

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/useradmin.css
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/useradmin.css
     (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/css/useradmin.css
     Thu Dec 23 15:23:17 2010
@@ -2,6 +2,10 @@
   background: #fff;
 }
 
+table td {
+  vertical-align: top;
+}
+
 table.stripeMe {
   border-collapse: collapse;
   font-size: 1.1em;
@@ -26,7 +30,7 @@
 
 table.stripeMe td * {
   padding: 2px 1px;
-  valign: center;
+  vertical-align: top;
 }
 
 table.stripeMe tr.alt td {

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/select_role.js
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/select_role.js
     (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/select_role.js
     Thu Dec 23 15:23:17 2010
@@ -40,7 +40,8 @@
     html += "<p><center><table><tr>";
     html += "<td>" + start + "</td>";
     html += "<td>" + prev + "</td>";
-    html += "<td><center>Displaying results <b>" + pageStartIndex + "-" + 
pageEndIndex + "<b> of <b>" + resultCount + "</b></center></td>";
+    html += "<td><center>" + prefs.getMsg('results_nav_1') + " <b>" + 
pageStartIndex + "-" + pageEndIndex;
+    html += "</b> " + prefs.getMsg('results_nav_2') + " <b>" + resultCount + 
"</b></center></td>";
     html += "<td>" + next + "</td>";
     html += "<td>" + end + "</td></table>"; 
   }

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/tabs.js
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/tabs.js
    (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/tabs.js
    Thu Dec 23 15:23:17 2010
@@ -39,7 +39,6 @@
   $("div.groups_tab").css("display", "none");
   $("div.members_tab").css("display", "none");
   currentView = "user";
-  switchToUsersView();
 }
 
 function switchToGroupsTab() {

Added: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
       Thu Dec 23 15:23:17 2010
@@ -0,0 +1,385 @@
+var currentUrl;
+var currentUsersUrl;
+var currentGroupsUrl;
+var selectedRole;
+var addToBasicMembers;
+
+var prefs = new gadgets.Prefs();
+    
+// Callback function invoked when roles have been loaded
+function onRolesLoaded(response) {
+  if (response.rc == 200) {
+    var jsonData = response.data["searchresult"];
+    var pageStartIndex = jsonData["pageStartIndex"];
+    var pageEndIndex = jsonData["pageEndIndex"];
+    var resultCount = jsonData["resultCount"];
+    var pageCount = jsonData["pageCount"];
+
+    var links = jsonData["links"];
+    for (i=0; i<links.length; i++) {
+      if (links[i]["rel"] == "Start") {
+         var start = getNavigationLink("start.gif", links[i]["href"], 
"onRolesLoaded");
+      } else if (links[i]["rel"] == "Prev") {
+         var prev = getNavigationLink("previous.gif", links[i]["href"], 
"onRolesLoaded");
+      } else if (links[i]["rel"] == "Next") {
+         var next = getNavigationLink("next.gif", links[i]["href"], 
"onRolesLoaded");
+      } else if (links[i]["rel"] == "End") {
+         var end = getNavigationLink("end.gif", links[i]["href"], 
"onRolesLoaded");
+      } else if (links[i]["rel"] == "Alternate") {
+         currentUrl = baseUrl + links[i]["href"];
+         if (currentView == "user") {
+          currentUsersUrl = currentUrl;
+         } else {
+          currentGroupsUrl = currentUrl;
+         }
+      } 
+    }
+
+    var html = "";
+
+    // First add the table header
+    var roles = ensureArray(jsonData["roles"]);
+    if (roles) {
+      if (currentView == "user") {
+        nameLabel = prefs.getMsg('username');
+      } else {
+        nameLabel = prefs.getMsg('group_name');
+      }
+      html += "<table class='stripeMe'>";
+      html += "<tr><th width='80%'>" + nameLabel + "</th><th width='20%'>" + 
prefs.getMsg('delete') + "</th></tr>";    
+      for (i=0; i<roles.length; i++) {
+        var role = roles[i];
+        var link = role["link"].href;
+        var editRole = " onclick=\"javascript:editRole('" + escape(link) + 
"');\"";
+        var deleteRole = " onclick=\"javascript:confirmDeleteRole('" + 
escape(link) + "', '" + escape(role["name"]) + "');\"";
+        html += "<tr><td><a href='#'" + editRole + ">" + role["name"] + 
"</a></td>";
+        html += "<td align='center'><a href='#'><img 
src='/gadget/useradmin/static/images/remove.gif'" + deleteRole + 
"/></a></td></tr>";
+      }
+      html += "</table></center></p>";
+    }
+    html += "<p><center><table><tr>";
+    html += "<td>" + start + "</td>";
+    html += "<td>" + prev + "</td>";
+    html += "<td><center>" + prefs.getMsg('results_nav_1') + " <b>" + 
pageStartIndex + "-" + pageEndIndex + "</b> ";
+    html += prefs.getMsg('results_nav_2') + " <b>" + resultCount + 
"</b></center></td>";
+    html += "<td>" + next + "</td>";
+    html += "<td>" + end + "</td></table>"; 
+
+    var resultDiv;
+    if (currentView == "user") {
+      resultDiv = document.getElementById("user");
+    } else {
+      resultDiv = document.getElementById("group");
+    }
+    resultDiv.innerHTML = html;
+
+    // make the table zebra-style
+    $(".stripeMe tr").mouseover(function() {$(this).addClass("over");});
+    $(".stripeMe tr").mouseout(function() {$(this).removeClass("over");});
+    $(".stripeMe tr:even").addClass("alt");
+  } else if (response.rc == 401) {
+    hide('add_' + currentView + '_button');
+    var html = "<p><font color='red'>" + prefs.getMsg('unauthorized') + 
"</font></p>";
+    document.getElementById(currentView).innerHTML = html;
+  } else {
+    showError(prefs.getMsg('unexpected_error') + response.errors);
+  }   
+  gadgets.window.adjustHeight();
+}          
+
+// Callback function invoked when one specific role details have been loaded
+function onRoleLoaded(response) {
+  if (response.rc == 200) {
+    var role = response.data["roles"];  
+    document.getElementById(currentView + '_name').value = role["name"];
+    if (currentView == "user") {
+      var roles = ensureArray(role["impliedRoles"]);
+      var html = "<table><tbody>";
+      for (i=0; i<roles.length; i++) {
+        html += "<tr><td>" + roles[i] + "</td></tr>";
+      }
+      html += "</table>";
+      document.getElementById('implied_roles').innerHTML = html;
+    } else {
+      selectedRole = role["name"];
+      var requiredMembers = ensureArray(role["requiredMembers"]);
+      var html = "<table><tbody>";
+      html += renderMembers(requiredMembers);
+      html += "<tr><td><input type='button' value='Add' 
onclick='javascript:showAddMember(false);'/></td>";
+      html += "</table>";
+      document.getElementById('required_members').innerHTML = html;
+
+      var basicMembers = ensureArray(role["basicMembers"]);
+      html = "<table><tbody>";
+      html += renderMembers(basicMembers);
+      html += "<tr><td><input type='button' value='Add' 
onclick='javascript:showAddMember(true);'/></td></tr>";
+      html += "</table>";
+      document.getElementById('basic_members').innerHTML = html;
+    }
+    gadgets.window.adjustHeight();
+  } else if (response.rc == 404) {
+    showError(prefs.getMsg('role_not_found'));
+  } else if (response.rc == 401) {
+    showError(prefs.getMsg('accessdenied'));
+  } else {
+    showError(prefs.getMsg('unexpected_error') + response.errors);
+  }   
+}
+
+function renderMembers(members) {
+  var html = "";
+  for (i=0; i<members.length; i++) {
+    var name = members[i]["name"];
+    html += "<tr><td>" + name + "</td>";
+    var deleteMember = " onclick=\"javascript:confirmDeleteMember('" + 
escape(name) + "');\"";
+    html += "<td><a href='#'><img 
src='/gadget/useradmin/static/images/remove.gif'" + deleteMember + 
"/></td></tr>";
+  }
+  return html;
+}
+
+// Callback function invoked when the password of the user has been changed
+function onPasswordChanged(response) {
+  if (response.rc == 200) {
+    showInfo(prefs.getMsg('password_changed'));
+  } else if (response.rc == 404) {
+    showError(prefs.getMsg('role_not_found'));
+  } else if (response.rc == 401) {
+    showError(prefs.getMsg('accessdenied'));
+  } else {
+    showError(prefs.getMsg('unexpected_error') + response.errors);
+  } 
+}
+
+// Callback function invoked when the the role has been removed
+function onRoleDeleted(response) {
+  if (response.rc == 200) {
+    // Role added successfully
+    loadRoles(currentUrl, onRolesLoaded);
+    gadgets.window.adjustHeight();
+  } else if (response.rc == 304) {
+    alert(prefs.getMsg('role_not_found'));
+  } else if (response.rc == 401) {
+    showError(prefs.getMsg('accessdenied'));
+  } else {
+    alert(prefs.getMsg('unexpected_error') + response.errors);
+  } 
+}
+
+function onRoleAdded(response) {
+  if (response.rc == 200) {
+    // Role added successfully
+    showInfo(prefs.getMsg('role_added'));
+    loadRoles(currentUrl, onRolesLoaded);
+    gadgets.window.adjustHeight();
+  } else if (response.rc == 304) {
+    showError(prefs.getMsg('role_already_exists'));
+  } else if (response.rc == 401) {
+    showError(prefs.getMsg('accessdenied'));
+  } else {
+    showError(prefs.getMsg('unexpected_error') + response.errors);
+  }    
+}
+
+function onMemberAdded(response) {
+  if (response.rc == 200) {
+    // Role added successfully
+    showInfo(prefs.getMsg('member_added'));
+    var url = escape(restUrl + "/groups/groups/" + 
encodeURIComponent(selectedRole));
+    loadRole(url, onRoleLoaded);
+    gadgets.window.adjustHeight();
+  } else if (response.rc == 304) {
+    showError(prefs.getMsg('member_already_assigned'));
+  } else if (response.rc == 401) {
+    showError(prefs.getMsg('accessdenied'));
+  } else {
+    showError(prefs.getMsg('unexpected_error') + response.errors);
+  }    
+}
+
+function onMemberRemoved(response) {
+  if (response.rc == 200) {
+    // Member removed successfully
+    showInfo(prefs.getMsg('member_removed'));
+    var url = escape(restUrl + "/groups/groups/" + 
encodeURIComponent(selectedRole));
+    loadRole(url, onRoleLoaded);
+    gadgets.window.adjustHeight();
+  } else if (response.rc == 304) {
+    showError(prefs.getMsg('member_already_removed'));
+  } else if (response.rc == 401) {
+    showError(prefs.getMsg('accessdenied'));
+  } else {
+    showError(prefs.getMsg('unexpected_error') + response.errors);
+  }    
+}
+
+function showAddMember(addToBasic) {
+  // Show select role popup
+  addToBasicMembers = addToBasic;
+  show('members_tab');
+  switchToMembersTab();
+  switchToMembersView();
+}
+
+function confirmDeleteMember(role) {
+  var removeFromRole = encodeURIComponent(selectedRole);
+  var removeRole = encodeURIComponent(unescape(role));
+  var url = baseUrl + "/rest/services/groups/groups/" + removeFromRole + 
"/members/" + removeRole;
+  deleteMember(url, onMemberRemoved);
+}
+
+function onAddMember(role) {
+  var addToRole = encodeURIComponent(selectedRole);
+  var addRole = encodeURIComponent(unescape(role));
+  if (addToBasicMembers) {
+    var url = baseUrl + "/rest/services/groups/groups/" + addToRole + 
"/basicmembers/" + addRole;
+  } else {
+    // Sanity check: if you add a required member to Administrators, only this 
role has permission
+    // for user amdin!
+    if (addToRole == 'Administrators') {
+      var alertMsg = prefs.getMsg('admin_alert');
+      alertMsg = alertMsg.replace("%s",  addRole);
+      if (!confirm(alertMsg)) {
+        return;
+      }
+    }
+    var url = baseUrl + "/rest/services/groups/groups/" + addToRole + 
"/requiredmembers/" + addRole;
+  }
+  addMember(url, onMemberAdded);
+}
+
+function saveRole() {
+  var method = document.getElementById(currentView + "_method").value;
+  var name = encodeURIComponent(document.getElementById(currentView + 
"_name").value);
+
+  if (currentView == "user") {
+    var newpassword = document.getElementById('password').value
+    var url = baseUrl + "/rest/services/users/users/" + name;
+    if (method == "update") {
+      url += "/credentials/password";
+      updatePassword(url, onPasswordChanged, newpassword);
+    } else {
+      addRole(url, onRoleAdded);
+    }
+  } else {
+    var url = baseUrl + "/rest/services/groups/groups/" + name;
+    addRole(url, onRoleAdded);
+  }
+}
+
+function validateNonEmpty(fieldId1, fieldId2) {
+  if (document.getElementById(fieldId1).value != "") {
+    if (!fieldId2 || document.getElementById(fieldId2).value != "") {
+      document.getElementById(currentView + "_save").disabled = "";
+      return;
+    }
+  }
+  document.getElementById(currentView + "_save").disabled = "disabled";
+}
+
+function getNavigationLink(image, href, callback) {
+  var result = "<a href='#'><img src='" + imgBaseUrl + "/" + image + "' 
onClick='javascript:loadRoles(\"" + baseUrl + href + "\", " + callback + 
")'/></a>";
+  return result;
+}
+
+function editRole(link) {
+  loadRole(escape(baseUrl + unescape(link)), onRoleLoaded);
+  showEditRole();
+}
+
+function confirmDeleteRole(link, name) {
+  var confirmMsg = prefs.getMsg('confirm_delete');
+  confirmMsg = confirmMsg.replace("%s",  unescape(name));
+  if (confirm(confirmMsg)) {
+    deleteRole(escape(baseUrl + unescape(link)), onRoleDeleted);
+  }
+}
+
+function showInfo(msg) {
+  if (msg != "") {
+    document.getElementById(currentView + '_message').innerHTML = "<p><font 
color='green'>" + msg + "</font></p>";
+  } else {
+    document.getElementById(currentView + '_message').innerHTML = "";
+  }
+  gadgets.window.adjustHeight();
+}
+
+function showError(msg) {
+  if (msg != "") {
+    document.getElementById(currentView + '_message').innerHTML = "<p><font 
color='red'>" + msg + "</font></p>";
+  } else {
+    document.getElementById(currentView + '_message').innerHTML = "";
+  }
+  gadgets.window.adjustHeight();
+}
+
+function showAddButton() {
+  show('add_' + currentView + '_button');
+  hide(currentView + '_details');
+  gadgets.window.adjustHeight();
+}
+
+function showNewRole() {
+  if (currentView == "user") {
+    var newLabel = prefs.getMsg('new_user');
+  } else {
+    var newLabel = prefs.getMsg('new_group');
+  }
+  document.getElementById(currentView + '_details_legend').innerHTML = 
newLabel;
+  document.getElementById(currentView + '_name').value = "";
+  document.getElementById(currentView + '_name').disabled = "";
+  document.getElementById(currentView + '_method').value = "add";
+
+  if (currentView == "user") {
+    document.getElementById('password_label').innerHTML =  
prefs.getMsg('password');
+    document.getElementById('password').value = "";
+    hide('implied_roles_row');
+  } else if (currentView == "group") {
+    hide('required_members_row');
+    hide('basic_members_row');
+  }
+  showError("");
+  show(currentView + '_details');
+  hide('add_' + currentView + '_button');
+  gadgets.window.adjustHeight();
+}
+
+function showEditRole() {
+  document.getElementById(currentView + '_details_legend').innerHTML = 
prefs.getMsg('details');
+  document.getElementById(currentView + '_name').disabled = "disabled";
+  document.getElementById(currentView + '_method').value = "update";
+
+  if (currentView == "user") {
+    document.getElementById('password_label').innerHTML = 
prefs.getMsg('new_password');
+    document.getElementById('password').value = "";
+    show('implied_roles_row');
+  } else if (currentView == "group") {
+    show('required_members_row');
+    show('basic_members_row');
+  }
+
+  showError("");
+  show(currentView + '_details');
+  hide('add_' + currentView + '_button');
+  gadgets.window.adjustHeight();
+}
+
+function switchToUsersView() {
+  var url = restUrl + "/users/users?maxResults=5";
+  currentUrl = currentUsersUrl;
+  loadRoles(url, onRolesLoaded);
+}
+
+function switchToGroupsView() {
+  var url = restUrl + "/groups/groups?maxResults=5";
+  currentUrl = currentGroupsUrl;
+  loadRoles(url, onRolesLoaded);
+}
+
+function switchToMembersView() {
+  var url = restUrl + "/roles/roles?maxResults=10";
+  loadRoles(url, onRolesLoadedForSelection);
+}
+
+$(document).ready(function(){
+  loadRoles(restUrl + "/users/users?maxResults=5", onRolesLoaded);
+});

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin_rest.js
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin_rest.js
  (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin_rest.js
  Thu Dec 23 15:23:17 2010
@@ -3,6 +3,7 @@
   var params = {};
   params[gadgets.io.RequestParameters.CONTENT_TYPE] = 
gadgets.io.ContentType.JSON;
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
+  addAmdatuToken(params);
   url = addNoCache(url);
   gadgets.io.makeRequest(url, callback, params);
 }
@@ -12,6 +13,7 @@
   var params = {};
   params[gadgets.io.RequestParameters.CONTENT_TYPE] = 
gadgets.io.ContentType.JSON;
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
+  addAmdatuToken(params);
   url = addNoCache(unescape(url));  
   gadgets.io.makeRequest(url, callback, params);
 }
@@ -21,6 +23,7 @@
   var params = {};
   params[gadgets.io.RequestParameters.CONTENT_TYPE] = 
gadgets.io.ContentType.JSON;
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
+  addAmdatuToken(params);
   var postdata = {value : newpassword};
   params[gadgets.io.RequestParameters.POST_DATA] = 
gadgets.io.encodeValues(postdata);
   url = addNoCache(url);  
@@ -31,6 +34,7 @@
  function addRole(url, callback) {
   var params = {};
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.PUT;
+  addAmdatuToken(params);
   url = addNoCache(url);  
   gadgets.io.makeRequest(url, callback, params);
 }
@@ -39,6 +43,7 @@
  function addMember(url, callback) {
   var params = {};
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.PUT;
+  addAmdatuToken(params);
   url = addNoCache(url);  
   gadgets.io.makeRequest(url, callback, params);
 }
@@ -47,6 +52,7 @@
 function deleteMember(url, callback) {
   var params = {};
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.DELETE;
+  addAmdatuToken(params);
   url = addNoCache(url);  
   gadgets.io.makeRequest(url, callback, params);
 }
@@ -56,6 +62,7 @@
   var params = {};
   params[gadgets.io.RequestParameters.CONTENT_TYPE] = 
gadgets.io.ContentType.JSON;
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.DELETE;
+  addAmdatuToken(params);
   url = addNoCache(unescape(url));
   gadgets.io.makeRequest(url, callback, params);
 }
@@ -68,4 +75,17 @@
     url += "&nocache=" + ts;
   }
   return url;
+}
+
+// Each invocation of gadgets.io.makeRequest is procies via the OpenSocial 
container 
+// to the REST service. For security reasons, it does not pass cookies to this 
REST 
+// service and so, since our REST service verifies authorization against 
UserAdmin, 
+// the REST service will deny all calls. The site authentication token needs 
thus
+// to be passed from the OpenSocial container to the REST service, which is 
what
+// happens here.
+function addAmdatuToken(params) {
+  var token = getCookie("amdatu_token");
+  if (token != null) {
+    params[gadgets.io.RequestParameters.HEADERS] = {"Authorization" : "Amdatu 
" + token}; 
+  }
 }
\ No newline at end of file

Added: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/util.js
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/util.js
    Thu Dec 23 15:23:17 2010
@@ -0,0 +1,32 @@
+function ensureArray(input) {
+  // check if this result is an array
+  if (jQuery.isArray(input)) {
+    return input;
+  }
+  var result = [];
+  if (input != null) {
+    result.push(input);
+  }
+  return result;
+}
+
+function show(id) {
+  var obj = document.getElementById(id);
+  obj.style.visibility = "";
+  obj.style.display = "";
+}
+
+function hide(id) {
+  var obj = document.getElementById(id);
+  obj.style.visibility = "hidden";
+  obj.style.display = "none";
+}
+
+function getCookie(cookieName) {
+  var results = document.cookie.match ( '(^|;) ?' + cookieName + 
'=([^;]*)(;|$)' );
+  if (results) {
+    return (unescape(results[2]));
+  } else {
+    return null;
+  }
+}

Added: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/labels/useradmin_ALL_ALL.xml
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/labels/useradmin_ALL_ALL.xml
  Thu Dec 23 15:23:17 2010
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<messagebundle>
+  <msg name="users">Users</msg>
+  <msg name="groups">Groups</msg>
+  <msg name="members">Select role to add</msg>
+  
+  <msg name="new_user">New user</msg>
+  <msg name="add_user">Add user</msg>
+  <msg name="new_group">New group</msg>
+  <msg name="add_group">Add group</msg>
+  <msg name="username">Username</msg>
+  <msg name="password">Password</msg>
+  <msg name="new_password">New password</msg>
+  <msg name="implied_roles">Implied roles</msg>
+  <msg name="details">Details</msg>
+  
+  <msg name="group_name">Group name</msg> 
+  <msg name="required_members">Required members</msg> 
+  <msg name="basic_members">Basic members</msg> 
+  
+  <msg name="save">Save</msg>  
+  <msg name="cancel">Cancel</msg> 
+  <msg name="delete">Delete</msg> 
+  
+  <msg name="results_nav_1">Displaying results</msg>
+  <msg name="results_nav_2">of</msg>
+  <msg name="role_added">Role added successfully.</msg>
+  <msg name="role_not_found">Role could not be found.</msg>
+  <msg name="role_already_exists">A role with this name already exists.</msg> 
+  <msg name="member_added">Member added successfully</msg>
+  <msg name="member_removed">Member removed successfully.</msg>
+  <msg name="member_already_removed">Member was already removed from this 
group.</msg>
+  <msg name="member_already_assigned">Member was already assigned to this 
role.</msg> 
+  <msg name="password_changed">Password changed successfully</msg>
+  <msg name="unauthorized">You do not have authorization to manage users and 
groups.</msg>
+  <msg name="accessdenied">You do not have proper authorization to perform 
this action.</msg>
+  <msg name="unexpected_error">An unexpected error has occurred: </msg>
+  
+  <msg name="confirm_delete">Are you sure you want to delete '%s'?</msg>
+  <msg name="admin_alert">If you add the required member '%s' to this group, 
only this role will have permission to manage users and groups. Are you sure 
you want to do this?</msg>
+</messagebundle>
\ No newline at end of file

Modified: trunk/amdatu-authorization/useradmin-rest/pom.xml
==============================================================================
--- trunk/amdatu-authorization/useradmin-rest/pom.xml   (original)
+++ trunk/amdatu-authorization/useradmin-rest/pom.xml   Thu Dec 23 15:23:17 2010
@@ -38,7 +38,13 @@
       <artifactId>utilities</artifactId>
       <version>${platform.version}</version>
       <scope>compile</scope>
-    </dependency>    
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.authentication</groupId>
+      <artifactId>tokenprovider</artifactId>
+      <version>${platform.version}</version>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
   
   <build>

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
 (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
 Thu Dec 23 15:23:17 2010
@@ -16,6 +16,7 @@
  */
 package org.amdatu.authorization.useradmin.rest.osgi;
 
+import org.amdatu.authentication.tokenprovider.TokenProvider;
 import org.amdatu.authorization.useradmin.rest.service.GroupsResource;
 import org.amdatu.authorization.useradmin.rest.service.RolesResource;
 import org.amdatu.authorization.useradmin.rest.service.UsersResource;
@@ -45,6 +46,7 @@
             .setInterface(RESTService.class.getName(), null)
             .setImplementation(UsersResource.class)
             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
             
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))); 
  
 
         // Create the groups resource service and register it as REST service
@@ -52,6 +54,7 @@
             .setInterface(RESTService.class.getName(), null)
             .setImplementation(GroupsResource.class)
             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
             
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true)));
         
         // Create the groups resource service and register it as REST service
@@ -59,6 +62,7 @@
             .setInterface(RESTService.class.getName(), null)
             .setImplementation(RolesResource.class)
             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
             
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))); 
       
     }
 

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
 (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
 Thu Dec 23 15:23:17 2010
@@ -16,6 +16,7 @@
  */
 package org.amdatu.authorization.useradmin.rest.service;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
@@ -24,11 +25,10 @@
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import org.amdatu.web.rest.jaxrs.RESTService;
 import org.osgi.service.useradmin.Group;
 import org.osgi.service.useradmin.Role;
 
@@ -46,7 +46,7 @@
  * @author ivol
  */
 @Path("groups")
-public class GroupsResource extends ResourceBase implements RESTService {
+public class GroupsResource extends ResourceBase {
     /**
      * This method can be used to check the availability of the Groups 
management service.
      * @return The text "UserAdmin Groups management service online"
@@ -56,7 +56,7 @@
     public String status() {
         return "UserAdmin Groups management service online";
     } 
-    
+
     /**
      * Returns all groups that match the specified filter options. This method 
can be invoked by making the following
      * REST call:<code><pre>
@@ -90,9 +90,13 @@
     @GET
     @Produces({MediaType.APPLICATION_JSON})
     public Response getGroups(@QueryParam("filter") final String filter,
-            @QueryParam("sortOrder") final String sortOrder,
-            @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
-            @DefaultValue("50") @QueryParam("maxResults") final int 
maxResults) {
+        @QueryParam("sortOrder") final String sortOrder,
+        @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
+        @DefaultValue("50") @QueryParam("maxResults") final int maxResults, 
+        @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.getRoles(filter, sortOrder, startIndex, maxResults, 
Role.GROUP);
     }
 
@@ -115,7 +119,10 @@
     @GET
     @Path("{name}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response getGroup(@PathParam("name") final String name) {
+    public Response getGroup(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.getRole(name, Role.GROUP);
     }
 
@@ -132,10 +139,13 @@
     @PUT
     @Path("{name}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response createGroup(@PathParam("name") final String name) {
+    public Response createGroup(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.createRole(name, Role.GROUP);
     }
-    
+
     /**
      * Sets a credential for the group with the specified name. This method 
can be invoked by making the following REST
      * call: <code><pre>
@@ -151,10 +161,13 @@
     @Path("{name}/credentials/{key}")
     @Produces({MediaType.APPLICATION_JSON})
     public Response setCredential(@PathParam("name") final String name,
-            @PathParam("key") final String key, @QueryParam("value") final 
String value) {
+        @PathParam("key") final String key, @QueryParam("value") final String 
value, @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return setCredential(name, key, value, Role.GROUP);
     }  
-    
+
     /**
      * Sets a property for the group with the specified name. This method can 
be invoked by making the following REST
      * call: <code><pre>
@@ -170,7 +183,10 @@
     @Path("{name}/properties/{key}")
     @Produces({MediaType.APPLICATION_JSON})
     public Response setProperty(@PathParam("name") final String name,
-            @PathParam("key") final String key, @QueryParam("value") final 
String value) {
+        @PathParam("key") final String key, @QueryParam("value") final String 
value, @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return setProperty(name, key, value, Role.USER);
     }    
 
@@ -189,7 +205,10 @@
     @Path("{name}/basicmembers/{memberName}")
     @Produces({MediaType.APPLICATION_JSON})
     public Response addBasicMember(@PathParam("name") final String name,
-            @PathParam("memberName") final String memberName) {
+        @PathParam("memberName") final String memberName, @Context final 
HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return addMember(name, memberName, false);
     }
 
@@ -208,7 +227,10 @@
     @Path("{name}/requiredmembers/{memberName}")
     @Produces({MediaType.APPLICATION_JSON})
     public Response addRequiredMember(@PathParam("name") final String name,
-            @PathParam("memberName") final String memberName) {
+        @PathParam("memberName") final String memberName, @Context final 
HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return addMember(name, memberName, true);
     }
 
@@ -224,7 +246,10 @@
     @DELETE
     @Path("{name}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response removeGroup(@PathParam("name") final String name) {
+    public Response removeGroup(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.removeRole(name, Role.GROUP);
     }
 
@@ -241,7 +266,11 @@
     @DELETE
     @Path("{name}/members/{memberName}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response removeMember(@PathParam("name") final String name, 
@PathParam("memberName") final String memberName) {
+    public Response removeMember(@PathParam("name") final String name, 
@PathParam("memberName") final String memberName, 
+        @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         Role role = m_userAdmin.getRole(name);
         Role member = m_userAdmin.getRole(memberName);
         if (role != null && role.getType() == Role.GROUP && member != null) {
@@ -270,7 +299,7 @@
             return buildNotFound();
         }
     }
-    
+
     protected String getBaseUrl() {
         return "/rest/services/groups/groups";
     }

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
   (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
   Thu Dec 23 15:23:17 2010
@@ -21,12 +21,17 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.CacheControl;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
+import org.amdatu.authentication.tokenprovider.InvalidTokenException;
+import org.amdatu.authentication.tokenprovider.TokenProvider;
+import org.amdatu.authentication.tokenprovider.TokenProviderException;
 import org.amdatu.authorization.useradmin.rest.bean.RoleBean;
 import org.amdatu.authorization.useradmin.rest.bean.SearchResultBean;
 import org.amdatu.libraries.utilities.rest.AtomSyndicationLink;
@@ -34,14 +39,19 @@
 import org.json.JSONObject;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.Group;
 import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
 abstract class ResourceBase implements RESTService {
+    // FIXME: Temporary fix for AMDATU-81
+    private static final String DEFAULT_ADMIN_GROUP = "Administrators";
+    
     // Service dependencies injected by the depedency manager
     protected volatile LogService m_logService;
     protected volatile UserAdmin m_userAdmin;
+    protected volatile TokenProvider m_tokenProvider;
 
     // Disable HTTP caching in this REST interface
     private static CacheControl m_cacheControl;
@@ -99,6 +109,10 @@
             Collections.sort(filteredRoles, userComparator);
 
             // Now filter from startIndex - endIndex
+            if (startIndex > filteredRoles.size()) {
+                // Start index out of range, shift!
+                startIndex = Math.max(0, startIndex - maxResults);
+            }
             List<Role> roleRange = new ArrayList<Role>();
             for (int i = (startIndex - 1); i < (startIndex + maxResults - 1) 
&& i < filteredRoles.size(); i++) {
                 roleRange.add(filteredRoles.get(i));
@@ -327,4 +341,39 @@
     }
 
     protected abstract String getBaseUrl();
+    
+    // FIXME: Temporary fix for AMDATU-81. Until AMDATU-230 has been fixed we 
need to make a
+    // quick fix, not having any form of authorization is simply not 
acceptable. For now
+    // we check if the user is logged in and in the "Administrators" role. 
This role is 
+    // hard coded.
+    protected boolean isAuthorized(HttpServletRequest request) {
+        String token = m_tokenProvider.getTokenFromRequest(request);
+        if (token != null) {
+            try {
+                Map<String, String> attributes = 
m_tokenProvider.verifyToken(token);
+                if (attributes.containsKey(TokenProvider.USERNAME)) {
+                    String userName = attributes.get(TokenProvider.USERNAME);
+                    if (userName != null && !userName.isEmpty()) {
+                        User user = (User) m_userAdmin.getRole(userName);
+                        if (user != null) {
+                            return 
m_userAdmin.getAuthorization(user).hasRole(DEFAULT_ADMIN_GROUP);
+                        }
+                    }
+                }               
+            }
+            catch (TokenProviderException e) {
+                // Ignore invalid tokens
+            }
+            catch (InvalidTokenException e) {
+                // Ignore invalid tokens
+            }
+        }
+        return false;
+    }
+    
+    public void fix() {
+        Role role = m_userAdmin.getRole("Administrator");
+        Group group = (Group) m_userAdmin.getRole(DEFAULT_ADMIN_GROUP);
+        group.addMember(role);
+    }
 }

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
  (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
  Thu Dec 23 15:23:17 2010
@@ -16,11 +16,13 @@
  */
 package org.amdatu.authorization.useradmin.rest.service;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -62,7 +64,11 @@
             @QueryParam("filter") final String filter,
             @QueryParam("sortOrder") final String sortOrder,
             @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
-            @DefaultValue("50") @QueryParam("maxResults") final int 
maxResults) {
+            @DefaultValue("50") @QueryParam("maxResults") final int maxResults,
+            @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.getRoles(filter, sortOrder, startIndex, maxResults, 
Role.ROLE);
     }
 

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java
  (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java
  Thu Dec 23 15:23:17 2010
@@ -16,6 +16,7 @@
  */
 package org.amdatu.authorization.useradmin.rest.service;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.FormParam;
@@ -26,10 +27,10 @@
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import org.amdatu.web.rest.jaxrs.RESTService;
 import org.osgi.service.useradmin.Role;
 
 /**
@@ -78,7 +79,11 @@
             @QueryParam("filter") final String filter,
             @QueryParam("sortOrder") final String sortOrder,
             @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
-            @DefaultValue("50") @QueryParam("maxResults") final int 
maxResults) {
+            @DefaultValue("50") @QueryParam("maxResults") final int 
maxResults, 
+            @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.getRoles(filter, sortOrder, startIndex, maxResults, 
Role.USER);
     }
     
@@ -99,7 +104,10 @@
     @GET
     @Path("{name}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response getUser(@PathParam("name") final String name) {
+    public Response getUser(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.getRole(name, Role.USER);
     }
     
@@ -116,7 +124,10 @@
     @PUT
     @Path("{name}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response createUser(@PathParam("name") final String name) {
+    public Response createUser(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.createRole(name, Role.USER);
     }
     
@@ -135,7 +146,10 @@
     @Path("{name}/credentials/{key}")
     @Produces({MediaType.APPLICATION_JSON})
     public Response setCredential(@PathParam("name") final String name,
-            @PathParam("key") final String key, @FormParam("value") final 
String value) {
+            @PathParam("key") final String key, @FormParam("value") final 
String value, @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return setCredential(name, key, value, Role.USER);
     }  
     
@@ -154,7 +168,10 @@
     @Path("{name}/properties/{key}")
     @Produces({MediaType.APPLICATION_JSON})
     public Response setProperty(@PathParam("name") final String name,
-            @PathParam("key") final String key, @FormParam("value") final 
String value) {
+            @PathParam("key") final String key, @FormParam("value") final 
String value, @Context final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return setProperty(name, key, value, Role.USER);
     }    
         
@@ -170,7 +187,10 @@
     @DELETE
     @Path("{name}")
     @Produces({MediaType.APPLICATION_JSON})
-    public Response removeUser(@PathParam("name") final String name) {
+    public Response removeUser(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+        if (!isAuthorized(request)) {
+            return Response.status(Response.Status.UNAUTHORIZED).build();
+        }
         return super.removeRole(name, Role.USER);
     }
     

Reply via email to