Changeset 985


Ignore:
Timestamp:
Oct 25, 2010, 3:28:44 PM (6 years ago)
Author:
robert@…
Message:

Removed spring-security-ui plugin to decrease dependencies. The functionality (user management and password resets) was copied to gscf itself.

Location:
trunk
Files:
4 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/application.properties

    r979 r985  
    11#Grails Metadata file
    2 #Fri Oct 22 12:28:07 CEST 2010
     2#Mon Oct 25 15:00:21 CEST 2010
    33app.grails.version=1.3.5
    44app.name=gscf
     
    77plugins.crypto=2.0
    88plugins.db-util=0.4
    9 plugins.famfamfam=1.0.1
    109plugins.grom=0.1.2
    1110plugins.hibernate=1.3.5
    1211plugins.jquery=1.4.3.2
    13 plugins.jquery-ui=1.8.4.3
    1412plugins.mail=0.9
    1513plugins.oauth=0.10
    1614plugins.searchable=0.5.5.1
    1715plugins.spring-security-core=1.0.1
    18 plugins.spring-security-ui=0.1.2
    1916plugins.tomcat=1.3.5
    2017plugins.webflow=1.3.4
  • trunk/grails-app/conf/Config.groovy

    r983 r985  
    166166grails.plugins.springsecurity.successHandler.targetUrlParameter = 'spring-security-redirect'
    167167
     168// Needed for the (copy of) the Spring Security UI plugin
     169grails.plugins.springsecurity.ui.forgotPassword.emailFrom = 'gscf@dbnp.org'
     170grails.plugins.springsecurity.ui.forgotPassword.emailSubject = 'Password reset GSCF'
     171
    168172// Make sure the different controllers provided by springsecurity.ui are only accessible by administrators
    169173// NB: the RegisterController is used for forgotten passwords. It should be accessible by anyone
  • trunk/grails-app/controllers/dbnp/authentication/RegisterController.groovy

    r976 r985  
     1/* Copyright 2009-2010 the original author or authors.
     2 *
     3 * Licensed under the Apache License, Version 2.0 (the "License");
     4 * you may not use this file except in compliance with the License.
     5 * You may obtain a copy of the License at
     6 *
     7 *      http://www.apache.org/licenses/LICENSE-2.0
     8 *
     9 * Unless required by applicable law or agreed to in writing, software
     10 * distributed under the License is distributed on an "AS IS" BASIS,
     11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 * See the License for the specific language governing permissions and
     13 * limitations under the License.
     14 */
    115package dbnp.authentication
    216
    3 import grails.plugins.springsecurity.Secured
    4 import grails.plugins.springsecurity.ui.*
     17import groovy.text.SimpleTemplateEngine
     18
     19import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
     20import org.codehaus.groovy.grails.plugins.springsecurity.NullSaltSource
    521import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
    6 import org.codehaus.groovy.grails.plugins.springsecurity.ui.RegistrationCode
    722
    8 class RegisterController extends grails.plugins.springsecurity.ui.RegisterController {
     23/**
     24 * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
     25 */
     26class RegisterController {
    927
    10     // The registration should be done using the UserRegistration controller
    11     @Secured(['ROLE_ADMIN'])
    12     def index = {
    13         throw new Exception( "Method should not be called!" )
    14     }
     28        def springSecurityService
     29        def mailService
     30       
     31        static defaultAction = 'index'
    1532
     33        def saltSource
     34
     35        def index = {
     36                [command: new RegisterCommand()]
     37        }
     38
     39        def forgotPassword = {
     40
     41                if (!request.post) {
     42                        // show the form
     43                        return
     44                }
     45
     46                String username = params.username
     47                if (!username) {
     48                        flash.error = message(code: 'spring.security.ui.forgotPassword.username.missing')
     49                        return
     50                }
     51
     52                def user = SecUser.findByUsername(username)
     53                if (!user) {
     54                        flash.error = message(code: 'spring.security.ui.forgotPassword.user.notFound')
     55                        return
     56                }
     57
     58                def registrationCode = new RegistrationCode(username: user.username).save()
     59
     60                String url = generateLink('resetPassword', [t: registrationCode.token])
     61
     62                def conf = SpringSecurityUtils.securityConfig
     63                def body = g.render(template:'/email/passwordReset', model: [user: user, url: url])
     64               
     65                mailService.sendMail {
     66                        to user.email
     67                        from conf.ui.forgotPassword.emailFrom
     68                        subject conf.ui.forgotPassword.emailSubject
     69                        html body.toString()
     70                }
     71
     72                [emailSent: true]
     73        }
     74
     75        def resetPassword = { ResetPasswordCommand command ->
     76
     77                String token = params.t
     78
     79                def registrationCode = token ? RegistrationCode.findByToken(token) : null
     80                if (!registrationCode) {
     81                        flash.error = message(code: 'spring.security.ui.resetPassword.badCode')
     82                        redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
     83                        return
     84                }
     85
     86                if (!request.post) {
     87                        return [token: token, command: new ResetPasswordCommand()]
     88                }
     89
     90                command.username = registrationCode.username
     91                command.validate()
     92
     93                if (command.hasErrors()) {
     94                        return [token: token, command: command]
     95                }
     96
     97                String salt = registrationCode.username
     98                RegistrationCode.withTransaction { status ->
     99                        def user = SecUser.findByUsername(registrationCode.username)
     100                        user.password = springSecurityService.encodePassword(command.password, salt)
     101                        user.save()
     102                        registrationCode.delete()
     103                }
     104
     105                springSecurityService.reauthenticate registrationCode.username
     106
     107                flash.message = message(code: 'spring.security.ui.resetPassword.success')
     108
     109                def conf = SpringSecurityUtils.securityConfig
     110                String postResetUrl = conf.ui.register.postResetUrl ?: conf.successHandler.defaultTargetUrl
     111                redirect uri: postResetUrl
     112        }
     113
     114        protected String generateLink(String action, linkParams) {
     115                createLink(base: "$request.scheme://$request.serverName:$request.serverPort$request.contextPath",
     116                                controller: 'register', action: action,
     117                                params: linkParams)
     118
     119        }
     120
     121        protected String evaluate(s, binding) {
     122                new SimpleTemplateEngine().createTemplate(s).make(binding)
     123        }
     124
     125        static final passwordValidator = { String password, command ->
     126                if (command.username && command.username.equals(password)) {
     127                        return 'command.password.error.username'
     128                }
     129
     130                if (!password || password.length() < 8 || password.length() > 64 ||
     131                                (!password.matches('^.*\\p{Alpha}.*$') ||
     132                                !password.matches('^.*\\p{Digit}.*$') ||
     133                                !password.matches('^.*[!@#$%^&].*$'))) {
     134                        return 'command.password.error.strength'
     135                }
     136        }
     137
     138        static final password2Validator = { value, command ->
     139                if (command.password != command.password2) {
     140                        return 'command.password2.error.mismatch'
     141                }
     142        }
    16143}
     144
     145class RegisterCommand {
     146
     147        String username
     148        String email
     149        String password
     150        String password2
     151
     152        static constraints = {
     153                username blank: false, validator: { value, command ->
     154                        if (value) {
     155                                def User = AH.application.getDomainClass(
     156                                        SpringSecurityUtils.securityConfig.userLookup.userDomainClassName).clazz
     157                                if (User.findByUsername(value)) {
     158                                        return 'registerCommand.username.unique'
     159                                }
     160                        }
     161                }
     162                email blank: false, email: true
     163                password blank: false, minSize: 8, maxSize: 64, validator: RegisterController.passwordValidator
     164                password2 validator: RegisterController.password2Validator
     165        }
     166}
     167
     168class ResetPasswordCommand {
     169        String username
     170        String password
     171        String password2
     172
     173        static constraints = {
     174                password blank: false, minSize: 8, maxSize: 64, validator: RegisterController.passwordValidator
     175                password2 validator: RegisterController.password2Validator
     176        }
     177}
  • trunk/grails-app/views/common/_login_panel.gsp

    r984 r985  
    77                                <h2>version <b>${meta(name: 'app.version')}</b></h2>
    88                                <p class="grey">Please use the forms on the right to either log in if you already have an account, or sign up if you think this data support platform suits your needs.</p>
    9                                 <p class="grey">Note that <span class="red">registration</span> and <span class="red">password reminders</span> are not yet implemented and hence <span class="red">do not work</span> at this moment!</p>
    109                                <g:if test="${flash.message}"><p class="red">${flash.message}</p></g:if>
    1110                        </div>
  • trunk/grails-app/views/common/_topnav.gsp

    r976 r985  
    55<sec:ifLoggedIn>
    66     <li><g:link controller="study" action="myStudies">My studies</g:link></li>
    7 </sec:ifLoggedIn>     <li>
     7</sec:ifLoggedIn>
     8        <li>
    89      <a href="#">Studies</a>
    910      <ul class="subnav">
     
    4445            <li><g:link controller="user" class="icon icon_user">List Users</g:link></li>
    4546            <li><g:link controller="user" action="create" class="icon icon_user_add">Create User</g:link></li>
    46             <li><g:link controller="role" class="icon icon_cog">List Roles</g:link></li>
    47             <li><g:link controller="role" action="create" class="icon icon_cog_add">Create Role</g:link></li>
    4847            <li><g:link controller="logout" class="icon icon_cross">Sign out</g:link></li>
    4948          </ul>
  • trunk/grails-app/views/register/resetPassword.gsp

    r976 r985  
    77
    88<p/>
     9        <g:form action='resetPassword' name='resetPasswordForm' autocomplete='off'>
     10        <g:hiddenField name='t' value='${token}'/>
     11          <div class="sign-in">
    912
    10         <g:form action='resetPassword' name='resetPasswordForm' autocomplete='off'>
    11         <g:hiddenField name='t' value='${token}'/>
    12         <div class="sign-in">
     13                <g:hasErrors bean="${command}">
     14                  <p>Both passwords should match, contain more than 8 and less than 64 characters.</p>
     15                  <p>Also, passwords should contain at least one letter, one number and one symbol.</p>
     16                </g:hasErrors>
    1317
    14         <br/>
    15         <h4><g:message code='spring.security.ui.resetPassword.description'/></h4>
     18                <br/>
     19                <h4><g:message code='spring.security.ui.resetPassword.description'/></h4>
    1620
    17         <table>
    18                 <s2ui:passwordFieldRow name='password' labelCode='resetPasswordCommand.password.label' bean="${command}"
    19                              labelCodeDefault='Password' value="${command?.password}"/>
     21                <table>
     22                  <tr><td>Password</td><td><g:passwordField name="password" value="${command?.password}" /></td></tr>
     23                  <tr><td>Password (again)</td><td>
     24                        <g:passwordField name="password2" value="${command?.password2}" />
     25                  </td></tr>
     26                </table>
    2027
    21                 <s2ui:passwordFieldRow name='password2' labelCode='resetPasswordCommand.password2.label' bean="${command}"
    22                              labelCodeDefault='Password (again)' value="${command?.password2}"/>
    23         </table>
     28                <input type="submit" value="Reset my password" />
    2429
    25         <input type="submit" value="Reset my password" />
    26 
    27 
    28         </div>
     30          </div>
    2931        </g:form>
    3032
  • trunk/grails-app/views/user/create.gsp

    r976 r985  
    11<head>
    2         <meta name='layout' content='springSecurityUI'/>
     2        <meta name='layout' content='main'/>
    33        <g:set var="entityName" value="${message(code: 'user.label', default: 'User')}"/>
    44        <title><g:message code="default.create.label" args="[entityName]"/></title>
     5
     6    <script type="text/javascript">
     7      // This method is called on the event body.onLoad
     8      $(function() {
     9              $("#tabs").tabs();
     10      });
     11    </script>
    512</head>
    613
    714<body>
    8 
     15    <script src="${resource(dir: 'js', file: 'jquery-callback-1.2.js')}" type="text/javascript"></script>
    916<h3><g:message code="default.create.label" args="[entityName]"/></h3>
    1017
    11 <g:form action="save" name='userCreateForm'>
     18<g:form action="save" name='userCreateForm' class="button-style">
    1219
    13 <%
    14 def tabData = []
    15 tabData << [name: 'userinfo', icon: 'icon_user',  messageCode: 'spring.security.ui.user.info']
    16 tabData << [name: 'roles',    icon: 'icon_role', messageCode: 'spring.security.ui.user.roles']
    17 %>
     20      <div id="tabs">
     21        <ul>
     22          <li><a href="#userinfo">User info</a></li>
     23          <li><a href="#roles">Roles</a></li>
     24        </ul>
    1825
    19 <s2ui:tabs elementId='tabs' height='375' data="${tabData}">
     26        <div id="userinfo">
    2027
    21         <s2ui:tab name='userinfo' height='280'>
    22                 <table>
    23                 <tbody>
     28                  <table>
     29                  <tbody>
     30                        <tr><td>Username</td><td><g:textField name="username" value="${user?.username}"/></td></tr>
     31                        <tr><td>Password</td><td><g:passwordField name="password" value="${user?.password}"/></td></tr>
     32                        <tr><td>Email address</td><td><g:textField name="email" value="${user?.email}"/></td></tr>
     33                        <tr><td>User confirmed</td><td><g:checkBox name="userConfirmed" value="${user?.userConfirmed}"/></td></tr>
     34                        <tr><td>Admin confirmed</td><td><g:checkBox name="adminConfirmed" value="${user?.adminConfirmed}"/></td></tr>
     35                        <tr><td>Account expired</td><td><g:checkBox name="accountExpired" value="${user?.accountExpired}"/></td></tr>
     36                        <tr><td>Account locked</td><td><g:checkBox name="accountLocked" value="${user?.accountLocked}"/></td></tr>
     37                        <tr><td>Password expired</td><td><g:checkBox name="passwordExpired" value="${user?.passwordExpired}"/></td></tr>
    2438
    25                         <s2ui:textFieldRow name='username' labelCode='user.username.label' bean="${user}"
    26                             labelCodeDefault='Username' value="${user?.username}"/>
    27 
    28                         <s2ui:passwordFieldRow name='password' labelCode='user.password.label' bean="${user}"
    29                                 labelCodeDefault='Password' value="${user?.password}"/>
    30 
    31                         <s2ui:checkboxRow name='userConfirmed' labelCode='user.confirmed.label' bean="${user}"
    32                            labelCodeDefault='Confirmed (by user)' value="${user?.userConfirmed}"/>
    33 
    34                         <s2ui:checkboxRow name='adminConfirmed' labelCode='user.approved.label' bean="${user}"
    35                            labelCodeDefault='Approved (by administrator)' value="${user?.adminConfirmed}"/>
    36 
    37                         <s2ui:checkboxRow name='accountExpired' labelCode='user.accountExpired.label' bean="${user}"
    38                            labelCodeDefault='Account Expired' value="${user?.accountExpired}"/>
    39 
    40                         <s2ui:checkboxRow name='accountLocked' labelCode='user.accountLocked.label' bean="${user}"
    41                            labelCodeDefault='Account Locked' value="${user?.accountLocked}"/>
    42 
    43                         <s2ui:checkboxRow name='passwordExpired' labelCode='user.passwordExpired.label' bean="${user}"
    44                            labelCodeDefault='Password Expired' value="${user?.passwordExpired}"/>
    45                 </tbody>
    46                 </table>
    47         </s2ui:tab>
    48 
    49         <s2ui:tab name='roles' height='280'>
    50                 <g:each var="auth" in="${authorityList}">
     39                  </tbody>
     40                  </table>
     41          </div>
     42          <div id="roles">
     43                <g:each var="entry" in="${roleMap}">
    5144                <div>
    52                         <g:checkBox name="${auth.authority}" />
    53                         <g:link controller='role' action='edit' id='${auth.id}'>${auth.authority.encodeAsHTML()}</g:link>
     45                        <g:checkBox name="${entry.key.authority}" value="${entry.value}"/>
     46                        <g:link controller='role' action='edit' id='${entry.key.id}'>${entry.key.authority.encodeAsHTML()}</g:link>
    5447                </div>
    5548                </g:each>
    56         </s2ui:tab>
     49          </div>
    5750
    58 </s2ui:tabs>
     51          </div>
    5952
    60 <div style='float:left; margin-top: 10px; '>
    61 <s2ui:submitButton elementId='create' form='userCreateForm' messageCode='default.button.create.label'/>
     53<div style='float:left; margin-top: 10px;'>
     54  <input type="submit" value="Save" />
     55
     56  <g:if test='${user}'>
     57        DELETE
     58  </g:if>
     59
    6260</div>
    6361
    6462</g:form>
    6563
     64<g:if test='${user}'>
     65  deleteform
     66</g:if>
     67
    6668<script>
    6769$(document).ready(function() {
    6870        $('#username').focus();
    69         <s2ui:initCheckboxes/>
    7071});
    7172</script>
  • trunk/grails-app/views/user/edit.gsp

    r976 r985  
    1 <%@ page import="org.codehaus.groovy.grails.plugins.PluginManagerHolder" %>
    2 
    3 <sec:ifNotSwitched>
    4         <sec:ifAllGranted roles='ROLE_SWITCH_USER'>
    5         <g:if test='${user.username}'>
    6         <g:set var='canRunAs' value='${true}'/>
    7         </g:if>
    8         </sec:ifAllGranted>
    9 </sec:ifNotSwitched>
    10 
    111<head>
    12         <meta name='layout' content='springSecurityUI'/>
     2        <meta name='layout' content='main'/>
    133        <g:set var="entityName" value="${message(code: 'user.label', default: 'User')}"/>
    144        <title><g:message code="default.edit.label" args="[entityName]"/></title>
     5
     6    <script type="text/javascript">
     7      // This method is called on the event body.onLoad
     8      $(function() {
     9              $("#tabs").tabs();
     10      });
     11    </script>
    1512</head>
    1613
    1714<body>
    18 
     15    <script src="${resource(dir: 'js', file: 'jquery-callback-1.2.js')}" type="text/javascript"></script>
    1916<h3><g:message code="default.edit.label" args="[entityName]"/></h3>
    2017
     
    2320<g:hiddenField name="version" value="${user?.version}"/>
    2421
    25 <%
    26 def tabData = []
    27 tabData << [name: 'userinfo', icon: 'icon_user', messageCode: 'spring.security.ui.user.info']
    28 tabData << [name: 'roles',    icon: 'icon_role', messageCode: 'spring.security.ui.user.roles']
    29 boolean isOpenId = PluginManagerHolder.pluginManager.hasGrailsPlugin('springSecurityOpenid')
    30 if (isOpenId) {
    31         tabData << [name: 'openIds', icon: 'icon_role', messageCode: 'spring.security.ui.user.openIds']
    32 }
    33 %>
     22      <div id="tabs">
     23        <ul>
     24          <li><a href="#userinfo">User info</a></li>
     25          <li><a href="#roles">Roles</a></li>
     26        </ul>
    3427
    35 <s2ui:tabs elementId='tabs' height='375' data="${tabData}">
     28        <div id="userinfo">
    3629
    37         <s2ui:tab name='userinfo' height='275'>
    38                 <table>
    39                 <tbody>
     30                  <table>
     31                  <tbody>
     32                        <tr><td>Username</td><td><g:textField name="username" value="${user?.username}"/></td></tr>
     33                        <tr><td>Password</td><td><g:passwordField name="password" value="${user?.password}"/></td></tr>
     34                        <tr><td>Email address</td><td><g:textField name="email" value="${user?.email}"/></td></tr>
     35                        <tr><td>User confirmed</td><td><g:checkBox name="userConfirmed" value="${user?.userConfirmed}"/></td></tr>
     36                        <tr><td>Admin confirmed</td><td><g:checkBox name="adminConfirmed" value="${user?.adminConfirmed}"/></td></tr>
     37                        <tr><td>Account expired</td><td><g:checkBox name="accountExpired" value="${user?.accountExpired}"/></td></tr>
     38                        <tr><td>Account locked</td><td><g:checkBox name="accountLocked" value="${user?.accountLocked}"/></td></tr>
     39                        <tr><td>Password expired</td><td><g:checkBox name="passwordExpired" value="${user?.passwordExpired}"/></td></tr>
    4040
    41                         <s2ui:textFieldRow name='username' labelCode='user.username.label' bean="${user}"
    42                             labelCodeDefault='Username' value="${user?.username}"/>
    43 
    44                         <s2ui:passwordFieldRow name='password' labelCode='user.password.label' bean="${user}"
    45                                 labelCodeDefault='Password' value="${user?.password}"/>
    46 
    47                         <s2ui:checkboxRow name='userConfirmed' labelCode='user.confirmed.label' bean="${user}"
    48                            labelCodeDefault='Confirmed (by user)' value="${user?.userConfirmed}"/>
    49 
    50                         <s2ui:checkboxRow name='adminConfirmed' labelCode='user.approved.label' bean="${user}"
    51                            labelCodeDefault='Approved (by administrator)' value="${user?.adminConfirmed}"/>
    52 
    53                         <s2ui:checkboxRow name='accountExpired' labelCode='user.accountExpired.label' bean="${user}"
    54                            labelCodeDefault='Account Expired' value="${user?.accountExpired}"/>
    55 
    56                         <s2ui:checkboxRow name='accountLocked' labelCode='user.accountLocked.label' bean="${user}"
    57                            labelCodeDefault='Account Locked' value="${user?.accountLocked}"/>
    58 
    59                         <s2ui:checkboxRow name='passwordExpired' labelCode='user.passwordExpired.label' bean="${user}"
    60                            labelCodeDefault='Password Expired' value="${user?.passwordExpired}"/>
    61                 </tbody>
    62                 </table>
    63         </s2ui:tab>
    64 
    65         <s2ui:tab name='roles' height='275'>
     41                  </tbody>
     42                  </table>
     43          </div>
     44          <div id="roles">
    6645                <g:each var="entry" in="${roleMap}">
    6746                <div>
     
    7049                </div>
    7150                </g:each>
    72         </s2ui:tab>
     51          </div>
    7352
    74         <g:if test='${isOpenId}'>
    75         <s2ui:tab name='openIds' height='275'>
    76         <g:if test='${user?.openIds}'>
    77                 <ul>
    78                 <g:each var="openId" in="${user.openIds}">
    79                 <li>${openId.url}</li>
    80                 </g:each>
    81                 </ul>
    82         </g:if>
    83         <g:else>
    84         No OpenIDs registered
    85         </g:else>
    86         </s2ui:tab>
    87         </g:if>
    88 
    89 </s2ui:tabs>
     53          </div>
    9054
    9155<div style='float:left; margin-top: 10px;'>
    92 <s2ui:submitButton elementId='update' form='userEditForm' messageCode='default.button.update.label'/>
     56  <input type="submit" value="Save" />
    9357
    94 <g:if test='${user}'>
    95 <s2ui:deleteButton />
    96 </g:if>
    97 
    98 <g:if test='${canRunAs}'>
    99 <a id="runAsButton">${message(code:'spring.security.ui.runas.submit')}</a>
    100 </g:if>
     58  <g:if test='${user}'>
     59        DELETE
     60  </g:if>
    10161
    10262</div>
     
    10565
    10666<g:if test='${user}'>
    107 <s2ui:deleteButtonForm instanceId='${user.id}'/>
    108 </g:if>
    109 
    110 <g:if test='${canRunAs}'>
    111         <form name='runAsForm' action='${request.contextPath}/j_spring_security_switch_user' method='POST'>
    112                 <g:hiddenField name='j_username' value="${user.username}"/>
    113                 <input type='submit' class='s2ui_hidden_button' />
    114         </form>
     67  deleteform
    11568</g:if>
    11669
     
    11871$(document).ready(function() {
    11972        $('#username').focus();
    120 
    121         <s2ui:initCheckboxes/>
    122 
    123         $("#runAsButton").button();
    124         $('#runAsButton').bind('click', function() {
    125            document.forms.runAsForm.submit();
    126         });
    12773});
    12874</script>
  • trunk/grails-app/views/user/search.gsp

    r976 r985  
    11<head>
    2         <meta name='layout' content='springSecurityUI'/>
     2        <meta name='layout' content='main'/>
    33        <title><g:message code='spring.security.ui.user.search'/></title>
    44</head>
     
    77
    88<div>
    9 
    10         <s2ui:form width='100%' height='375' elementId='formContainer'
    11               titleCode='spring.security.ui.user.search'>
    129
    1310        <g:form action='userSearch' name='userSearchForm'>
     
    5552                        <tr><td colspan='4'>&nbsp;</td></tr>
    5653                        <tr>
    57                                 <td colspan='4'><s2ui:submitButton elementId='search' form='userSearchForm' messageCode='spring.security.ui.search'/></td>
     54                                <td colspan='4'><input type="submit" value="Search" /></td>
    5855                        </tr>
    5956                        </tbody>
    6057                </table>
    6158        </g:form>
    62 
    63         </s2ui:form>
    6459
    6560        <g:if test='${searched}'>
     
    9994        </div>
    10095
    101         <div style="text-align:center">
    102                 <s2ui:paginationSummary total="${totalCount}"/>
    103         </div>
    104 
    10596        </g:if>
    10697
     
    116107});
    117108
    118 <s2ui:initCheckboxes/>
    119 
    120109</script>
    121110
Note: See TracChangeset for help on using the changeset viewer.