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

Revision 628, 8.6 KB checked in by gav, 4 years ago (diff)

Full authorisation review.
Add manager role to BaseController.
Remove inventory manager role from CostCode controller as per ticket #77.
Remove inventory manager role from InventoryGroup controller CUD actions.
Add all manager roles to Address and Contact controllers.
Add production and task manager roles to ProductionReference controller.

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.message = "You cannot delete yourself, please login as another manager and try again."
97                redirect(action:show,id:params.id)
98            }
99            else {
100                //first, delete this person from Persons_Authorities table.
101                Authority.findAll().each { it.removeFromPersons(person) }
102                person.isActive = false
103                person.save(flush: true)
104
105                try {
106                    person.delete(flush: true)
107                    flash.message = "Person $params.id deleted."
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                }
114            }
115        }
116        else {
117            flash.message = "Person not found with id $params.id"
118        }
119    }
120
121    def edit = {
122
123        // In the case of an actionSubmit button, rewrite action name from 'index'.
124        if(params._action_Edit)
125            params.action='edit'
126
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    }
136
137    /**
138    * Person update action.
139    */
140    def update = {
141        Person.withTransaction { status ->
142
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            }
149
150            long version = params.version.toLong()
151            if (person.version > version) {
152                person.errors.rejectValue 'version', "default.optimistic.locking.failure"
153                render view: 'edit', model: buildPersonModel(person)
154                return
155            }
156
157            person.properties = params
158            person.setPersonGroupsFromCheckBoxList(params.personGroups)
159
160            if(params.pass == "") {
161                person.pass = "InsertNothingToClearValidation"
162            }
163            else {
164                if (person.validate()) {
165                    person.password = authenticateService.encodePassword(params.pass)
166                }
167            }
168
169            if (!person.hasErrors() && person.save(flush: true)) {
170                addRemoveAuthorities(person)
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            }
177
178        } //end withTransaction
179    } // update()
180
181    def create = {
182        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
183        [person: new Person(params), authorityList: getLimitedAuthorityList()]
184    }
185
186    /**
187    * Person save action.
188    */
189    def save = {
190        Person.withTransaction { status ->
191
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)) {
197                addRemoveAuthorities(person)
198                redirect action: show, id: person.id
199            }
200            else {
201                render view: 'create', model: [person: person, authorityList: getLimitedAuthorityList()]
202            }
203
204        } //end withTransaction
205    }
206
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.
214        for (key in params.keySet()) {
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            }
221        }
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        }
230    }
231
232    private Map buildPersonModel(person) {
233
234        List roles = getLimitedAuthorityList()
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        }
243
244        return [person: person, roleMap: roleMap]
245    }
246
247    /**
248    * Get the full authorityList if current user is an App Admin else leave that authority off the list.
249    */
250    private List getLimitedAuthorityList() {
251        def authorityList = []
252        if(authenticateService.ifAnyGranted('ROLE_AppAdmin'))
253            authorityList = Authority.list().sort { p1, p2 -> p1.id <=> p2.id }
254        else
255            authorityList = Authority.withCriteria { gt("id", 1L) }.sort { p1, p2 -> p1.id <=> p2.id }
256
257        return authorityList
258    }
259} // end class
Note: See TracBrowser for help on using the repository browser.