Index: branches/TaskRewrite/src/grails-app/controllers/AuthorityController.groovy
===================================================================
--- branches/TaskRewrite/src/grails-app/controllers/AuthorityController.groovy	(revision 58)
+++ branches/TaskRewrite/src/grails-app/controllers/AuthorityController.groovy	(revision 58)
@@ -0,0 +1,123 @@
+
+
+
+/**
+ * Authority Controller.
+ */
+class AuthorityController {
+
+	// the delete, save and update actions only accept POST requests
+	static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
+
+	def authenticateService
+
+	def index = {
+		redirect action: list, params: params
+	}
+
+	/**
+	 * Display the list authority page.
+	 */
+	def list = {
+		if (!params.max) {
+			params.max = 10
+		}
+		[authorityList: Authority.list(params)]
+	}
+
+	/**
+	 * Display the show authority page.
+	 */
+	def show = {
+		def authority = Authority.get(params.id)
+		if (!authority) {
+			flash.message = "Authority not found with id $params.id"
+			redirect action: list
+			return
+		}
+
+		[authority: authority]
+	}
+
+	/**
+	 * Delete an authority.
+	 */
+	def delete = {
+		def authority = Authority.get(params.id)
+		if (!authority) {
+			flash.message = "Authority not found with id $params.id"
+			redirect action: list
+			return
+		}
+
+		authenticateService.deleteRole(authority)
+
+		flash.message = "Authority $params.id deleted."
+		redirect action: list
+	}
+
+	/**
+	 * Display the edit authority page.
+	 */
+	def edit = {
+		def authority = Authority.get(params.id)
+		if (!authority) {
+			flash.message = "Authority not found with id $params.id"
+			redirect action: list
+			return
+		}
+
+		[authority: authority]
+	}
+
+	/**
+	 * Authority update action.
+	 */
+	def update = {
+
+		def authority = Authority.get(params.id)
+		if (!authority) {
+			flash.message = "Authority not found with id $params.id"
+			redirect action: edit, id: params.id
+			return
+		}
+
+		long version = params.version.toLong()
+		if (authority.version > version) {
+			authority.errors.rejectValue 'version', 'authority.optimistic.locking.failure',
+				'Another user has updated this Authority while you were editing.'
+			render view: 'edit', model: [authority: authority]
+			return
+		}
+
+		if (authenticateService.updateRole(authority, params)) {
+			authenticateService.clearCachedRequestmaps()
+			redirect action: show, id: authority.id
+		}
+		else {
+			render view: 'edit', model: [authority: authority]
+		}
+	}
+
+	/**
+	 * Display the create new authority page.
+	 */
+	def create = {
+		[authority: new Authority()]
+	}
+
+	/**
+	 * Save a new authority.
+	 */
+	def save = {
+
+		def authority = new Authority()
+		authority.properties = params
+		if (authority.save()) {
+			redirect action: show, id: authority.id
+		}
+		else {
+			render view: 'create', model: [authority: authority]
+		}
+	}
+}
Index: branches/TaskRewrite/src/grails-app/controllers/LoginController.groovy
===================================================================
--- branches/TaskRewrite/src/grails-app/controllers/LoginController.groovy	(revision 58)
+++ branches/TaskRewrite/src/grails-app/controllers/LoginController.groovy	(revision 58)
@@ -0,0 +1,179 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.RedirectUtils
+import org.grails.plugins.springsecurity.service.AuthenticateService
+
+import org.springframework.security.AuthenticationTrustResolverImpl
+import org.springframework.security.DisabledException
+import org.springframework.security.context.SecurityContextHolder as SCH
+import org.springframework.security.ui.AbstractProcessingFilter
+import org.springframework.security.ui.webapp.AuthenticationProcessingFilter
+
+/**
+ * Login Controller (Example).
+ */
+class LoginController {
+
+	/**
+	 * Dependency injection for the authentication service.
+	 */
+	def authenticateService
+
+	/**
+	 * Dependency injection for OpenIDConsumer.
+	 */
+	def openIDConsumer
+
+	/**
+	 * Dependency injection for OpenIDAuthenticationProcessingFilter.
+	 */
+	def openIDAuthenticationProcessingFilter
+
+	private final authenticationTrustResolver = new AuthenticationTrustResolverImpl()
+
+	def index = {
+		if (isLoggedIn()) {
+			redirect uri: '/'
+		}
+		else {
+			redirect action: auth, params: params
+		}
+	}
+
+	/**
+	 * Show the login page.
+	 */
+	def auth = {
+
+		nocache response
+
+		if (isLoggedIn()) {
+			redirect uri: '/'
+			return
+		}
+
+		String view
+		String postUrl
+		def config = authenticateService.securityConfig.security
+		if (config.useOpenId) {
+			view = 'openIdAuth'
+			postUrl = "${request.contextPath}/login/openIdAuthenticate"
+		}
+		else if (config.useFacebook) {
+			view = 'facebookAuth'
+			postUrl = "${request.contextPath}${config.facebook.filterProcessesUrl}"
+		}
+		else {
+			view = 'auth'
+			postUrl = "${request.contextPath}${config.filterProcessesUrl}"
+		}
+
+		render view: view, model: [postUrl: postUrl]
+	}
+
+	/**
+	 * Form submit action to start an OpenID authentication.
+	 */
+	def openIdAuthenticate = {
+		String openID = params['j_username']
+		try {
+			String returnToURL = RedirectUtils.buildRedirectUrl(
+					request, response, openIDAuthenticationProcessingFilter.filterProcessesUrl)
+			String redirectUrl = openIDConsumer.beginConsumption(request, openID, returnToURL)
+			redirect url: redirectUrl
+		}
+		catch (org.springframework.security.ui.openid.OpenIDConsumerException e) {
+			log.error "Consumer error: $e.message", e
+			redirect url: openIDAuthenticationProcessingFilter.authenticationFailureUrl
+		}
+	}
+
+	// Login page (function|json) for Ajax access.
+	def authAjax = {
+		nocache(response)
+		//this is example:
+		render """
+		<script type='text/javascript'>
+		(function() {
+			loginForm();
+		})();
+		</script>
+		"""
+	}
+
+	/**
+	 * The Ajax success redirect url.
+	 */
+	def ajaxSuccess = {
+		nocache(response)
+		render '{success: true}'
+	}
+
+	/**
+	 * Show denied page.
+	 */
+	def denied = {
+		if (isLoggedIn() && authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
+			// have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
+			redirect action: full, params: params
+		}
+	}
+
+	/**
+	 * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
+	 */
+	def full = {
+		render view: 'auth', params: params,
+			model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication)]
+	}
+
+	// Denial page (data|view|json) for Ajax access.
+	def deniedAjax = {
+		//this is example:
+		render "{error: 'access denied'}"
+	}
+
+	/**
+	 * login failed
+	 */
+	def authfail = {
+
+		def username = session[AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
+		def msg = ''
+		def exception = session[AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY]
+		if (exception) {
+			if (exception instanceof DisabledException) {
+				msg = "[$username] is disabled."
+			}
+			else {
+				msg = "[$username] wrong username/password."
+			}
+		}
+
+		if (isAjax()) {
+			render "{error: '${msg}'}"
+		}
+		else {
+			flash.message = msg
+			redirect action: auth, params: params
+		}
+	}
+
+	/**
+	 * Check if logged in.
+	 */
+	private boolean isLoggedIn() {
+		return authenticateService.isLoggedIn()
+	}
+
+	private boolean isAjax() {
+		return authenticateService.isAjax(request)
+	}
+
+	/** cache controls */
+	private void nocache(response) {
+		response.setHeader('Cache-Control', 'no-cache') // HTTP 1.1
+		response.addDateHeader('Expires', 0)
+		response.setDateHeader('max-age', 0)
+		response.setIntHeader ('Expires', -1) //prevents caching at the proxy server
+		response.addHeader('cache-Control', 'private') //IE5.x only
+	}
+}
Index: branches/TaskRewrite/src/grails-app/controllers/LogoutController.groovy
===================================================================
--- branches/TaskRewrite/src/grails-app/controllers/LogoutController.groovy	(revision 58)
+++ branches/TaskRewrite/src/grails-app/controllers/LogoutController.groovy	(revision 58)
@@ -0,0 +1,13 @@
+/**
+ * Logout Controller (Example).
+ */
+class LogoutController {
+
+	/**
+	 * Index action. Redirects to the Spring security logout uri.
+	 */
+	def index = {
+		// TODO  put any pre-logout code here
+		redirect(uri: '/j_spring_security_logout')
+	}
+}
Index: branches/TaskRewrite/src/grails-app/controllers/PersonController.groovy
===================================================================
--- branches/TaskRewrite/src/grails-app/controllers/PersonController.groovy	(revision 58)
+++ branches/TaskRewrite/src/grails-app/controllers/PersonController.groovy	(revision 58)
@@ -0,0 +1,162 @@
+
+
+
+/**
+ * User controller.
+ */
+class PersonController {
+
+	def authenticateService
+
+	// the delete, save and update actions only accept POST requests
+	static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
+
+	def index = {
+		redirect action: list, params: params
+	}
+
+	def list = {
+		if (!params.max) {
+			params.max = 10
+		}
+		[personList: Person.list(params)]
+	}
+
+	def show = {
+		def person = Person.get(params.id)
+		if (!person) {
+			flash.message = "Person not found with id $params.id"
+			redirect action: list
+			return
+		}
+		List roleNames = []
+		for (role in person.authorities) {
+			roleNames << role.authority
+		}
+		roleNames.sort { n1, n2 ->
+			n1 <=> n2
+		}
+		[person: person, roleNames: roleNames]
+	}
+
+	/**
+	 * Person delete action. Before removing an existing person,
+	 * he should be removed from those authorities which he is involved.
+	 */
+	def delete = {
+
+		def person = Person.get(params.id)
+		if (person) {
+			def authPrincipal = authenticateService.principal()
+			//avoid self-delete if the logged-in user is an admin
+			if (!(authPrincipal instanceof String) && authPrincipal.username == person.loginName) {
+				flash.message = "You can not delete yourself, please login as another admin and try again"
+			}
+			else {
+				//first, delete this person from Persons_Authorities table.
+				Authority.findAll().each { it.removeFromPersons(person) }
+				person.delete()
+				flash.message = "Person $params.id deleted."
+			}
+		}
+		else {
+			flash.message = "Person not found with id $params.id"
+		}
+
+		redirect action: list
+	}
+
+	def edit = {
+
+		def person = Person.get(params.id)
+		if (!person) {
+			flash.message = "Person not found with id $params.id"
+			redirect action: list
+			return
+		}
+
+		return buildPersonModel(person)
+	}
+
+	/**
+	 * Person update action.
+	 */
+	def update = {
+
+		def person = Person.get(params.id)
+		if (!person) {
+			flash.message = "Person not found with id $params.id"
+			redirect action: edit, id: params.id
+			return
+		}
+
+		long version = params.version.toLong()
+		if (person.version > version) {
+			person.errors.rejectValue 'version', "person.optimistic.locking.failure",
+				"Another user has updated this Person while you were editing."
+				render view: 'edit', model: buildPersonModel(person)
+			return
+		}
+
+		def oldPassword = person.password
+		person.properties = params
+		if (!params.password.equals(oldPassword)) {
+			person.password = authenticateService.encodePassword(params.password)
+		}
+		if (person.save()) {
+			Authority.findAll().each { it.removeFromPersons(person) }
+			addRoles(person)
+			redirect action: show, id: person.id
+		}
+		else {
+			render view: 'edit', model: buildPersonModel(person)
+		}
+	}
+
+	def create = {
+		[person: new Person(params), authorityList: Authority.list()]
+	}
+
+	/**
+	 * Person save action.
+	 */
+	def save = {
+
+		def person = new Person()
+		person.properties = params
+		person.password = authenticateService.encodePassword(params.password)
+		if (person.save()) {
+			addRoles(person)
+			redirect action: show, id: person.id
+		}
+		else {
+			render view: 'create', model: [authorityList: Authority.list(), person: person]
+		}
+	}
+
+	private void addRoles(person) {
+		for (String key in params.keySet()) {
+			if (key.contains('ROLE') && 'on' == params.get(key)) {
+				Authority.findByAuthority(key).addToPersons(person)
+			}
+		}
+	}
+
+	private Map buildPersonModel(person) {
+
+		List roles = Authority.list()
+		roles.sort { r1, r2 ->
+			r1.authority <=> r2.authority
+		}
+		Set userRoleNames = []
+		for (role in person.authorities) {
+			userRoleNames << role.authority
+		}
+		LinkedHashMap<Authority, Boolean> roleMap = [:]
+		for (role in roles) {
+			roleMap[(role)] = userRoleNames.contains(role.authority)
+		}
+
+		return [person: person, roleMap: roleMap]
+	}
+}
