source: trunk/grails-app/controllers/dbnp/authentication/UserController.groovy @ 985

Last change on this file since 985 was 985, checked in by robert@…, 12 years ago

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

File size: 6.3 KB
Line 
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 */
15package dbnp.authentication
16
17import grails.converters.JSON
18
19import org.springframework.dao.DataIntegrityViolationException
20
21/**
22 * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
23 */
24class UserController {
25
26        def userCache
27        def springSecurityService
28
29        static defaultAction = 'search'
30
31        def create = {
32                def user = new SecUser(params)
33                [user: user, authorityList: sortedRoles()]
34        }
35
36        def save = {
37                def user = new SecUser(params)
38                if (params.password) {
39                        user.password = springSecurityService.encodePassword(params.password, params.username)
40                }
41                if (!user.save(flush: true)) {
42                        // Reset encoded password
43                        user.password = params.password
44                        render view: 'create', model: [user: user, authorityList: sortedRoles()]
45                        return
46                }
47
48                addRoles(user)
49                flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), user.id])}"
50                redirect action: edit, id: user.id
51        }
52
53        def edit = {
54                def user = findById()
55
56                if (!user) return
57
58                return buildUserModel(user)
59        }
60
61        def update = {
62                def user = findById()
63                if (!user) return
64
65                if (!versionCheck('user.label', 'User', user, [user: user])) {
66                        return
67                }
68               
69                def oldPassword = user.password
70                user.properties = params
71                if (params.password && !params.password.equals(oldPassword)) {
72                        user.password = springSecurityService.encodePassword(params.password, params.username)
73                }
74
75                if (!user.save()) {
76                        render view: 'edit', model: buildUserModel(user)
77                        return
78                }
79
80                SecUserSecRole.removeAll user
81                addRoles user
82               
83                userCache.removeUserFromCache user.username
84
85                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'user.label', default: 'User'), user.id])}"
86                redirect action: edit, id: user.id
87        }
88
89        def delete = {
90                def user = findById()
91                if (!user) return
92
93                try {
94                        SecUserSecRole.removeAll user
95                        user.delete flush: true
96
97                        userCache.removeUserFromCache user.username
98                       
99                        flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
100                        redirect action: search
101                }
102                catch (DataIntegrityViolationException e) {
103                        flash.error = "${message(code: 'default.not.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
104                        redirect action: edit, id: params.id
105                }
106        }
107
108        def search = {
109                [enabled: 0, accountExpired: 0, accountLocked: 0, passwordExpired: 0]
110        }
111
112        def userSearch = {
113
114                boolean useOffset = params.containsKey('offset')
115                params.max = params.max ?: 10
116                params.offset = params.offset ?: 0
117
118                def hql = new StringBuilder('FROM SecUser u WHERE 1=1 ')
119                def queryParams = [:]
120
121                for (name in ['username']) {
122                        if (params[name]) {
123                                hql.append " AND LOWER(u.$name) LIKE :$name"
124                                queryParams[name] = params[name].toLowerCase() + '%'
125                        }
126                }
127
128                for (name in ['enabled', 'accountExpired', 'accountLocked', 'passwordExpired']) {
129                        int value = params.int(name)
130                        if (value) {
131                                hql.append " AND u.$name=:$name"
132                                queryParams[name] = value == 1
133                        }
134                }
135
136                int totalCount = SecUser.executeQuery("SELECT COUNT(DISTINCT u) $hql", queryParams)[0]
137
138                int max = params.int('max')
139                int offset = params.int('offset')
140
141                String orderBy = ''
142                if (params.sort) {
143                        orderBy = " ORDER BY u.$params.sort ${params.order ?: 'ASC'}"
144                }
145
146                def results = SecUser.executeQuery(
147                                "SELECT DISTINCT u $hql $orderBy",
148                                queryParams, [max: max, offset: offset])
149                def model = [results: results, totalCount: totalCount, searched: true]
150
151                // add query params to model for paging
152                for (name in ['username', 'enabled', 'accountExpired', 'accountLocked',
153                              'passwordExpired', 'sort', 'order']) {
154                        model[name] = params[name]
155                }
156
157                render view: 'search', model: model
158        }
159
160        /**
161         * Ajax call used by autocomplete textfield.
162         */
163        def ajaxUserSearch = {
164
165                def jsonData = []
166
167                if (params.term?.length() > 2) {
168                        String username = params.term
169
170                        setIfMissing 'max', 10, 100
171
172                        def results = SecUser.executeQuery(
173                                        "SELECT DISTINCT u.username " +
174                                        "FROM SecUser u " +
175                                        "WHERE LOWER(u.username) LIKE :name " +
176                                        "ORDER BY u.username",
177                                        [name: "${username.toLowerCase()}%"],
178                                        [max: params.max])
179
180                        for (result in results) {
181                                jsonData << [value: result]
182                        }
183                }
184
185                render text: jsonData as JSON, contentType: 'text/plain'
186        }
187
188        protected void addRoles(user) {
189                for (String key in params.keySet()) {
190                        if (key.contains('ROLE') && 'on' == params.get(key)) {
191                                SecUserSecRole.create user, SecRole.findByAuthority(key), true
192                        }
193                }
194        }
195
196        protected Map buildUserModel(user) {
197
198                List roles = sortedRoles()
199                Set userRoleNames = user.authorities*.authority
200                def granted = [:]
201                def notGranted = [:]
202                for (role in roles) {
203                        if (userRoleNames.contains(role.authority)) {
204                                granted[(role)] = userRoleNames.contains(role.authority)
205                        }
206                        else {
207                                notGranted[(role)] = userRoleNames.contains(role.authority)
208                        }
209                }
210
211                return [user: user, roleMap: granted + notGranted]
212        }
213
214        protected findById() {
215                def user = SecUser.get(params.id)
216                if (!user) {
217                        flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
218                        redirect action: search
219                }
220
221                user
222        }
223
224        protected List sortedRoles() {
225                SecRole.list().sort { it.authority }
226        }
227
228        protected boolean versionCheck(String messageCode, String messageCodeDefault, instance, model) {
229                if (params.version) {
230                        def version = params.version.toLong()
231                        if (instance.version > version) {
232                                instance.errors.rejectValue('version', 'default.optimistic.locking.failure',
233                                                [message(code: messageCode, default: messageCodeDefault)] as Object[],
234                                                "Another user has updated this instance while you were editing")
235                                render view: 'edit', model: model
236                                return false
237                        }
238                }
239                true
240        }
241}
Note: See TracBrowser for help on using the repository browser.