user.go 5.07 KB
Newer Older
zauberstuhl's avatar
zauberstuhl committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
package controllers
//
// GangGo Application Server
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

import (
Ghost User's avatar
Ghost User committed
21
  "regexp"
zauberstuhl's avatar
zauberstuhl committed
22
  "github.com/revel/revel"
23
  "github.com/dchest/captcha"
zauberstuhl's avatar
zauberstuhl committed
24 25
  "git.feneas.org/ganggo/ganggo/app/models"
  "git.feneas.org/ganggo/ganggo/app/helpers"
zauberstuhl's avatar
zauberstuhl committed
26
  "net/http"
zauberstuhl's avatar
zauberstuhl committed
27 28 29 30 31 32 33 34 35 36 37 38 39
)

type User struct {
  *revel.Controller
}

func (u User) Index() revel.Result {
  return u.Render()
}

func (u User) Create() revel.Result {
  var user models.User
  var username, password, verify string
40
  var captchaID, captchaValue string
zauberstuhl's avatar
zauberstuhl committed
41

42
  db, err := models.OpenDatabase()
zauberstuhl's avatar
zauberstuhl committed
43 44
  if err != nil {
    revel.WARN.Println(err)
45 46
    u.Log.Error("Cannot open database", "error", err)
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
47 48 49 50 51 52 53
  }
  defer db.Close()

  u.Params.Bind(&username, "username")
  u.Params.Bind(&password, "password")
  u.Params.Bind(&verify, "confirm")

54 55 56
  u.Params.Bind(&captchaID, "captchaID")
  u.Params.Bind(&captchaValue, "captchaValue")

57
  if !revel.DevMode && !captcha.VerifyString(captchaID, captchaValue) {
58 59 60 61 62 63
    u.Flash.Error(u.Message("flash.errors.captcha"))
    return u.Redirect(User.Index)
  }

  if _, exists := helpers.UserBlacklist[username]; exists {
    u.Flash.Error(u.Message("flash.errors.username"))
zauberstuhl's avatar
zauberstuhl committed
64
    u.Response.Status = http.StatusResetContent
65 66 67
    return u.Redirect(User.Index)
  }

Ghost User's avatar
Ghost User committed
68 69 70 71 72 73 74
  // only allow alphabet, numeric and dash characters
  validUsername := regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
  if !validUsername.MatchString(username) {
    u.Flash.Error(u.Message("flash.errors.username"))
    return u.Redirect(User.Index)
  }

zauberstuhl's avatar
zauberstuhl committed
75
  if !db.Where("username = ?", username).First(&user).RecordNotFound() {
76
    u.Flash.Error(u.Message("flash.errors.username"))
zauberstuhl's avatar
zauberstuhl committed
77 78 79 80
    return u.Redirect(User.Index)
  }

  if password == "" || password != verify {
81
    u.Flash.Error(u.Message("flash.errors.password_empty"))
zauberstuhl's avatar
zauberstuhl committed
82 83 84 85
    return u.Redirect(User.Index)
  }

  if len(password) < 4 {
86
    u.Flash.Error(u.Message("flash.errors.password_length"))
zauberstuhl's avatar
zauberstuhl committed
87 88 89 90 91
    return u.Redirect(User.Index)
  }

  // build user struct
  user = models.User{
92
    Password: password,
zauberstuhl's avatar
zauberstuhl committed
93 94 95
    Username: username,
    Person: models.Person {
      Profile: models.Profile{
96
        Searchable: true,
zauberstuhl's avatar
zauberstuhl committed
97 98 99 100
        ImageUrl: "/public/img/avatar.png",
      },
    },
  }
101

zauberstuhl's avatar
zauberstuhl committed
102 103
  err = db.Create(&user).Error
  if err != nil {
104
    u.Log.Error("Cannot create user", "error", err)
zauberstuhl's avatar
zauberstuhl committed
105
    u.Response.Status = http.StatusInternalServerError
106
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
107
  }
108
  u.Flash.Success(u.Message("flash.success.registration"))
109
  return u.Redirect(User.Login)
zauberstuhl's avatar
zauberstuhl committed
110 111 112 113 114
}

func (u User) Logout() revel.Result {
  var session models.Session

115
  db, err := models.OpenDatabase()
zauberstuhl's avatar
zauberstuhl committed
116
  if err != nil {
117
    u.Log.Error("Cannot open database", "error", err)
zauberstuhl's avatar
zauberstuhl committed
118
    u.Response.Status = http.StatusInternalServerError
119
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
120 121 122 123 124
  }
  defer db.Close()

  err = db.Where("token = ?", u.Session["TOKEN"]).First(&session).Error
  if err != nil {
125
    u.Log.Error("Cannot find session", "error", err)
zauberstuhl's avatar
zauberstuhl committed
126
    u.Response.Status = http.StatusInternalServerError
127
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
128 129 130 131 132 133 134 135 136 137 138 139 140
  }
  db.Delete(&session)
  delete(u.Session, "TOKEN")
  return u.Redirect(App.Index)
}

func (u User) Login() revel.Result {
  var (
    username string
    password string
    user models.User
    session models.Session
  )
141 142 143 144 145 146

  // render the login screen on GET
  if u.Request.Method == "GET" {
    return u.Render()
  }

zauberstuhl's avatar
zauberstuhl committed
147 148 149
  u.Params.Bind(&username, "username")
  u.Params.Bind(&password, "password")

150
  db, err := models.OpenDatabase()
zauberstuhl's avatar
zauberstuhl committed
151
  if err != nil {
152
    u.Log.Error("Cannot open database", "error", err)
zauberstuhl's avatar
zauberstuhl committed
153
    u.Response.Status = http.StatusInternalServerError
154
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
155 156 157 158 159
  }
  defer db.Close()

  err = db.Where("username = ?", username).First(&user).Error
  if err != nil {
160 161
    u.Flash.Error(u.Message(
      "flash.errors.username_not_found",  username))
162
    return u.Redirect(User.Login)
zauberstuhl's avatar
zauberstuhl committed
163 164
  }

165
  if !helpers.CheckHash(password, user.EncryptedPassword) {
166
    u.Flash.Error(u.Message("flash.errors.login_failed"))
167
    return u.Redirect(User.Login)
zauberstuhl's avatar
zauberstuhl committed
168 169 170 171
  }

  token, err := helpers.Uuid()
  if err != nil {
172
    u.Log.Error("Cannot generate UUID", "error", err)
zauberstuhl's avatar
zauberstuhl committed
173
    u.Response.Status = http.StatusInternalServerError
174
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
175 176 177 178 179 180
  }
  session.UserID = user.ID
  session.Token = token

  err = db.Create(&session).Error
  if err != nil {
181
    u.Log.Error("Cannot create session", "error", err)
zauberstuhl's avatar
zauberstuhl committed
182
    u.Response.Status = http.StatusInternalServerError
183
    return u.RenderError(err)
zauberstuhl's avatar
zauberstuhl committed
184
  }
185 186
  u.Session["TOKEN"] = session.Token

187
  u.Flash.Success(u.Message("flash.success.login"))
zauberstuhl's avatar
zauberstuhl committed
188 189
  return u.Redirect(Stream.Index)
}