Browse Source

Backport GoPX migration to GORM

Dashie der otter 8 months ago
parent
commit
18a3627913
Signed by: Dashie <dashie@sigpipe.me> GPG Key ID: C2D57B325840B755
14 changed files with 196 additions and 235 deletions
  1. 20
    19
      Gopkg.lock
  2. 0
    24
      Gopkg.toml
  3. 1
    1
      cmd/web.go
  4. 1
    2
      conf/app.ini
  5. 4
    2
      context/context.go
  6. 1
    1
      models/errors/user.go
  7. 40
    66
      models/models.go
  8. 1
    5
      models/models_sqlite.go
  9. 111
    102
      models/user.go
  10. 4
    4
      routers/user/auth.go
  11. 1
    1
      routers/user/setting.go
  12. 6
    6
      stuff/auth/auth.go
  13. 1
    1
      stuff/mailer/mail.go
  14. 5
    1
      stuff/template/template.go

+ 20
- 19
Gopkg.lock View File

@@ -88,24 +88,6 @@
88 88
   revision = "a0583e0143b1624142adab07e0e97fe106d99561"
89 89
   version = "v1.3"
90 90
 
91
-[[projects]]
92
-  name = "github.com/go-xorm/builder"
93
-  packages = ["."]
94
-  revision = "a9b7ffcca3f0c6445c4e3b1bf72c01578817a6c3"
95
-  version = "v0.1.0"
96
-
97
-[[projects]]
98
-  name = "github.com/go-xorm/core"
99
-  packages = ["."]
100
-  revision = "f43c33d9a48db006417a7ac4c16b08897e3e1458"
101
-  version = "v0.5.8"
102
-
103
-[[projects]]
104
-  name = "github.com/go-xorm/xorm"
105
-  packages = ["."]
106
-  revision = "fc1b13e0d8e240788213230aa5747eb557f80f41"
107
-  version = "v0.6.6"
108
-
109 91
 [[projects]]
110 92
   name = "github.com/gogits/cron"
111 93
   packages = ["."]
@@ -124,6 +106,24 @@
124 106
   packages = ["."]
125 107
   revision = "64a82a6d140778896f13303121a49d8cb8007034"
126 108
 
109
+[[projects]]
110
+  name = "github.com/jinzhu/gorm"
111
+  packages = [
112
+    ".",
113
+    "dialects/mssql",
114
+    "dialects/mysql",
115
+    "dialects/postgres",
116
+    "dialects/sqlite"
117
+  ]
118
+  revision = "6ed508ec6a4ecb3531899a69cbc746ccf65a4166"
119
+  version = "v1.9.1"
120
+
121
+[[projects]]
122
+  branch = "master"
123
+  name = "github.com/jinzhu/inflection"
124
+  packages = ["."]
125
+  revision = "04140366298a54a039076d798123ffa108fff46c"
126
+
127 127
 [[projects]]
128 128
   name = "github.com/jtolds/gls"
129 129
   packages = ["."]
@@ -135,6 +135,7 @@
135 135
   name = "github.com/lib/pq"
136 136
   packages = [
137 137
     ".",
138
+    "hstore",
138 139
     "oid"
139 140
   ]
140 141
   revision = "d34b9ff171c21ad295489235aec8b6626023cd04"
@@ -287,6 +288,6 @@
287 288
 [solve-meta]
288 289
   analyzer-name = "dep"
289 290
   analyzer-version = 1
290
-  inputs-digest = "99819157a3b8f3a5cd71cf759d8b24cc4d89703c9cb72b4afac3b5db41f71b12"
291
+  inputs-digest = "fe7d05c1bc31d42dbef4597c69e4bd8f54c6aa81548cc15292a0f2696ae94cc8"
291 292
   solver-name = "gps-cdcl"
292 293
   solver-version = 1

+ 0
- 24
Gopkg.toml View File

@@ -29,10 +29,6 @@
29 29
   name = "github.com/Unknwon/com"
30 30
   branch = "master"
31 31
 
32
-[[constraint]]
33
-  branch = "master"
34
-  name = "github.com/denisenkom/go-mssqldb"
35
-
36 32
 [[constraint]]
37 33
   branch = "master"
38 34
   name = "github.com/getsentry/raven-go"
@@ -61,18 +57,6 @@
61 57
   branch = "master"
62 58
   name = "github.com/go-macaron/toolbox"
63 59
 
64
-[[constraint]]
65
-  name = "github.com/go-sql-driver/mysql"
66
-  version = "1.3.0"
67
-
68
-[[constraint]]
69
-  name = "github.com/go-xorm/core"
70
-  version = "0.5.8"
71
-
72
-[[constraint]]
73
-  name = "github.com/go-xorm/xorm"
74
-  version = "0.6.6"
75
-
76 60
 [[constraint]]
77 61
   name = "github.com/gogits/cron"
78 62
   version = "1.0.0"
@@ -81,14 +65,6 @@
81 65
   branch = "master"
82 66
   name = "github.com/jaytaylor/html2text"
83 67
 
84
-[[constraint]]
85
-  branch = "master"
86
-  name = "github.com/lib/pq"
87
-
88
-[[constraint]]
89
-  name = "github.com/mattn/go-sqlite3"
90
-  version = "1.6.0"
91
-
92 68
 [[constraint]]
93 69
   branch = "master"
94 70
   name = "github.com/microcosm-cc/bluemonday"

+ 1
- 1
cmd/web.go View File

@@ -60,7 +60,7 @@ func newMacaron() *macaron.Macaron {
60 60
 		},
61 61
 	))
62 62
 
63
-	funcMap := template.NewFuncMap()
63
+	funcMap := template.NewFuncMap(m)
64 64
 	m.Use(macaron.Renderer(macaron.RenderOptions{
65 65
 		Directory:  path.Join(setting.StaticRootPath, "templates"),
66 66
 		Funcs:      funcMap,

+ 1
- 2
conf/app.ini View File

@@ -1,6 +1,5 @@
1 1
 APP_NAME = myapp
2 2
 CAN_REGISTER = true
3
-ANONYMOUS_CREATE = true
4 3
 ; Either "dev", "prod" or "test"
5 4
 RUN_MODE = dev
6 5
 
@@ -66,7 +65,7 @@ LEVEL =
66 65
 ; Webhook URL
67 66
 URL =
68 67
 
69
-[log.xorm]
68
+[log.gorm]
70 69
 ; Enable file rotation
71 70
 ROTATE = true
72 71
 ; Rotate every day

+ 4
- 2
context/context.go View File

@@ -27,7 +27,7 @@ type Context struct {
27 27
 	Flash   *session.Flash
28 28
 	Session session.Store
29 29
 
30
-	User *models.User // logged in user
30
+	User models.User // logged in user
31 31
 
32 32
 	IsLogged    bool
33 33
 	IsBasicAuth bool
@@ -186,7 +186,9 @@ func Contexter() macaron.Handler {
186 186
 		// Get user from session if logined.
187 187
 		ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Context, ctx.Session)
188 188
 
189
-		if ctx.User != nil {
189
+		log.Info("user ID %d", ctx.User.ID)
190
+
191
+		if ctx.User.ID > 0 {
190 192
 			ctx.IsLogged = true
191 193
 			ctx.Data["IsLogged"] = ctx.IsLogged
192 194
 			ctx.Data["UserIsAdmin"] = ctx.User.IsAdmin

+ 1
- 1
models/errors/user.go View File

@@ -22,7 +22,7 @@ func (err EmptyName) Error() string {
22 22
 
23 23
 // UserNotExist struct
24 24
 type UserNotExist struct {
25
-	UserID int64
25
+	UserID uint
26 26
 	Name   string
27 27
 }
28 28
 

+ 40
- 66
models/models.go View File

@@ -1,45 +1,28 @@
1 1
 package models
2 2
 
3 3
 import (
4
-	"database/sql"
5 4
 	"dev.sigpipe.me/dashie/myapp/setting"
6 5
 	"errors"
7 6
 	"fmt"
8
-	// mssql
9
-	_ "github.com/denisenkom/go-mssqldb"
10
-	// mysql
11
-	_ "github.com/go-sql-driver/mysql"
12
-	"github.com/go-xorm/core"
13
-	"github.com/go-xorm/xorm"
14
-	// Postgresql
15
-	_ "github.com/lib/pq"
7
+	"github.com/jinzhu/gorm"
16 8
 	log "gopkg.in/clog.v1"
17 9
 	"net/url"
18 10
 	"os"
19 11
 	"path"
20 12
 	"strings"
13
+	// mysql
14
+	_ "github.com/jinzhu/gorm/dialects/mysql"
15
+	// postgresql
16
+	_ "github.com/jinzhu/gorm/dialects/postgres"
17
+	// sqlite
18
+	_ "github.com/jinzhu/gorm/dialects/sqlite"
19
+	// mssql
20
+	_ "github.com/jinzhu/gorm/dialects/mssql"
21 21
 )
22 22
 
23
-// Engine represents a XORM engine or session.
24
-type Engine interface {
25
-	Delete(interface{}) (int64, error)
26
-	Exec(string, ...interface{}) (sql.Result, error)
27
-	Find(interface{}, ...interface{}) error
28
-	Get(interface{}) (bool, error)
29
-	Id(interface{}) *xorm.Session
30
-	In(string, ...interface{}) *xorm.Session
31
-	Insert(...interface{}) (int64, error)
32
-	InsertOne(interface{}) (int64, error)
33
-	Iterate(interface{}, xorm.IterFunc) error
34
-	Sql(string, ...interface{}) *xorm.Session
35
-	Table(interface{}) *xorm.Session
36
-	Where(interface{}, ...interface{}) *xorm.Session
37
-}
38
-
39 23
 // Vars
40 24
 var (
41
-	x         *xorm.Engine
42
-	tables    []interface{}
25
+	db        *gorm.DB
43 26
 	HasEngine bool
44 27
 
45 28
 	DbCfg struct {
@@ -49,16 +32,6 @@ var (
49 32
 	EnableSQLite3 bool
50 33
 )
51 34
 
52
-func init() {
53
-	tables = append(tables,
54
-		new(User))
55
-
56
-	gonicNames := []string{"SSL"}
57
-	for _, name := range gonicNames {
58
-		core.LintGonicMapper[name] = true
59
-	}
60
-}
61
-
62 35
 // LoadConfigs to init db
63 36
 func LoadConfigs() {
64 37
 	sec := setting.Cfg.Section("database")
@@ -112,7 +85,7 @@ func parseMSSQLHostPort(info string) (string, string) {
112 85
 	return host, port
113 86
 }
114 87
 
115
-func getEngine() (*xorm.Engine, error) {
88
+func getEngine() (*gorm.DB, error) {
116 89
 	connStr := ""
117 90
 	var Param = "?"
118 91
 	if strings.Contains(DbCfg.Name, Param) {
@@ -120,6 +93,7 @@ func getEngine() (*xorm.Engine, error) {
120 93
 	}
121 94
 	switch DbCfg.Type {
122 95
 	case "mysql":
96
+		// "user:password@/dbname?charset=utf8&parseTime=True&loc=Local"
123 97
 		if DbCfg.Host[0] == '/' { // looks like a unix socket
124 98
 			connStr = fmt.Sprintf("%s:%s@unix(%s)/%s%scharset=utf8&parseTime=true",
125 99
 				DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name, Param)
@@ -128,6 +102,7 @@ func getEngine() (*xorm.Engine, error) {
128 102
 				DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name, Param)
129 103
 		}
130 104
 	case "postgres":
105
+		// "host=myhost port=myport user=gorm dbname=gorm password=mypassword"
131 106
 		host, port := parsePostgreSQLHostPort(DbCfg.Host)
132 107
 		if host[0] == '/' { // looks like a unix socket
133 108
 			connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s",
@@ -137,6 +112,7 @@ func getEngine() (*xorm.Engine, error) {
137 112
 				url.QueryEscape(DbCfg.User), url.QueryEscape(DbCfg.Passwd), host, port, DbCfg.Name, Param, DbCfg.SSLMode)
138 113
 		}
139 114
 	case "mssql":
115
+		// "sqlserver://username:password@localhost:1433?database=dbname"
140 116
 		host, port := parseMSSQLHostPort(DbCfg.Host)
141 117
 		connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd)
142 118
 	case "sqlite3":
@@ -150,45 +126,47 @@ func getEngine() (*xorm.Engine, error) {
150 126
 	default:
151 127
 		return nil, fmt.Errorf("unknown database type: %s", DbCfg.Type)
152 128
 	}
153
-	return xorm.NewEngine(DbCfg.Type, connStr)
129
+	return gorm.Open(DbCfg.Type, connStr)
154 130
 }
155 131
 
156 132
 // NewTestEngine to test
157
-func NewTestEngine(x *xorm.Engine) (err error) {
158
-	x, err = getEngine()
133
+func NewTestEngine(db *gorm.DB) (err error) {
134
+	db, err = getEngine()
159 135
 	if err != nil {
160 136
 		return fmt.Errorf("connect to database: %v", err)
161 137
 	}
162 138
 
163
-	x.SetMapper(core.GonicMapper{})
164
-	return x.StoreEngine("InnoDB").Sync2(tables...)
139
+	return err
165 140
 }
166 141
 
167 142
 // SetEngine to use
168 143
 func SetEngine() (err error) {
169
-	x, err = getEngine()
144
+	db, err = getEngine()
170 145
 	if err != nil {
171 146
 		return fmt.Errorf("fail to connect to database: %v", err)
172 147
 	}
173 148
 
174
-	x.SetMapper(core.GonicMapper{})
175
-
176 149
 	// WARNING: for serv command, MUST remove the output to os.stdout,
177 150
 	// so use log file to instead print to stdout.
178
-	sec := setting.Cfg.Section("log.xorm")
179
-	logger, err := log.NewFileWriter(path.Join(setting.LogRootPath, "xorm.log"),
180
-		log.FileRotationConfig{
181
-			Rotate:  sec.Key("ROTATE").MustBool(true),
182
-			Daily:   sec.Key("ROTATE_DAILY").MustBool(true),
183
-			MaxSize: sec.Key("MAX_SIZE").MustInt64(100) * 1024 * 1024,
184
-			MaxDays: sec.Key("MAX_DAYS").MustInt64(3),
185
-		})
186
-	if err != nil {
187
-		return fmt.Errorf("fail to create 'xorm.log': %v", err)
188
-	}
189
-
190
-	x.SetLogger(xorm.NewSimpleLogger3(logger, xorm.DEFAULT_LOG_PREFIX, xorm.DEFAULT_LOG_FLAG, core.LOG_DEBUG))
191
-	x.ShowSQL(true)
151
+	//sec := setting.Cfg.Section("log.gorm")
152
+	//logger, err := log.New(log.FILE, log.FileConfig {
153
+	//		Level: log.TRACE,
154
+	//		BufferSize: 100,
155
+	//		Filename: path.Join(setting.LogRootPath, "gorm.log"),
156
+	//		FileRotationConfig: log.FileRotationConfig {
157
+	//			Rotate:  sec.Key("ROTATE").MustBool(true),
158
+	//			Daily:   sec.Key("ROTATE_DAILY").MustBool(true),
159
+	//			MaxSize: sec.Key("MAX_SIZE").MustInt64(100) * 1024 * 1024,
160
+	//			MaxDays: sec.Key("MAX_DAYS").MustInt64(3),
161
+	//		},
162
+	//	})
163
+	//if err != nil {
164
+	//	return fmt.Errorf("fail to create 'gorm.log': %v", err)
165
+	//}
166
+
167
+	db.LogMode(true)
168
+	// TODO logger with clog
169
+	//db.SetLogger(log.New(os.Stdout, "\r\n", 0))
192 170
 	return nil
193 171
 }
194 172
 
@@ -198,18 +176,14 @@ func NewEngine() (err error) {
198 176
 		return err
199 177
 	}
200 178
 
201
-	// TODO: here do migrations if any
202
-
203
-	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
204
-		return fmt.Errorf("sync database struct error: %v", err)
205
-	}
179
+	db.AutoMigrate(&User{})
206 180
 
207 181
 	return nil
208 182
 }
209 183
 
210 184
 // Ping pong
211 185
 func Ping() error {
212
-	return x.Ping()
186
+	return db.DB().Ping()
213 187
 }
214 188
 
215 189
 // InitDb from config

+ 1
- 5
models/models_sqlite.go View File

@@ -2,10 +2,6 @@
2 2
 
3 3
 package models
4 4
 
5
-import (
6
-	_ "github.com/mattn/go-sqlite3"
7
-)
8
-
9 5
 func init() {
10 6
 	EnableSQLite3 = true
11
-}
7
+}

+ 111
- 102
models/user.go View File

@@ -9,114 +9,98 @@ import (
9 9
 	"encoding/hex"
10 10
 	"fmt"
11 11
 	"github.com/Unknwon/com"
12
+	"github.com/jinzhu/gorm"
12 13
 	"golang.org/x/crypto/pbkdf2"
13 14
 	log "gopkg.in/clog.v1"
14 15
 	"strings"
15
-	"time"
16 16
 	"unicode/utf8"
17 17
 )
18 18
 
19 19
 // User struct
20 20
 type User struct {
21
-	ID        int64  `xorm:"pk autoincr"`
22
-	UserName  string `xorm:"UNIQUE NOT NULL"`
23
-	LowerName string `xorm:"UNIQUE NOT NULL"`
24
-	Email     string `xorm:"NOT NULL"`
21
+	gorm.Model
22
+	UserName  string `gorm:"UNIQUE;NOT NULL"`
23
+	LowerName string `gorm:"UNIQUE;NOT NULL"`
24
+	Email     string `gorm:"NOT NULL"`
25 25
 
26
-	Password string `xorm:"NOT NULL"`
27
-	Rands    string `xorm:"VARCHAR(10)"`
28
-	Salt     string `xorm:"VARCHAR(10)"`
26
+	Password string `gorm:"NOT NULL"`
27
+	Rands    string `gorm:"Size:10"`
28
+	Salt     string `gorm:"Size:10"`
29 29
 
30 30
 	// Permissions
31
-	IsAdmin  bool `xorm:"DEFAULT 0"`
32
-	IsActive bool `xorm:"DEFAULT 0"`
33
-
34
-	Created     time.Time `xorm:"-"`
35
-	CreatedUnix int64
36
-	Updated     time.Time `xorm:"-"`
37
-	UpdatedUnix int64
38
-}
39
-
40
-// BeforeInsert hooks
41
-func (user *User) BeforeInsert() {
42
-	user.CreatedUnix = time.Now().Unix()
43
-	user.UpdatedUnix = user.CreatedUnix
31
+	IsAdmin  bool `gorm:"DEFAULT:0"`
32
+	IsActive bool `gorm:"DEFAULT:0"`
44 33
 }
45 34
 
46
-// BeforeUpdate hooks
47
-func (user *User) BeforeUpdate() {
48
-	user.UpdatedUnix = time.Now().Unix()
49
-}
50
-
51
-func countUsers(e Engine) int64 {
52
-	count, _ := x.Count(new(User))
53
-	return count
35
+func countUsers(db *gorm.DB) (count int64) {
36
+	db.Model(&User{}).Select("id").Count(&count)
37
+	return
54 38
 }
55 39
 
56 40
 // CountUsers returns number of users.
57 41
 func CountUsers() int64 {
58
-	return countUsers(x)
42
+	return countUsers(db)
59 43
 }
60 44
 
61
-func getUserByID(e Engine, id int64) (*User, error) {
62
-	u := new(User)
63
-	has, err := e.Id(id).Get(u)
64
-	if err != nil {
65
-		return nil, err
66
-	} else if !has {
67
-		return nil, errors.UserNotExist{id, ""}
45
+func getUserByID(id uint) (user User, err error) {
46
+	err = db.Where("id = ?", id).First(&user).Error
47
+	if gorm.IsRecordNotFoundError(err) || user.ID == 0 {
48
+		return user, errors.UserNotExist{UserID: id, Name: ""}
49
+	} else if err != nil {
50
+		return user, err
68 51
 	}
69
-	return u, nil
52
+	return
70 53
 }
71 54
 
72 55
 // GetUserByID returns the user object by given ID if exists.
73
-func GetUserByID(id int64) (*User, error) {
74
-	return getUserByID(x, id)
56
+func GetUserByID(id uint) (User, error) {
57
+	return getUserByID(id)
75 58
 }
76 59
 
77 60
 // GetUserByName returns user by given name.
78
-func GetUserByName(name string) (*User, error) {
61
+func GetUserByName(name string) (user User, err error) {
79 62
 	if len(name) == 0 {
80
-		return nil, errors.UserNotExist{0, name}
63
+		return user, errors.UserNotExist{UserID: 0, Name: name}
81 64
 	}
82
-	u := &User{LowerName: strings.ToLower(name)}
83
-	has, err := x.Get(u)
84
-	if err != nil {
85
-		return nil, err
86
-	} else if !has {
87
-		return nil, errors.UserNotExist{0, name}
65
+	err = db.Where("lower_name = ?", strings.ToLower(name)).First(&user).Error
66
+	if gorm.IsRecordNotFoundError(err) || user.ID == 0 {
67
+		return user, errors.UserNotExist{UserID: 0, Name: name}
68
+	} else if err != nil {
69
+		return user, err
88 70
 	}
89
-	return u, nil
71
+	return
90 72
 }
91 73
 
92 74
 // GetUserByEmail returns the user object by given e-mail if exists.
93
-func GetUserByEmail(email string) (*User, error) {
75
+func GetUserByEmail(email string) (user User, err error) {
94 76
 	if len(email) == 0 {
95
-		return nil, errors.UserNotExist{0, "email"}
77
+		return user, errors.UserNotExist{UserID: 0, Name: email}
96 78
 	}
97
-
98
-	email = strings.ToLower(email)
99
-	user := &User{Email: email}
100
-	has, err := x.Get(user)
101
-	if err != nil {
102
-		return nil, err
103
-	}
104
-	if has {
105
-		return user, nil
79
+	err = db.Where("email = ?", strings.ToLower(email)).First(&user).Error
80
+	if gorm.IsRecordNotFoundError(err) || user.ID == 0 {
81
+		return user, errors.UserNotExist{UserID: 0, Name: email}
82
+	} else if err != nil {
83
+		return user, err
106 84
 	}
107
-
108
-	return nil, errors.UserNotExist{0, email}
85
+	return
109 86
 }
110 87
 
111 88
 // IsUserExist checks if given user name exist,
112 89
 // the user name should be noncased unique.
113 90
 // If uid is presented, then check will rule out that one,
114 91
 // it is used when update a user name in settings page.
115
-func IsUserExist(uid int64, name string) (bool, error) {
92
+func IsUserExist(uid int64, name string) (exist bool, err error) {
116 93
 	if len(name) == 0 {
117 94
 		return false, nil
118 95
 	}
119
-	return x.Where("id != ?", uid).Get(&User{LowerName: strings.ToLower(name)})
96
+	user := User{}
97
+	err = db.Where("id != ?", uid).Where(&User{LowerName: strings.ToLower(name)}).First(&user).Error
98
+	if gorm.IsRecordNotFoundError(err) || user.ID == 0 {
99
+		return false, nil
100
+	} else if err != nil {
101
+		return false, nil
102
+	}
103
+	return true, nil
120 104
 }
121 105
 
122 106
 var (
@@ -173,105 +157,130 @@ func GetUserSalt() (string, error) {
173 157
 }
174 158
 
175 159
 // CreateUser and do some validation
176
-func CreateUser(u *User) (err error) {
177
-	if err = IsUsableUsername(u.UserName); err != nil {
160
+func CreateUser(user *User) (err error) {
161
+	if err = IsUsableUsername(user.UserName); err != nil {
178 162
 		return err
179 163
 	}
180 164
 
181
-	isExist, err := IsUserExist(0, u.UserName)
165
+	isExist, err := IsUserExist(0, user.UserName)
182 166
 	if err != nil {
183 167
 		return err
184 168
 	} else if isExist {
185
-		return ErrUserAlreadyExist{u.UserName}
169
+		return ErrUserAlreadyExist{user.UserName}
186 170
 	}
187 171
 
188
-	u.Email = strings.ToLower(u.Email)
189
-	u.LowerName = strings.ToLower(u.UserName)
172
+	user.Email = strings.ToLower(user.Email)
173
+	user.LowerName = strings.ToLower(user.UserName)
190 174
 
191
-	if u.Rands, err = GetUserSalt(); err != nil {
175
+	if user.Rands, err = GetUserSalt(); err != nil {
192 176
 		return err
193 177
 	}
194
-	if u.Salt, err = GetUserSalt(); err != nil {
178
+	if user.Salt, err = GetUserSalt(); err != nil {
179
+		return err
180
+	}
181
+	user.EncodePasswd()
182
+
183
+	tx := db.Begin()
184
+	defer func() {
185
+		if r := recover(); r != nil {
186
+			tx.Rollback()
187
+		}
188
+	}()
189
+
190
+	if tx.Error != nil {
195 191
 		return err
196 192
 	}
197
-	u.EncodePasswd()
198 193
 
199
-	sess := x.NewSession()
200
-	defer sess.Close()
201
-	if err = sess.Begin(); err != nil {
194
+	if err := tx.Create(user).Error; err != nil {
195
+		tx.Rollback()
202 196
 		return err
203 197
 	}
204 198
 
205
-	if _, err = sess.Insert(u); err != nil {
199
+	if err := tx.Commit().Error; err != nil {
206 200
 		return err
207 201
 	}
208 202
 
209
-	return sess.Commit()
203
+	return err
210 204
 }
211 205
 
212 206
 // Update an user
213
-func updateUser(e Engine, u *User) error {
214
-	u.LowerName = strings.ToLower(u.UserName)
215
-	u.Email = strings.ToLower(u.Email)
216
-	_, err := e.Id(u.ID).AllCols().Update(u)
207
+func updateUser(db *gorm.DB, user *User) (err error) {
208
+	tx := db.Begin()
209
+	defer func() {
210
+		if r := recover(); r != nil {
211
+			tx.Rollback()
212
+		}
213
+	}()
214
+
215
+	if tx.Error != nil {
216
+		return err
217
+	}
218
+
219
+	if err := tx.Save(user).Error; err != nil {
220
+		tx.Rollback()
221
+		return err
222
+	}
223
+
224
+	if err := tx.Commit().Error; err != nil {
225
+		return err
226
+	}
227
+
217 228
 	return err
218 229
 }
219 230
 
220 231
 // UpdateUser with datas
221 232
 func UpdateUser(u *User) error {
222
-	return updateUser(x, u)
233
+	return updateUser(db, u)
223 234
 }
224 235
 
225 236
 // UserLogin validates user name and password.
226
-func UserLogin(username, password string) (*User, error) {
227
-	var user *User
237
+func UserLogin(username, password string) (user *User, err error) {
228 238
 	if strings.Contains(username, "@") {
229 239
 		user = &User{Email: strings.ToLower(username)}
230 240
 	} else {
231 241
 		user = &User{LowerName: strings.ToLower(username)}
232 242
 	}
233 243
 
234
-	hasUser, err := x.Get(user)
235
-	if err != nil {
244
+	err = db.Where(user).First(&user).Error
245
+	if gorm.IsRecordNotFoundError(err) {
246
+		return nil, errors.UserNotExist{UserID: user.ID, Name: user.UserName}
247
+	} else if err != nil {
236 248
 		return nil, err
237 249
 	}
238 250
 
239
-	if hasUser {
240
-		if user.ValidatePassword(password) {
241
-			return user, nil
242
-		}
243
-
244
-		return nil, errors.UserNotExist{user.ID, user.UserName}
251
+	if user.ValidatePassword(password) {
252
+		return user, nil
245 253
 	}
246 254
 
247
-	return nil, errors.UserNotExist{user.ID, user.UserName}
255
+	return nil, errors.UserNotExist{UserID: user.ID, Name: user.UserName}
256
+
248 257
 }
249 258
 
250 259
 // get user by verify code
251
-func getVerifyUser(code string) (user *User) {
260
+func getVerifyUser(code string) (user User) {
252 261
 	if len(code) <= tool.TimeLimitCodeLength {
253
-		return nil
262
+		return user
254 263
 	}
255 264
 
256 265
 	// use tail hex username query user
257 266
 	hexStr := code[tool.TimeLimitCodeLength:]
258 267
 	if b, err := hex.DecodeString(hexStr); err == nil {
259
-		if user, err = GetUserByName(string(b)); user != nil {
268
+		if user, err = GetUserByName(string(b)); user.ID > 0 {
260 269
 			return user
261 270
 		} else if !errors.IsUserNotExist(err) {
262 271
 			log.Error(2, "GetUserByName: %v", err)
263 272
 		}
264 273
 	}
265 274
 
266
-	return nil
275
+	return user
267 276
 }
268 277
 
269 278
 // VerifyUserActiveCode when active account
270
-func VerifyUserActiveCode(code string) (user *User) {
279
+func VerifyUserActiveCode(code string) (user User) {
271 280
 	// HARDCODED
272 281
 	minutes := 180
273 282
 
274
-	if user = getVerifyUser(code); user != nil {
283
+	if user = getVerifyUser(code); user.ID > 0 {
275 284
 		// time limit code
276 285
 		prefix := code[:tool.TimeLimitCodeLength]
277 286
 		data := com.ToStr(user.ID) + user.Email + user.LowerName + user.Password + user.Rands
@@ -280,7 +289,7 @@ func VerifyUserActiveCode(code string) (user *User) {
280 289
 			return user
281 290
 		}
282 291
 	}
283
-	return nil
292
+	return user
284 293
 }
285 294
 
286 295
 // GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
@@ -304,7 +313,7 @@ type mailerUser struct {
304 313
 }
305 314
 
306 315
 // ID id
307
-func (mUser mailerUser) ID() int64 {
316
+func (mUser mailerUser) ID() uint {
308 317
 	return mUser.user.ID
309 318
 }
310 319
 

+ 4
- 4
routers/user/auth.go View File

@@ -206,7 +206,7 @@ func RegisterPost(ctx *context.Context, f form.Register) {
206 206
 		}
207 207
 		return
208 208
 	}
209
-	log.Trace("Account created: %s", u.UserName)
209
+	log.Trace("Account created: %d/%s", u.ID, u.UserName)
210 210
 
211 211
 	// Auto set Admin if first user
212 212
 	if models.CountUsers() == 1 {
@@ -258,7 +258,7 @@ func ResetPasswdPost(ctx *context.Context) {
258 258
 	}
259 259
 	ctx.Data["Code"] = code
260 260
 
261
-	if u := models.VerifyUserActiveCode(code); u != nil {
261
+	if u := models.VerifyUserActiveCode(code); u.ID > 0 {
262 262
 		// Validate password length.
263 263
 		passwd := ctx.Query("password")
264 264
 		if len(passwd) < 6 {
@@ -279,7 +279,7 @@ func ResetPasswdPost(ctx *context.Context) {
279 279
 			return
280 280
 		}
281 281
 		u.EncodePasswd()
282
-		if err := models.UpdateUser(u); err != nil {
282
+		if err := models.UpdateUser(&u); err != nil {
283 283
 			ctx.Handle(500, "UpdateUser", err)
284 284
 			return
285 285
 		}
@@ -342,7 +342,7 @@ func ForgotPasswdPost(ctx *context.Context) {
342 342
 		return
343 343
 	}
344 344
 
345
-	mailer.SendResetPasswordMail(ctx.Context, models.NewMailerUser(u))
345
+	mailer.SendResetPasswordMail(ctx.Context, models.NewMailerUser(&u))
346 346
 	if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
347 347
 		log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
348 348
 	}

+ 1
- 1
routers/user/setting.go View File

@@ -30,7 +30,7 @@ func SettingsPost(ctx *context.Context, f form.UpdateSettingsProfile) {
30 30
 	}
31 31
 
32 32
 	ctx.User.Email = f.Email
33
-	if err := models.UpdateUser(ctx.User); err != nil {
33
+	if err := models.UpdateUser(&ctx.User); err != nil {
34 34
 		ctx.ServerError("UpdateUser", err)
35 35
 		return
36 36
 	}

+ 6
- 6
stuff/auth/auth.go View File

@@ -20,7 +20,7 @@ func IsAPIPath(url string) bool {
20 20
 }
21 21
 
22 22
 // SignedInID returns the id of signed in user.
23
-func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
23
+func SignedInID(ctx *macaron.Context, sess session.Store) uint {
24 24
 	if !models.HasEngine {
25 25
 		return 0
26 26
 	}
@@ -29,7 +29,7 @@ func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
29 29
 	if uid == nil {
30 30
 		return 0
31 31
 	}
32
-	if id, ok := uid.(int64); ok {
32
+	if id, ok := uid.(uint); ok {
33 33
 		if _, err := models.GetUserByID(id); err != nil {
34 34
 			if !errors.IsUserNotExist(err) {
35 35
 				log.Error(2, "GetUserByID: %v", err)
@@ -43,21 +43,21 @@ func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
43 43
 
44 44
 // SignedInUser returns the user object of signed user.
45 45
 // It returns a bool value to indicate whether user uses basic auth or not.
46
-func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) {
46
+func SignedInUser(ctx *macaron.Context, sess session.Store) (user models.User, basicAuth bool) {
47 47
 	if !models.HasEngine {
48
-		return nil, false
48
+		return user, false
49 49
 	}
50 50
 
51 51
 	uid := SignedInID(ctx, sess)
52 52
 
53 53
 	if uid <= 0 {
54
-		return nil, false
54
+		return user, false
55 55
 	}
56 56
 
57 57
 	u, err := models.GetUserByID(uid)
58 58
 	if err != nil {
59 59
 		log.Error(4, "GetUserById: %v", err)
60
-		return nil, false
60
+		return u, false
61 61
 	}
62 62
 	return u, false
63 63
 }

+ 1
- 1
stuff/mailer/mail.go View File

@@ -53,7 +53,7 @@ func SendTestMail(email string) error {
53 53
 
54 54
 // User is email user
55 55
 type User interface {
56
-	ID() int64
56
+	ID() uint
57 57
 	DisplayName() string
58 58
 	Email() string
59 59
 	GenerateActivateCode() string

+ 5
- 1
stuff/template/template.go View File

@@ -8,6 +8,7 @@ import (
8 8
 	"dev.sigpipe.me/dashie/myapp/stuff/tool"
9 9
 	"fmt"
10 10
 	"github.com/microcosm-cc/bluemonday"
11
+	"gopkg.in/macaron.v1"
11 12
 	"html/template"
12 13
 	"mime"
13 14
 	"path/filepath"
@@ -17,7 +18,7 @@ import (
17 18
 )
18 19
 
19 20
 // NewFuncMap initialize the Functions Map
20
-func NewFuncMap() []template.FuncMap {
21
+func NewFuncMap(m *macaron.Macaron) []template.FuncMap {
21 22
 	return []template.FuncMap{map[string]interface{}{
22 23
 		"GoVer": func() string {
23 24
 			return strings.Title(runtime.Version())
@@ -97,6 +98,9 @@ func NewFuncMap() []template.FuncMap {
97 98
 		"IsPdf": func(mime string) bool {
98 99
 			return strings.EqualFold(mime, "application/pdf")
99 100
 		},
101
+		"URLFor": func(name string, pairs ...string) string {
102
+			return fmt.Sprintf("%s%s", strings.TrimSuffix(setting.AppURL, "/"), m.URLFor(name, pairs...))
103
+		},
100 104
 	}}
101 105
 }
102 106
 

Loading…
Cancel
Save