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

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

Add some logic to protect the system (no delete or edit) and admin (no delete) pseudo persons.

File size: 9.5 KB
Line 
1import org.codehaus.groovy.grails.plugins.springsecurity.Secured
2import org.codehaus.groovy.grails.commons.ConfigurationHolder
3
4@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
5class PersonController extends BaseAppAdminController {
6
7    def filterService
8    def personCsvService
9    def authenticateService
10
11    // the delete, save and update actions only accept POST requests
12    static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
13
14    def index = {
15        redirect action: list, params: params
16    }
17
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
53    def list = {
54        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100 )
55
56        if(!params.filter) {
57            return [personList: Person.list(params),
58                            personTotal: Person.count(),
59                            filterParams: params]
60        }
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
69    def show = {
70
71        // In the case of an actionSubmit button, rewrite action name from 'index'.
72        if(params._action_Show)
73            params.action='show'
74
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        }
81        def authorityList = person.authorities.sort { p1, p2 -> p1.id <=> p2.id }
82        [person: person, authorityList: authorityList]
83    }
84
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 = {
90
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.errorMessage = "You cannot delete yourself, please login as another manager and try again."
97                redirect(action:show,id:params.id)
98            }
99            else if ( person.id == 1L) {
100                flash.errorMessage = "You cannot delete the pseudo system person."
101                redirect(action:show,id:params.id)
102            }
103            else if ( person.id == 2L) {
104                flash.errorMessage = "You cannot delete the admin person."
105                redirect(action:show,id:params.id)
106            }
107            else {
108                //first, delete this person from Persons_Authorities table.
109                Authority.findAll().each { it.removeFromPersons(person) }
110                person.isActive = false
111                person.save(flush: true)
112
113                try {
114                    person.delete(flush: true)
115                    flash.message = "Person $params.id deleted."
116                    redirect(action:list)
117                }
118                catch(org.springframework.dao.DataIntegrityViolationException e) {
119                    flash.message = "Could not delete '$person.loginName' due to database constraints, but all authorities have been removed."
120                    redirect(action:show,id:params.id)
121                }
122            }
123        }
124        else {
125            flash.errorMessage = "Person not found with id $params.id"
126        }
127    }
128
129    def edit = {
130
131        // In the case of an actionSubmit button, rewrite action name from 'index'.
132        if(params._action_Edit)
133            params.action='edit'
134
135        def person = Person.get(params.id)
136        if (!person) {
137            flash.message = "Person not found with id $params.id"
138            redirect action: list
139            return
140        }
141
142        if ( person.id == 1L) {
143            flash.errorMessage = "You cannot edit the pseudo system person."
144            redirect(action:show,id:params.id)
145            return
146        }
147
148        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
149        return buildPersonModel(person)
150    }
151
152    /**
153    * Person update action.
154    */
155    def update = {
156        Person.withTransaction { status ->
157
158            def person = Person.get(params.id)
159            if (!person) {
160                flash.message = "Person not found with id $params.id"
161                redirect action: edit, id: params.id
162                return
163            }
164
165            long version = params.version.toLong()
166            if (person.version > version) {
167                person.errors.rejectValue 'version', "default.optimistic.locking.failure"
168                render view: 'edit', model: buildPersonModel(person)
169                return
170            }
171
172            if ( person.id == 1L) {
173                flash.errorMessage = "You cannot edit the pseudo system person."
174                redirect(action:show,id:params.id)
175                return
176            }
177
178            person.properties = params
179            person.setPersonGroupsFromCheckBoxList(params.personGroups)
180            person.setPurchasingGroupsFromCheckBoxList(params.purchasingGroups)
181
182            if(params.pass == "") {
183                person.pass = "InsertNothingToClearValidation"
184            }
185            else {
186                if (person.validate()) {
187                    person.password = authenticateService.encodePassword(params.pass)
188                }
189            }
190
191            if (!person.hasErrors() && person.save(flush: true)) {
192                addRemoveAuthorities(person)
193                flash.message = "Person '$params.id - $params.loginName' updated."
194                redirect action: show, id: person.id
195            }
196            else {
197                render view: 'edit', model: buildPersonModel(person)
198            }
199
200        } //end withTransaction
201    } // update()
202
203    def create = {
204        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
205        [person: new Person(params), authorityList: getLimitedAuthorityList()]
206    }
207
208    /**
209    * Person save action.
210    */
211    def save = {
212        Person.withTransaction { status ->
213
214            def person = new Person()
215            person.properties = params
216            person.password = authenticateService.encodePassword(params.pass)
217            person.setPersonGroupsFromCheckBoxList(params.personGroups)
218            person.setPurchasingGroupsFromCheckBoxList(params.purchasingGroups)
219            if (person.save(flush: true)) {
220                addRemoveAuthorities(person)
221                redirect action: show, id: person.id
222            }
223            else {
224                render view: 'create', model: [person: person, authorityList: getLimitedAuthorityList()]
225            }
226
227        } //end withTransaction
228    }
229
230    /**
231    * Add or remove authorities from person as indicated in params.
232    */
233    private void addRemoveAuthorities(person) {
234        def authMap = [:]
235
236        // Build authMap from params.
237        for (key in params.keySet()) {
238            if(key.startsWith("ROLE")) {
239                authMap.(key.toString()) = "add"
240            }
241            else if(key.startsWith("_ROLE")) {
242                if( !authMap.(key.substring(1)) ) authMap.(key.substring(1)) = "remove"
243            }
244        }
245
246        // Add or remove authorities.
247        for(a in authMap) {
248            if(a.value == "add")
249                Authority.findByAuthority(a.key.toString()).addToPersons(person)
250            else
251                Authority.findByAuthority(a.key.toString()).removeFromPersons(person)
252        }
253    }
254
255    private Map buildPersonModel(person) {
256
257        List roles = getLimitedAuthorityList()
258        Set userRoleNames = []
259        for (role in person.authorities) {
260            userRoleNames << role.authority
261        }
262        LinkedHashMap<Authority, Boolean> roleMap = [:]
263        for (role in roles) {
264            roleMap[(role)] = userRoleNames.contains(role.authority)
265        }
266
267        return [person: person, roleMap: roleMap]
268    }
269
270    /**
271    * Get the full authorityList if current user is an App Admin else leave that authority off the list.
272    */
273    private List getLimitedAuthorityList() {
274        def authorityList = []
275        if(authenticateService.ifAnyGranted('ROLE_AppAdmin'))
276            authorityList = Authority.list().sort { p1, p2 -> p1.id <=> p2.id }
277        else
278            authorityList = Authority.withCriteria { gt("id", 1L) }.sort { p1, p2 -> p1.id <=> p2.id }
279
280        return authorityList
281    }
282} // end class
Note: See TracBrowser for help on using the repository browser.