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

Last change on this file since 613 was 440, checked in by gav, 15 years ago

Add Person import feature.
Commit has a small amount of cross over code to the commits will follow.

File size: 8.6 KB
RevLine 
[62]1import org.codehaus.groovy.grails.plugins.springsecurity.Secured
[440]2import org.codehaus.groovy.grails.commons.ConfigurationHolder
[58]3
[149]4@Secured(['ROLE_Manager','ROLE_AppAdmin'])
[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 )
[58]55
[250]56        if(!params.filter) {
57            return [personList: Person.list(params),
58                            personTotal: Person.count(),
59                            filterParams: params]
60        }
[147]61
62        // filterPane:
63        return[ personList: filterService.filter( params, Person ),
64            personTotal: filterService.count( params, Person ),
65            filterParams: com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params),
66            params:params ]
67    }
68
[150]69    def show = {
[147]70
71        // In the case of an actionSubmit button, rewrite action name from 'index'.
72        if(params._action_Show)
[375]73            params.action='show'
[147]74
[150]75        def person = Person.get(params.id)
76        if (!person) {
77            flash.message = "Person not found with id $params.id"
78            redirect action: list
79            return
80        }
[295]81        def authorityList = person.authorities.sort { p1, p2 -> p1.id <=> p2.id }
82        [person: person, authorityList: authorityList]
[150]83    }
[58]84
[150]85    /**
86    * Person delete action. Before removing an existing person,
87    * they should be removed from those authorities which they are involved.
88    */
89    def delete = {
[58]90
[150]91        def person = Person.get(params.id)
92        if (person) {
93            def authPrincipal = authenticateService.principal()
94            // Avoid self-delete.
95            if (!(authPrincipal instanceof String) && authPrincipal.username == person.loginName) {
96                flash.message = "You cannot delete yourself, please login as another manager and try again."
[147]97                redirect(action:show,id:params.id)
[150]98            }
99            else {
100                //first, delete this person from Persons_Authorities table.
101                Authority.findAll().each { it.removeFromPersons(person) }
[147]102                person.isActive = false
103                person.save(flush: true)
104
[97]105                try {
[147]106                    person.delete(flush: true)
[91]107                    flash.message = "Person $params.id deleted."
[97]108                    redirect(action:list)
109                }
110                catch(org.springframework.dao.DataIntegrityViolationException e) {
111                    flash.message = "Could not delete '$person.loginName' due to database constraints, but all authorities have been removed."
112                    redirect(action:show,id:params.id)
113                }
[150]114            }
115        }
116        else {
117            flash.message = "Person not found with id $params.id"
118        }
119    }
[58]120
[150]121    def edit = {
[58]122
[147]123        // In the case of an actionSubmit button, rewrite action name from 'index'.
124        if(params._action_Edit)
[375]125            params.action='edit'
[147]126
[150]127        def person = Person.get(params.id)
128        if (!person) {
129            flash.message = "Person not found with id $params.id"
130            redirect action: list
131            return
132        }
133        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
134        return buildPersonModel(person)
135    }
[58]136
[150]137    /**
[294]138    * Person update action.
139    */
[150]140    def update = {
[294]141        Person.withTransaction { status ->
[58]142
[294]143            def person = Person.get(params.id)
144            if (!person) {
145                flash.message = "Person not found with id $params.id"
146                redirect action: edit, id: params.id
147                return
148            }
[58]149
[294]150            long version = params.version.toLong()
151            if (person.version > version) {
[403]152                person.errors.rejectValue 'version', "default.optimistic.locking.failure"
[294]153                render view: 'edit', model: buildPersonModel(person)
154                return
155            }
[58]156
[294]157            person.properties = params
158            person.setPersonGroupsFromCheckBoxList(params.personGroups)
[73]159
[294]160            if(params.pass == "") {
161                person.pass = "InsertNothingToClearValidation"
[73]162            }
[294]163            else {
164                if (person.validate()) {
165                    person.password = authenticateService.encodePassword(params.pass)
166                }
167            }
[73]168
[294]169            if (!person.hasErrors() && person.save(flush: true)) {
[295]170                addRemoveAuthorities(person)
[294]171                flash.message = "Person '$params.id - $params.loginName' updated."
172                redirect action: show, id: person.id
173            }
174            else {
175                render view: 'edit', model: buildPersonModel(person)
176            }
[73]177
[294]178        } //end withTransaction
179    } // update()
[58]180
[150]181    def create = {
182        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
[294]183        [person: new Person(params), authorityList: getLimitedAuthorityList()]
[150]184    }
[58]185
[150]186    /**
[294]187    * Person save action.
188    */
[150]189    def save = {
[294]190        Person.withTransaction { status ->
[58]191
[294]192            def person = new Person()
193            person.properties = params
194            person.password = authenticateService.encodePassword(params.pass)
195            person.setPersonGroupsFromCheckBoxList(params.personGroups)
196            if (person.save(flush: true)) {
[295]197                addRemoveAuthorities(person)
[294]198                redirect action: show, id: person.id
199            }
200            else {
201                render view: 'create', model: [person: person, authorityList: getLimitedAuthorityList()]
202            }
203
204        } //end withTransaction
[150]205    }
[58]206
[295]207    /**
208    * Add or remove authorities from person as indicated in params.
209    */
210    private void addRemoveAuthorities(person) {
211        def authMap = [:]
212
213        // Build authMap from params.
[294]214        for (key in params.keySet()) {
[295]215            if(key.startsWith("ROLE")) {
216                authMap.(key.toString()) = "add"
217            }
218            else if(key.startsWith("_ROLE")) {
219                if( !authMap.(key.substring(1)) ) authMap.(key.substring(1)) = "remove"
220            }
[150]221        }
[295]222
223        // Add or remove authorities.
224        for(a in authMap) {
225            if(a.value == "add")
226                Authority.findByAuthority(a.key.toString()).addToPersons(person)
227            else
228                Authority.findByAuthority(a.key.toString()).removeFromPersons(person)
229        }
[150]230    }
[58]231
[150]232    private Map buildPersonModel(person) {
[58]233
[294]234        List roles = getLimitedAuthorityList()
[150]235        Set userRoleNames = []
236        for (role in person.authorities) {
237            userRoleNames << role.authority
238        }
239        LinkedHashMap<Authority, Boolean> roleMap = [:]
240        for (role in roles) {
241            roleMap[(role)] = userRoleNames.contains(role.authority)
242        }
[58]243
[150]244        return [person: person, roleMap: roleMap]
245    }
[294]246
247    /**
248    * Get the full authorityList if current user is an App Admin else leave that authority off the list.
249    */
[295]250    private List getLimitedAuthorityList() {
[294]251        def authorityList = []
252        if(authenticateService.ifAnyGranted('ROLE_AppAdmin'))
[295]253            authorityList = Authority.list().sort { p1, p2 -> p1.id <=> p2.id }
[294]254        else
[295]255            authorityList = Authority.withCriteria { gt("id", 1L) }.sort { p1, p2 -> p1.id <=> p2.id }
[294]256
257        return authorityList
258    }
[295]259} // end class
Note: See TracBrowser for help on using the repository browser.