source: trunk/grails-app/controllers/PersonController.groovy @ 956

Last change on this file since 956 was 956, checked in by gav, 13 years ago

Fix person list filterpane memory bug on associated properties.

File size: 10.2 KB
RevLine 
[62]1import org.codehaus.groovy.grails.plugins.springsecurity.Secured
[440]2import org.codehaus.groovy.grails.commons.ConfigurationHolder
[58]3
[628]4@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
[97]5class PersonController extends BaseAppAdminController {
[58]6
[440]7    def filterService
8    def personCsvService
[147]9    def authenticateService
[58]10
[150]11    // the delete, save and update actions only accept POST requests
12    static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
[58]13
[150]14    def index = {
15        redirect action: list, params: params
16    }
[58]17
[440]18    /**
19    * Disaply the import view.
20    */
21    def importPersons = {
22    }
23
24    /**
25    * Handle the import save.
26    */
27    def importPersonsSave = {
28        def result = personCsvService.importPersons(request)
29
30        if(!result.error) {
31            response.contentType = ConfigurationHolder.config.grails.mime.types["text"]
32            response.setHeader("Content-disposition", "attachment; filename=LoginNamesAndPasswords.txt")
33            render result.loginNamesAndPasswords
34            return
35        }
36
37        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
38        redirect(action: importPersons)
39    }
40
41    /**
42    * Export a csv template.
43    * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time!
44    * This does not appear to be a problem once deployed to Tomcat.
45    */
46    def exportPersonsTemplate = {
47        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
48        response.setHeader("Content-disposition", "attachment; filename=personsTemplate.csv")
49        def s = personCsvService.buildPersonsTemplate()
50        render s
51    }
52
[147]53    def list = {
54        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100 )
[956]55        def associatedPropertyMax = 1000
56        def associatedPropertyValues = [:]
57        def personGroupNameQuery = 'select distinct a.name from PersonGroup a where a.isActive = ? order by a.name'
58        associatedPropertyValues.personGroupList = PersonGroup.executeQuery(personGroupNameQuery, [true], [max:associatedPropertyMax])
[58]59
[956]60        def authorityQuery = 'select a.authority from Authority a'
61        associatedPropertyValues.authorityList = Authority.executeQuery(authorityQuery, [max:associatedPropertyMax])
62
[250]63        if(!params.filter) {
64            return [personList: Person.list(params),
[956]65                    personTotal: Person.count(),
66                    associatedPropertyValues: associatedPropertyValues,
67                    filterParams: params]
[250]68        }
[147]69
70        // filterPane:
71        return[ personList: filterService.filter( params, Person ),
[956]72                personTotal: filterService.count( params, Person ),
73                associatedPropertyValues: associatedPropertyValues,
74                filterParams: com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params),
75                params:params ]
[147]76    }
77
[150]78    def show = {
[147]79
80        // In the case of an actionSubmit button, rewrite action name from 'index'.
81        if(params._action_Show)
[375]82            params.action='show'
[147]83
[150]84        def person = Person.get(params.id)
85        if (!person) {
86            flash.message = "Person not found with id $params.id"
87            redirect action: list
88            return
89        }
[295]90        def authorityList = person.authorities.sort { p1, p2 -> p1.id <=> p2.id }
91        [person: person, authorityList: authorityList]
[150]92    }
[58]93
[150]94    /**
95    * Person delete action. Before removing an existing person,
96    * they should be removed from those authorities which they are involved.
97    */
98    def delete = {
[58]99
[150]100        def person = Person.get(params.id)
101        if (person) {
102            def authPrincipal = authenticateService.principal()
103            // Avoid self-delete.
104            if (!(authPrincipal instanceof String) && authPrincipal.username == person.loginName) {
[724]105                flash.errorMessage = "You cannot delete yourself, please login as another manager and try again."
[147]106                redirect(action:show,id:params.id)
[150]107            }
[724]108            else if ( person.id == 1L) {
109                flash.errorMessage = "You cannot delete the pseudo system person."
110                redirect(action:show,id:params.id)
111            }
112            else if ( person.id == 2L) {
113                flash.errorMessage = "You cannot delete the admin person."
114                redirect(action:show,id:params.id)
115            }
[150]116            else {
117                //first, delete this person from Persons_Authorities table.
118                Authority.findAll().each { it.removeFromPersons(person) }
[147]119                person.isActive = false
120                person.save(flush: true)
121
[97]122                try {
[147]123                    person.delete(flush: true)
[91]124                    flash.message = "Person $params.id deleted."
[97]125                    redirect(action:list)
126                }
127                catch(org.springframework.dao.DataIntegrityViolationException e) {
128                    flash.message = "Could not delete '$person.loginName' due to database constraints, but all authorities have been removed."
129                    redirect(action:show,id:params.id)
130                }
[150]131            }
132        }
133        else {
[724]134            flash.errorMessage = "Person not found with id $params.id"
[150]135        }
136    }
[58]137
[150]138    def edit = {
[58]139
[147]140        // In the case of an actionSubmit button, rewrite action name from 'index'.
141        if(params._action_Edit)
[375]142            params.action='edit'
[147]143
[150]144        def person = Person.get(params.id)
145        if (!person) {
146            flash.message = "Person not found with id $params.id"
147            redirect action: list
148            return
149        }
[724]150
151        if ( person.id == 1L) {
152            flash.errorMessage = "You cannot edit the pseudo system person."
153            redirect(action:show,id:params.id)
154            return
155        }
156
[150]157        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
158        return buildPersonModel(person)
159    }
[58]160
[150]161    /**
[294]162    * Person update action.
163    */
[150]164    def update = {
[294]165        Person.withTransaction { status ->
[58]166
[294]167            def person = Person.get(params.id)
168            if (!person) {
169                flash.message = "Person not found with id $params.id"
170                redirect action: edit, id: params.id
171                return
172            }
[58]173
[294]174            long version = params.version.toLong()
175            if (person.version > version) {
[403]176                person.errors.rejectValue 'version', "default.optimistic.locking.failure"
[294]177                render view: 'edit', model: buildPersonModel(person)
178                return
179            }
[58]180
[724]181            if ( person.id == 1L) {
182                flash.errorMessage = "You cannot edit the pseudo system person."
183                redirect(action:show,id:params.id)
184                return
185            }
186
[294]187            person.properties = params
188            person.setPersonGroupsFromCheckBoxList(params.personGroups)
[633]189            person.setPurchasingGroupsFromCheckBoxList(params.purchasingGroups)
[73]190
[294]191            if(params.pass == "") {
192                person.pass = "InsertNothingToClearValidation"
[73]193            }
[294]194            else {
195                if (person.validate()) {
196                    person.password = authenticateService.encodePassword(params.pass)
197                }
198            }
[73]199
[294]200            if (!person.hasErrors() && person.save(flush: true)) {
[295]201                addRemoveAuthorities(person)
[294]202                flash.message = "Person '$params.id - $params.loginName' updated."
203                redirect action: show, id: person.id
204            }
205            else {
206                render view: 'edit', model: buildPersonModel(person)
207            }
[73]208
[294]209        } //end withTransaction
210    } // update()
[58]211
[150]212    def create = {
213        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
[294]214        [person: new Person(params), authorityList: getLimitedAuthorityList()]
[150]215    }
[58]216
[150]217    /**
[294]218    * Person save action.
219    */
[150]220    def save = {
[294]221        Person.withTransaction { status ->
[58]222
[294]223            def person = new Person()
224            person.properties = params
225            person.password = authenticateService.encodePassword(params.pass)
226            person.setPersonGroupsFromCheckBoxList(params.personGroups)
[633]227            person.setPurchasingGroupsFromCheckBoxList(params.purchasingGroups)
[294]228            if (person.save(flush: true)) {
[295]229                addRemoveAuthorities(person)
[294]230                redirect action: show, id: person.id
231            }
232            else {
233                render view: 'create', model: [person: person, authorityList: getLimitedAuthorityList()]
234            }
235
236        } //end withTransaction
[150]237    }
[58]238
[295]239    /**
240    * Add or remove authorities from person as indicated in params.
241    */
242    private void addRemoveAuthorities(person) {
243        def authMap = [:]
244
245        // Build authMap from params.
[294]246        for (key in params.keySet()) {
[295]247            if(key.startsWith("ROLE")) {
248                authMap.(key.toString()) = "add"
249            }
250            else if(key.startsWith("_ROLE")) {
251                if( !authMap.(key.substring(1)) ) authMap.(key.substring(1)) = "remove"
252            }
[150]253        }
[295]254
255        // Add or remove authorities.
256        for(a in authMap) {
257            if(a.value == "add")
258                Authority.findByAuthority(a.key.toString()).addToPersons(person)
259            else
260                Authority.findByAuthority(a.key.toString()).removeFromPersons(person)
261        }
[150]262    }
[58]263
[150]264    private Map buildPersonModel(person) {
[58]265
[294]266        List roles = getLimitedAuthorityList()
[150]267        Set userRoleNames = []
268        for (role in person.authorities) {
269            userRoleNames << role.authority
270        }
271        LinkedHashMap<Authority, Boolean> roleMap = [:]
272        for (role in roles) {
273            roleMap[(role)] = userRoleNames.contains(role.authority)
274        }
[58]275
[150]276        return [person: person, roleMap: roleMap]
277    }
[294]278
279    /**
280    * Get the full authorityList if current user is an App Admin else leave that authority off the list.
281    */
[295]282    private List getLimitedAuthorityList() {
[294]283        def authorityList = []
284        if(authenticateService.ifAnyGranted('ROLE_AppAdmin'))
[295]285            authorityList = Authority.list().sort { p1, p2 -> p1.id <=> p2.id }
[294]286        else
[295]287            authorityList = Authority.withCriteria { gt("id", 1L) }.sort { p1, p2 -> p1.id <=> p2.id }
[294]288
289        return authorityList
290    }
[295]291} // end class
Note: See TracBrowser for help on using the repository browser.