<commit_before>/**
 * vithesaurus - web-based thesaurus management tool
 * Copyright (C) 2009 vionto GmbH, www.vionto.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */ 

import com.vionto.vithesaurus.*
import java.security.MessageDigest
            
class UserController extends BaseController {
    
    def beforeInterceptor = [action: this.&auth, 
                             except: ['login', 'register', 'doRegister', 'confirmRegistration']]

    static def allowedMethods = [delete:'POST', save:'POST', update:'POST', doRegister:'POST']

    def index = {
        redirect(action:list,params:params)
    }

    def register = {
      []
    }
    
    def doRegister = {
      if (!params.userId) {
        //FIXME: show clean error, not exception 
        throw new Exception("Parameter email missing")
      }
      if (!ThesaurusUser.findByUserId(params.userId)) {
        log.info("Creating user: " + params.userId)
        if (params.password1 != params.password2) {
          throw new Exception("Passwords don't match")
        }
        final int minPasswordLength = 4
        if (params.password1.length() < minPasswordLength) {
          throw new Exception("Password too short, must be ${minPasswordLength} or more")
        }
        def user = new ThesaurusUser(params.userId, UserController.md5sum(params.password1),
            ThesaurusUser.USER_PERM)
        user.confirmationDate = null
        // generate a random code:
        user.confirmationCode = ""
        for (int i = 0; i < 1; i++) {
          String partialCode = Math.random() + ""
          user.confirmationCode += partialCode.replace(".", "")
        }
        if (!user.validate()) {
          log.error("User validation failed: ${user.errors}")
        } else {
          boolean saved = user.save()
          if (!saved) {
            throw new Exception("Could not save user: ${user.errors}")
          }
        }
        String activationLink = grailsApplication.config.thesaurus.serverURL + "/user/confirmRegistration?userId=${user.id}&code=${user.confirmationCode}"
        sendMail {    
          from message(code:'user.register.email.from')
          to params.userId
          subject message(code:'user.register.email.subject')     
          body message(code:'user.register.email.body', args:[activationLink]) 
        }
        log.info("Sent registration mail to ${params.userId}, code ${user.confirmationCode}")
      } else {
        //FIXME: show clean error, not exception; i18n 
        throw new Exception("User ${params.userId} already exists")
      }
      [email: params.userId]
    }
    
    // called when clicking on the link in the email
    def confirmRegistration = {
      if (!params.userId || !params.code) {
        throw new Exception("Parameters userId and/or code missing")
      }
      log.info("Confirming registration for ${params.userId}, ${params.code}")
      def user = ThesaurusUser.get(params.userId)
      if (!user) {
        throw new Exception("User not found for id ${params.userId}")
      }
      if (user.confirmationDate) {
        log.warn("Confirming registration had happened before for ${params.userId}, ${params.code}")
        //FIXME: i18n
        flash.message = "Your user account has already been confirmed before"
        redirect(url:grailsApplication.config.thesaurus.serverURL)     // go to homepage
      } else {
        if (user.confirmationCode != params.code) {
          throw new Exception("Confirmation code invalid for ${params.userId}, ${params.code} != ${user.confirmationCode}")
        }
        user.confirmationDate = new Date()
        log.info("Confirming registration successful for ${params.userId}, ${params.code}")
        //FIXME: i18n
        //flash.message = "Your user account has been confirmed. You may now <a href='login'>log in</a>."
        flash.message = "Ihr Account wurde aktiviert - Sie können sich jetzt <a href='user/login'>einloggen</a>."
        redirect(url:grailsApplication.config.thesaurus.serverURL)     // go to homepage
      }
    }
    
    /**
     * Show login page for GET request, handle login (authenticate + redirect)
     * otherwise.
     */
    def login = {
        if (request.method == 'GET') {
          // show login page
          session.user = null
          if (params.controllerName && params.actionName) {
              session.controllerName = params.controllerName
              session.actionName = params.actionName
          }
          if (params.controllerName && params.actionName) {
              session.origId = params.origId
          }
          if (params.q) {
              session.origQuery = params.q
          }
          ThesaurusUser user = new ThesaurusUser()
        } else {
          ThesaurusUser user = 
              ThesaurusUser.findByUserIdAndPassword(params.userId, md5sum(params.password))
          if (user) {
            if (user.blocked) {
              log.warn("login failed for user ${params.userId} (${request.getRemoteAddr()}): user is blocked")
              // deliberately show same message as otherwise... 
              flash.message = message(code:'user.invalid.login')
              return
            }
            if (!user.confirmationDate) {
              log.warn("login failed for user ${params.userId} (${request.getRemoteAddr()}): account not confirmed")
              flash.message = message(code:'user.unconfirmed.login')
              return
            }
            log.info("login successful for user ${user}")
            flash.message = message(code:'user.logged.in')
            session.user = user
            user.lastLoginDate = new Date()
            def redirectParams = 
              session.origParams ? session.origParams : [uri:"/"]
            if (redirectParams?.origId) {
                redirectParams.id = redirectParams.origId
            }
            // TODO: there must be a better way for this "redirect after 
            // login" problem:
            if (redirectParams?.controller && redirectParams?.action) {
                redirect(controller:redirectParams?.controller,
                        action: redirectParams?.action, params:redirectParams)
            } else if (session.controllerName && session.actionName && session.origId) {<commit_msg>adding comment<commit_after>/**
 * vithesaurus - web-based thesaurus management tool
 * Copyright (C) 2009 vionto GmbH, www.vionto.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */ 

import com.vionto.vithesaurus.*
import java.security.MessageDigest
            
class UserController extends BaseController {
    
    def beforeInterceptor = [action: this.&auth, 
                             except: ['login', 'register', 'doRegister', 'confirmRegistration']]

    static def allowedMethods = [delete:'POST', save:'POST', update:'POST', doRegister:'POST']

    def index = {
        redirect(action:list,params:params)
    }

    def register = {
      []
    }
    
    def doRegister = {
      if (!params.userId) {
        //FIXME: show clean error, not exception 
        throw new Exception("Parameter email missing")
      }
      if (!ThesaurusUser.findByUserId(params.userId)) {
        log.info("Creating user: " + params.userId)
        if (params.password1 != params.password2) {
          throw new Exception("Passwords don't match")
        }
        final int minPasswordLength = 4
        if (params.password1.length() < minPasswordLength) {
          throw new Exception("Password too short, must be ${minPasswordLength} or more")
        }
        def user = new ThesaurusUser(params.userId, UserController.md5sum(params.password1),
            ThesaurusUser.USER_PERM)
        user.confirmationDate = null
        // generate a random code:
        user.confirmationCode = ""
        for (int i = 0; i < 1; i++) {
          String partialCode = Math.random() + ""
          user.confirmationCode += partialCode.replace(".", "")
        }
        if (!user.validate()) {
          log.error("User validation failed: ${user.errors}")
        } else {
          boolean saved = user.save()
          if (!saved) {
            throw new Exception("Could not save user: ${user.errors}")
          }
        }
        String activationLink = grailsApplication.config.thesaurus.serverURL + "/user/confirmRegistration?userId=${user.id}&code=${user.confirmationCode}"
        sendMail {    
          from message(code:'user.register.email.from')
          to params.userId
          subject message(code:'user.register.email.subject')     
          body message(code:'user.register.email.body', args:[activationLink]) 
        }
        log.info("Sent registration mail to ${params.userId}, code ${user.confirmationCode}")
      } else {
        //FIXME: show clean error, not exception; i18n 
        throw new Exception("User ${params.userId} already exists")
      }
      [email: params.userId]
    }
    
    // called when clicking on the link in the email
    def confirmRegistration = {
      if (!params.userId || !params.code) {
        throw new Exception("Parameters userId and/or code missing")
      }
      log.info("Confirming registration for ${params.userId}, ${params.code}")
      def user = ThesaurusUser.get(params.userId)
      if (!user) {
        throw new Exception("User not found for id ${params.userId}")
      }
      if (user.confirmationDate) {
        log.warn("Confirming registration had happened before for ${params.userId}, ${params.code}")
        //FIXME: i18n
        flash.message = "Your user account has already been confirmed before"
        redirect(url:grailsApplication.config.thesaurus.serverURL)     // go to homepage
      } else {
        if (user.confirmationCode != params.code) {
          throw new Exception("Confirmation code invalid for ${params.userId}, ${params.code} != ${user.confirmationCode}")
        }
        user.confirmationDate = new Date()
        log.info("Confirming registration successful for ${params.userId}, ${params.code}")
        //FIXME: i18n
        //flash.message = "Your user account has been confirmed. You may now <a href='login'>log in</a>."
        flash.message = "Ihr Account wurde aktiviert - Sie können sich jetzt <a href='user/login'>einloggen</a>."
        redirect(url:grailsApplication.config.thesaurus.serverURL)     // go to homepage
      }
    }
    
    /**
     * Show login page for GET request, handle login (authenticate + redirect)
     * otherwise.
     */
    def login = {
        if (request.method == 'GET') {
          // show login page
          session.user = null
          if (params.controllerName && params.actionName) {
              session.controllerName = params.controllerName
              session.actionName = params.actionName
          }
          if (params.controllerName && params.actionName) {
              session.origId = params.origId
          }
          if (params.q) {
              session.origQuery = params.q
          }
          ThesaurusUser user = new ThesaurusUser()
        } else {
          ThesaurusUser user = 
              ThesaurusUser.findByUserIdAndPassword(params.userId, md5sum(params.password))
          if (user) {
            if (user.blocked) {
              log.warn("login failed for user ${params.userId} (${request.getRemoteAddr()}): user is blocked")
              // deliberately show same message as otherwise... 
              flash.message = message(code:'user.invalid.login')
              return
            }
            if (!user.confirmationDate) {
              log.warn("login failed for user ${params.userId} (${request.getRemoteAddr()}): account not confirmed")
              flash.message = message(code:'user.unconfirmed.login')
              return
            }
            log.info("login successful for user ${user}")
            flash.message = message(code:'user.logged.in')
            session.user = user
            user.lastLoginDate = new Date()
            def redirectParams = 
              session.origParams ? session.origParams : [uri:"/"]
            if (redirectParams?.origId) {
                redirectParams.id = redirectParams.origId
            }
            // TODO: there must be a better way for this "redirect after 
            // login" problem (maybe "originalRequestParameters"?)
            if (redirectParams?.controller && redirectParams?.action) {
                redirect(controller:redirectParams?.controller,
                        action: redirectParams?.action, params:redirectParams)
            } else if (session.controllerName && session.actionName && session.origId) {
{'fraction_non_alphanumeric': 0.10890445583880985, 'fraction_numerical': 0.002888712356467105, 'mean_word_length': 2.255289139633286, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '360252', 'n_tokens_mistral': 3589, 'n_tokens_neox': 3576, 'n_words': 1029}