439b1afb by asta.xie

Merge branch 'release/1.1.1'

2 parents c358c180 745e9fb0
...@@ -12,7 +12,7 @@ import ( ...@@ -12,7 +12,7 @@ import (
12 ) 12 )
13 13
14 // beego web framework version. 14 // beego web framework version.
15 const VERSION = "1.1.0" 15 const VERSION = "1.1.1"
16 16
17 type hookfunc func() error //hook function to run 17 type hookfunc func() error //hook function to run
18 var hooks []hookfunc //hook function slice to store the hookfunc 18 var hooks []hookfunc //hook function slice to store the hookfunc
...@@ -28,12 +28,12 @@ type GroupRouters []groupRouter ...@@ -28,12 +28,12 @@ type GroupRouters []groupRouter
28 28
29 // Get a new GroupRouters 29 // Get a new GroupRouters
30 func NewGroupRouters() GroupRouters { 30 func NewGroupRouters() GroupRouters {
31 return make([]groupRouter, 0) 31 return make(GroupRouters, 0)
32 } 32 }
33 33
34 // Add Router in the GroupRouters 34 // Add Router in the GroupRouters
35 // it is for plugin or module to register router 35 // it is for plugin or module to register router
36 func (gr GroupRouters) AddRouter(pattern string, c ControllerInterface, mappingMethod ...string) { 36 func (gr *GroupRouters) AddRouter(pattern string, c ControllerInterface, mappingMethod ...string) {
37 var newRG groupRouter 37 var newRG groupRouter
38 if len(mappingMethod) > 0 { 38 if len(mappingMethod) > 0 {
39 newRG = groupRouter{ 39 newRG = groupRouter{
...@@ -48,16 +48,16 @@ func (gr GroupRouters) AddRouter(pattern string, c ControllerInterface, mappingM ...@@ -48,16 +48,16 @@ func (gr GroupRouters) AddRouter(pattern string, c ControllerInterface, mappingM
48 "", 48 "",
49 } 49 }
50 } 50 }
51 gr = append(gr, newRG) 51 *gr = append(*gr, newRG)
52 } 52 }
53 53
54 func (gr GroupRouters) AddAuto(c ControllerInterface) { 54 func (gr *GroupRouters) AddAuto(c ControllerInterface) {
55 newRG := groupRouter{ 55 newRG := groupRouter{
56 "", 56 "",
57 c, 57 c,
58 "", 58 "",
59 } 59 }
60 gr = append(gr, newRG) 60 *gr = append(*gr, newRG)
61 } 61 }
62 62
63 // AddGroupRouter with the prefix 63 // AddGroupRouter with the prefix
......
...@@ -147,6 +147,8 @@ func (this *FileCache) Get(key string) interface{} { ...@@ -147,6 +147,8 @@ func (this *FileCache) Get(key string) interface{} {
147 // timeout means how long to keep this file, unit of ms. 147 // timeout means how long to keep this file, unit of ms.
148 // if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever. 148 // if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever.
149 func (this *FileCache) Put(key string, val interface{}, timeout int64) error { 149 func (this *FileCache) Put(key string, val interface{}, timeout int64) error {
150 gob.Register(val)
151
150 filename := this.getCacheFileName(key) 152 filename := this.getCacheFileName(key)
151 var item FileCacheItem 153 var item FileCacheItem
152 item.Data = val 154 item.Data = val
......
1 package context 1 package context
2 2
3 import ( 3 import (
4 "crypto/hmac"
5 "crypto/sha1"
6 "encoding/base64"
7 "fmt"
4 "net/http" 8 "net/http"
9 "strconv"
10 "strings"
11 "time"
5 12
6 "github.com/astaxie/beego/middleware" 13 "github.com/astaxie/beego/middleware"
7 ) 14 )
...@@ -59,3 +66,41 @@ func (ctx *Context) GetCookie(key string) string { ...@@ -59,3 +66,41 @@ func (ctx *Context) GetCookie(key string) string {
59 func (ctx *Context) SetCookie(name string, value string, others ...interface{}) { 66 func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
60 ctx.Output.Cookie(name, value, others...) 67 ctx.Output.Cookie(name, value, others...)
61 } 68 }
69
70 // Get secure cookie from request by a given key.
71 func (ctx *Context) GetSecureCookie(Secret, key string) (string, bool) {
72 val := ctx.Input.Cookie(key)
73 if val == "" {
74 return "", false
75 }
76
77 parts := strings.SplitN(val, "|", 3)
78
79 if len(parts) != 3 {
80 return "", false
81 }
82
83 vs := parts[0]
84 timestamp := parts[1]
85 sig := parts[2]
86
87 h := hmac.New(sha1.New, []byte(Secret))
88 fmt.Fprintf(h, "%s%s", vs, timestamp)
89
90 if fmt.Sprintf("%02x", h.Sum(nil)) != sig {
91 return "", false
92 }
93 res, _ := base64.URLEncoding.DecodeString(vs)
94 return string(res), true
95 }
96
97 // Set Secure cookie for response.
98 func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interface{}) {
99 vs := base64.URLEncoding.EncodeToString([]byte(value))
100 timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
101 h := hmac.New(sha1.New, []byte(Secret))
102 fmt.Fprintf(h, "%s%s", vs, timestamp)
103 sig := fmt.Sprintf("%02x", h.Sum(nil))
104 cookie := strings.Join([]string{vs, timestamp, sig}, "|")
105 ctx.Output.Cookie(name, cookie, others...)
106 }
......
...@@ -77,39 +77,77 @@ func (output *BeegoOutput) Cookie(name string, value string, others ...interface ...@@ -77,39 +77,77 @@ func (output *BeegoOutput) Cookie(name string, value string, others ...interface
77 var b bytes.Buffer 77 var b bytes.Buffer
78 fmt.Fprintf(&b, "%s=%s", sanitizeName(name), sanitizeValue(value)) 78 fmt.Fprintf(&b, "%s=%s", sanitizeName(name), sanitizeValue(value))
79 if len(others) > 0 { 79 if len(others) > 0 {
80 switch others[0].(type) { 80 switch v := others[0].(type) {
81 case int: 81 case int:
82 if others[0].(int) > 0 { 82 if v > 0 {
83 fmt.Fprintf(&b, "; Max-Age=%d", others[0].(int)) 83 fmt.Fprintf(&b, "; Max-Age=%d", v)
84 } else if others[0].(int) < 0 { 84 } else if v < 0 {
85 fmt.Fprintf(&b, "; Max-Age=0") 85 fmt.Fprintf(&b, "; Max-Age=0")
86 } 86 }
87 case int64: 87 case int64:
88 if others[0].(int64) > 0 { 88 if v > 0 {
89 fmt.Fprintf(&b, "; Max-Age=%d", others[0].(int64)) 89 fmt.Fprintf(&b, "; Max-Age=%d", v)
90 } else if others[0].(int64) < 0 { 90 } else if v < 0 {
91 fmt.Fprintf(&b, "; Max-Age=0") 91 fmt.Fprintf(&b, "; Max-Age=0")
92 } 92 }
93 case int32: 93 case int32:
94 if others[0].(int32) > 0 { 94 if v > 0 {
95 fmt.Fprintf(&b, "; Max-Age=%d", others[0].(int32)) 95 fmt.Fprintf(&b, "; Max-Age=%d", v)
96 } else if others[0].(int32) < 0 { 96 } else if v < 0 {
97 fmt.Fprintf(&b, "; Max-Age=0") 97 fmt.Fprintf(&b, "; Max-Age=0")
98 } 98 }
99 } 99 }
100 } 100 }
101
102 // the settings below
103 // Path, Domain, Secure, HttpOnly
104 // can use nil skip set
105
106 // default "/"
101 if len(others) > 1 { 107 if len(others) > 1 {
102 fmt.Fprintf(&b, "; Path=%s", sanitizeValue(others[1].(string))) 108 if v, ok := others[1].(string); ok && len(v) > 0 {
109 fmt.Fprintf(&b, "; Path=%s", sanitizeValue(v))
110 }
111 } else {
112 fmt.Fprintf(&b, "; Path=%s", "/")
103 } 113 }
114
115 // default empty
104 if len(others) > 2 { 116 if len(others) > 2 {
105 fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(others[2].(string))) 117 if v, ok := others[2].(string); ok && len(v) > 0 {
118 fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(v))
119 }
106 } 120 }
121
122 // default empty
107 if len(others) > 3 { 123 if len(others) > 3 {
108 fmt.Fprintf(&b, "; Secure") 124 var secure bool
125 switch v := others[3].(type) {
126 case bool:
127 secure = v
128 default:
129 if others[3] != nil {
130 secure = true
131 }
132 }
133 if secure {
134 fmt.Fprintf(&b, "; Secure")
135 }
109 } 136 }
137
138 // default true
139 httponly := true
110 if len(others) > 4 { 140 if len(others) > 4 {
141 if v, ok := others[4].(bool); ok && !v || others[4] == nil {
142 // HttpOnly = false
143 httponly = false
144 }
145 }
146
147 if httponly {
111 fmt.Fprintf(&b, "; HttpOnly") 148 fmt.Fprintf(&b, "; HttpOnly")
112 } 149 }
150
113 output.Context.ResponseWriter.Header().Add("Set-Cookie", b.String()) 151 output.Context.ResponseWriter.Header().Add("Set-Cookie", b.String())
114 } 152 }
115 153
......
...@@ -2,11 +2,7 @@ package beego ...@@ -2,11 +2,7 @@ package beego
2 2
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "crypto/hmac"
6 "crypto/sha1"
7 "encoding/base64"
8 "errors" 5 "errors"
9 "fmt"
10 "html/template" 6 "html/template"
11 "io" 7 "io"
12 "io/ioutil" 8 "io/ioutil"
...@@ -17,7 +13,6 @@ import ( ...@@ -17,7 +13,6 @@ import (
17 "reflect" 13 "reflect"
18 "strconv" 14 "strconv"
19 "strings" 15 "strings"
20 "time"
21 16
22 "github.com/astaxie/beego/context" 17 "github.com/astaxie/beego/context"
23 "github.com/astaxie/beego/session" 18 "github.com/astaxie/beego/session"
...@@ -313,11 +308,11 @@ func (c *Controller) GetString(key string) string { ...@@ -313,11 +308,11 @@ func (c *Controller) GetString(key string) string {
313 // GetStrings returns the input string slice by key string. 308 // GetStrings returns the input string slice by key string.
314 // it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection. 309 // it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection.
315 func (c *Controller) GetStrings(key string) []string { 310 func (c *Controller) GetStrings(key string) []string {
316 r := c.Ctx.Request 311 f := c.Input()
317 if r.Form == nil { 312 if f == nil {
318 return []string{} 313 return []string{}
319 } 314 }
320 vs := r.Form[key] 315 vs := f[key]
321 if len(vs) > 0 { 316 if len(vs) > 0 {
322 return vs 317 return vs
323 } 318 }
...@@ -417,40 +412,12 @@ func (c *Controller) IsAjax() bool { ...@@ -417,40 +412,12 @@ func (c *Controller) IsAjax() bool {
417 412
418 // GetSecureCookie returns decoded cookie value from encoded browser cookie values. 413 // GetSecureCookie returns decoded cookie value from encoded browser cookie values.
419 func (c *Controller) GetSecureCookie(Secret, key string) (string, bool) { 414 func (c *Controller) GetSecureCookie(Secret, key string) (string, bool) {
420 val := c.Ctx.GetCookie(key) 415 return c.Ctx.GetSecureCookie(Secret, key)
421 if val == "" {
422 return "", false
423 }
424
425 parts := strings.SplitN(val, "|", 3)
426
427 if len(parts) != 3 {
428 return "", false
429 }
430
431 vs := parts[0]
432 timestamp := parts[1]
433 sig := parts[2]
434
435 h := hmac.New(sha1.New, []byte(Secret))
436 fmt.Fprintf(h, "%s%s", vs, timestamp)
437
438 if fmt.Sprintf("%02x", h.Sum(nil)) != sig {
439 return "", false
440 }
441 res, _ := base64.URLEncoding.DecodeString(vs)
442 return string(res), true
443 } 416 }
444 417
445 // SetSecureCookie puts value into cookie after encoded the value. 418 // SetSecureCookie puts value into cookie after encoded the value.
446 func (c *Controller) SetSecureCookie(Secret, name, val string, age int64) { 419 func (c *Controller) SetSecureCookie(Secret, name, value string, others ...interface{}) {
447 vs := base64.URLEncoding.EncodeToString([]byte(val)) 420 c.Ctx.SetSecureCookie(Secret, name, value, others...)
448 timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
449 h := hmac.New(sha1.New, []byte(Secret))
450 fmt.Fprintf(h, "%s%s", vs, timestamp)
451 sig := fmt.Sprintf("%02x", h.Sum(nil))
452 cookie := strings.Join([]string{vs, timestamp, sig}, "|")
453 c.Ctx.SetCookie(name, cookie, age, "/")
454 } 421 }
455 422
456 // XsrfToken creates a xsrf token string and returns. 423 // XsrfToken creates a xsrf token string and returns.
......
...@@ -24,7 +24,7 @@ func Get(url string) *BeegoHttpRequest { ...@@ -24,7 +24,7 @@ func Get(url string) *BeegoHttpRequest {
24 req.Method = "GET" 24 req.Method = "GET"
25 req.Header = http.Header{} 25 req.Header = http.Header{}
26 req.Header.Set("User-Agent", defaultUserAgent) 26 req.Header.Set("User-Agent", defaultUserAgent)
27 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil} 27 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil, nil, nil}
28 } 28 }
29 29
30 // Post returns *BeegoHttpRequest with POST method. 30 // Post returns *BeegoHttpRequest with POST method.
...@@ -33,7 +33,7 @@ func Post(url string) *BeegoHttpRequest { ...@@ -33,7 +33,7 @@ func Post(url string) *BeegoHttpRequest {
33 req.Method = "POST" 33 req.Method = "POST"
34 req.Header = http.Header{} 34 req.Header = http.Header{}
35 req.Header.Set("User-Agent", defaultUserAgent) 35 req.Header.Set("User-Agent", defaultUserAgent)
36 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil} 36 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil, nil, nil}
37 } 37 }
38 38
39 // Put returns *BeegoHttpRequest with PUT method. 39 // Put returns *BeegoHttpRequest with PUT method.
...@@ -42,7 +42,7 @@ func Put(url string) *BeegoHttpRequest { ...@@ -42,7 +42,7 @@ func Put(url string) *BeegoHttpRequest {
42 req.Method = "PUT" 42 req.Method = "PUT"
43 req.Header = http.Header{} 43 req.Header = http.Header{}
44 req.Header.Set("User-Agent", defaultUserAgent) 44 req.Header.Set("User-Agent", defaultUserAgent)
45 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil} 45 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil, nil, nil}
46 } 46 }
47 47
48 // Delete returns *BeegoHttpRequest DELETE GET method. 48 // Delete returns *BeegoHttpRequest DELETE GET method.
...@@ -51,7 +51,7 @@ func Delete(url string) *BeegoHttpRequest { ...@@ -51,7 +51,7 @@ func Delete(url string) *BeegoHttpRequest {
51 req.Method = "DELETE" 51 req.Method = "DELETE"
52 req.Header = http.Header{} 52 req.Header = http.Header{}
53 req.Header.Set("User-Agent", defaultUserAgent) 53 req.Header.Set("User-Agent", defaultUserAgent)
54 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil} 54 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil, nil, nil}
55 } 55 }
56 56
57 // Head returns *BeegoHttpRequest with HEAD method. 57 // Head returns *BeegoHttpRequest with HEAD method.
...@@ -60,7 +60,7 @@ func Head(url string) *BeegoHttpRequest { ...@@ -60,7 +60,7 @@ func Head(url string) *BeegoHttpRequest {
60 req.Method = "HEAD" 60 req.Method = "HEAD"
61 req.Header = http.Header{} 61 req.Header = http.Header{}
62 req.Header.Set("User-Agent", defaultUserAgent) 62 req.Header.Set("User-Agent", defaultUserAgent)
63 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil} 63 return &BeegoHttpRequest{url, &req, map[string]string{}, false, 60 * time.Second, 60 * time.Second, nil, nil, nil}
64 } 64 }
65 65
66 // BeegoHttpRequest provides more useful methods for requesting one url than http.Request. 66 // BeegoHttpRequest provides more useful methods for requesting one url than http.Request.
...@@ -72,6 +72,8 @@ type BeegoHttpRequest struct { ...@@ -72,6 +72,8 @@ type BeegoHttpRequest struct {
72 connectTimeout time.Duration 72 connectTimeout time.Duration
73 readWriteTimeout time.Duration 73 readWriteTimeout time.Duration
74 tlsClientConfig *tls.Config 74 tlsClientConfig *tls.Config
75 proxy func(*http.Request) (*url.URL, error)
76 transport http.RoundTripper
75 } 77 }
76 78
77 // Debug sets show debug or not when executing request. 79 // Debug sets show debug or not when executing request.
...@@ -105,6 +107,24 @@ func (b *BeegoHttpRequest) SetCookie(cookie *http.Cookie) *BeegoHttpRequest { ...@@ -105,6 +107,24 @@ func (b *BeegoHttpRequest) SetCookie(cookie *http.Cookie) *BeegoHttpRequest {
105 return b 107 return b
106 } 108 }
107 109
110 // Set transport to
111 func (b *BeegoHttpRequest) SetTransport(transport http.RoundTripper) *BeegoHttpRequest {
112 b.transport = transport
113 return b
114 }
115
116 // Set http proxy
117 // example:
118 //
119 // func(req *http.Request) (*url.URL, error) {
120 // u, _ := url.ParseRequestURI("http://127.0.0.1:8118")
121 // return u, nil
122 // }
123 func (b *BeegoHttpRequest) SetProxy(proxy func(*http.Request) (*url.URL, error)) *BeegoHttpRequest {
124 b.proxy = proxy
125 return b
126 }
127
108 // Param adds query param in to request. 128 // Param adds query param in to request.
109 // params build query string as ?key1=value1&key2=value2... 129 // params build query string as ?key1=value1&key2=value2...
110 func (b *BeegoHttpRequest) Param(key, value string) *BeegoHttpRequest { 130 func (b *BeegoHttpRequest) Param(key, value string) *BeegoHttpRequest {
...@@ -171,12 +191,34 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { ...@@ -171,12 +191,34 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
171 println(string(dump)) 191 println(string(dump))
172 } 192 }
173 193
174 client := &http.Client{ 194 trans := b.transport
175 Transport: &http.Transport{ 195
196 if trans == nil {
197 // create default transport
198 trans = &http.Transport{
176 TLSClientConfig: b.tlsClientConfig, 199 TLSClientConfig: b.tlsClientConfig,
200 Proxy: b.proxy,
177 Dial: TimeoutDialer(b.connectTimeout, b.readWriteTimeout), 201 Dial: TimeoutDialer(b.connectTimeout, b.readWriteTimeout),
178 }, 202 }
203 } else {
204 // if b.transport is *http.Transport then set the settings.
205 if t, ok := trans.(*http.Transport); ok {
206 if t.TLSClientConfig == nil {
207 t.TLSClientConfig = b.tlsClientConfig
208 }
209 if t.Proxy == nil {
210 t.Proxy = b.proxy
211 }
212 if t.Dial == nil {
213 t.Dial = TimeoutDialer(b.connectTimeout, b.readWriteTimeout)
214 }
215 }
179 } 216 }
217
218 client := &http.Client{
219 Transport: trans,
220 }
221
180 resp, err := client.Do(b.req) 222 resp, err := client.Do(b.req)
181 if err != nil { 223 if err != nil {
182 return nil, err 224 return nil, err
......
...@@ -35,7 +35,7 @@ var ( ...@@ -35,7 +35,7 @@ var (
35 "istartswith": true, 35 "istartswith": true,
36 "iendswith": true, 36 "iendswith": true,
37 "in": true, 37 "in": true,
38 // "range": true, 38 "between": true,
39 // "year": true, 39 // "year": true,
40 // "month": true, 40 // "month": true,
41 // "day": true, 41 // "day": true,
...@@ -103,15 +103,36 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val ...@@ -103,15 +103,36 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
103 } else { 103 } else {
104 switch fi.fieldType { 104 switch fi.fieldType {
105 case TypeBooleanField: 105 case TypeBooleanField:
106 value = field.Bool() 106 if nb, ok := field.Interface().(sql.NullBool); ok {
107 value = nil
108 if nb.Valid {
109 value = nb.Bool
110 }
111 } else {
112 value = field.Bool()
113 }
107 case TypeCharField, TypeTextField: 114 case TypeCharField, TypeTextField:
108 value = field.String() 115 if ns, ok := field.Interface().(sql.NullString); ok {
116 value = nil
117 if ns.Valid {
118 value = ns.String
119 }
120 } else {
121 value = field.String()
122 }
109 case TypeFloatField, TypeDecimalField: 123 case TypeFloatField, TypeDecimalField:
110 vu := field.Interface() 124 if nf, ok := field.Interface().(sql.NullFloat64); ok {
111 if _, ok := vu.(float32); ok { 125 value = nil
112 value, _ = StrTo(ToStr(vu)).Float64() 126 if nf.Valid {
127 value = nf.Float64
128 }
113 } else { 129 } else {
114 value = field.Float() 130 vu := field.Interface()
131 if _, ok := vu.(float32); ok {
132 value, _ = StrTo(ToStr(vu)).Float64()
133 } else {
134 value = field.Float()
135 }
115 } 136 }
116 case TypeDateField, TypeDateTimeField: 137 case TypeDateField, TypeDateTimeField:
117 value = field.Interface() 138 value = field.Interface()
...@@ -124,7 +145,14 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val ...@@ -124,7 +145,14 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
124 case fi.fieldType&IsPostiveIntegerField > 0: 145 case fi.fieldType&IsPostiveIntegerField > 0:
125 value = field.Uint() 146 value = field.Uint()
126 case fi.fieldType&IsIntegerField > 0: 147 case fi.fieldType&IsIntegerField > 0:
127 value = field.Int() 148 if ni, ok := field.Interface().(sql.NullInt64); ok {
149 value = nil
150 if ni.Valid {
151 value = ni.Int64
152 }
153 } else {
154 value = field.Int()
155 }
128 case fi.fieldType&IsRelField > 0: 156 case fi.fieldType&IsRelField > 0:
129 if field.IsNil() { 157 if field.IsNil() {
130 value = nil 158 value = nil
...@@ -144,6 +172,11 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val ...@@ -144,6 +172,11 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
144 switch fi.fieldType { 172 switch fi.fieldType {
145 case TypeDateField, TypeDateTimeField: 173 case TypeDateField, TypeDateTimeField:
146 if fi.auto_now || fi.auto_now_add && insert { 174 if fi.auto_now || fi.auto_now_add && insert {
175 if insert {
176 if t, ok := value.(time.Time); ok && !t.IsZero() {
177 break
178 }
179 }
147 tnow := time.Now() 180 tnow := time.Now()
148 d.ins.TimeToDB(&tnow, tz) 181 d.ins.TimeToDB(&tnow, tz)
149 value = tnow 182 value = tnow
...@@ -883,13 +916,19 @@ func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator stri ...@@ -883,13 +916,19 @@ func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator stri
883 } 916 }
884 arg := params[0] 917 arg := params[0]
885 918
886 if operator == "in" { 919 switch operator {
920 case "in":
887 marks := make([]string, len(params)) 921 marks := make([]string, len(params))
888 for i, _ := range marks { 922 for i, _ := range marks {
889 marks[i] = "?" 923 marks[i] = "?"
890 } 924 }
891 sql = fmt.Sprintf("IN (%s)", strings.Join(marks, ", ")) 925 sql = fmt.Sprintf("IN (%s)", strings.Join(marks, ", "))
892 } else { 926 case "between":
927 if len(params) != 2 {
928 panic(fmt.Errorf("operator `%s` need 2 args not %d", operator, len(params)))
929 }
930 sql = "BETWEEN ? AND ?"
931 default:
893 if len(params) > 1 { 932 if len(params) > 1 {
894 panic(fmt.Errorf("operator `%s` need 1 args not %d", operator, len(params))) 933 panic(fmt.Errorf("operator `%s` need 1 args not %d", operator, len(params)))
895 } 934 }
...@@ -1117,17 +1156,37 @@ setValue: ...@@ -1117,17 +1156,37 @@ setValue:
1117 switch { 1156 switch {
1118 case fieldType == TypeBooleanField: 1157 case fieldType == TypeBooleanField:
1119 if isNative { 1158 if isNative {
1120 if value == nil { 1159 if nb, ok := field.Interface().(sql.NullBool); ok {
1121 value = false 1160 if value == nil {
1161 nb.Valid = false
1162 } else {
1163 nb.Bool = value.(bool)
1164 nb.Valid = true
1165 }
1166 field.Set(reflect.ValueOf(nb))
1167 } else {
1168 if value == nil {
1169 value = false
1170 }
1171 field.SetBool(value.(bool))
1122 } 1172 }
1123 field.SetBool(value.(bool))
1124 } 1173 }
1125 case fieldType == TypeCharField || fieldType == TypeTextField: 1174 case fieldType == TypeCharField || fieldType == TypeTextField:
1126 if isNative { 1175 if isNative {
1127 if value == nil { 1176 if ns, ok := field.Interface().(sql.NullString); ok {
1128 value = "" 1177 if value == nil {
1178 ns.Valid = false
1179 } else {
1180 ns.String = value.(string)
1181 ns.Valid = true
1182 }
1183 field.Set(reflect.ValueOf(ns))
1184 } else {
1185 if value == nil {
1186 value = ""
1187 }
1188 field.SetString(value.(string))
1129 } 1189 }
1130 field.SetString(value.(string))
1131 } 1190 }
1132 case fieldType == TypeDateField || fieldType == TypeDateTimeField: 1191 case fieldType == TypeDateField || fieldType == TypeDateTimeField:
1133 if isNative { 1192 if isNative {
...@@ -1146,18 +1205,39 @@ setValue: ...@@ -1146,18 +1205,39 @@ setValue:
1146 } 1205 }
1147 } else { 1206 } else {
1148 if isNative { 1207 if isNative {
1149 if value == nil { 1208 if ni, ok := field.Interface().(sql.NullInt64); ok {
1150 value = int64(0) 1209 if value == nil {
1210 ni.Valid = false
1211 } else {
1212 ni.Int64 = value.(int64)
1213 ni.Valid = true
1214 }
1215 field.Set(reflect.ValueOf(ni))
1216 } else {
1217 if value == nil {
1218 value = int64(0)
1219 }
1220 field.SetInt(value.(int64))
1151 } 1221 }
1152 field.SetInt(value.(int64))
1153 } 1222 }
1154 } 1223 }
1155 case fieldType == TypeFloatField || fieldType == TypeDecimalField: 1224 case fieldType == TypeFloatField || fieldType == TypeDecimalField:
1156 if isNative { 1225 if isNative {
1157 if value == nil { 1226 if nf, ok := field.Interface().(sql.NullFloat64); ok {
1158 value = float64(0) 1227 if value == nil {
1228 nf.Valid = false
1229 } else {
1230 nf.Float64 = value.(float64)
1231 nf.Valid = true
1232 }
1233 field.Set(reflect.ValueOf(nf))
1234 } else {
1235
1236 if value == nil {
1237 value = float64(0)
1238 }
1239 field.SetFloat(value.(float64))
1159 } 1240 }
1160 field.SetFloat(value.(float64))
1161 } 1241 }
1162 case fieldType&IsRelField > 0: 1242 case fieldType&IsRelField > 0:
1163 if value != nil { 1243 if value != nil {
......
...@@ -168,7 +168,7 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) { ...@@ -168,7 +168,7 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) {
168 } 168 }
169 169
170 if dataBaseCache.add(aliasName, al) == false { 170 if dataBaseCache.add(aliasName, al) == false {
171 return nil, fmt.Errorf("db name `%s` already registered, cannot reuse", aliasName) 171 return nil, fmt.Errorf("DataBase alias name `%s` already registered, cannot reuse", aliasName)
172 } 172 }
173 173
174 return al, nil 174 return al, nil
...@@ -239,7 +239,7 @@ func SetDataBaseTZ(aliasName string, tz *time.Location) error { ...@@ -239,7 +239,7 @@ func SetDataBaseTZ(aliasName string, tz *time.Location) error {
239 if al, ok := dataBaseCache.get(aliasName); ok { 239 if al, ok := dataBaseCache.get(aliasName); ok {
240 al.TZ = tz 240 al.TZ = tz
241 } else { 241 } else {
242 return fmt.Errorf("DataBase name `%s` not registered\n", aliasName) 242 return fmt.Errorf("DataBase alias name `%s` not registered\n", aliasName)
243 } 243 }
244 return nil 244 return nil
245 } 245 }
...@@ -260,3 +260,19 @@ func SetMaxOpenConns(aliasName string, maxOpenConns int) { ...@@ -260,3 +260,19 @@ func SetMaxOpenConns(aliasName string, maxOpenConns int) {
260 fun.Call([]reflect.Value{reflect.ValueOf(maxOpenConns)}) 260 fun.Call([]reflect.Value{reflect.ValueOf(maxOpenConns)})
261 } 261 }
262 } 262 }
263
264 // Get *sql.DB from registered database by db alias name.
265 // Use "default" as alias name if you not set.
266 func GetDB(aliasNames ...string) (*sql.DB, error) {
267 var name string
268 if len(aliasNames) > 0 {
269 name = aliasNames[0]
270 } else {
271 name = "default"
272 }
273 if al, ok := dataBaseCache.get(name); ok {
274 return al.DB, nil
275 } else {
276 return nil, fmt.Errorf("DataBase of alias name `%s` not found\n", name)
277 }
278 }
......
...@@ -98,3 +98,9 @@ func (mc *_modelCache) clean() { ...@@ -98,3 +98,9 @@ func (mc *_modelCache) clean() {
98 mc.cacheByFN = make(map[string]*modelInfo) 98 mc.cacheByFN = make(map[string]*modelInfo)
99 mc.done = false 99 mc.done = false
100 } 100 }
101
102 // Clean model cache. Then you can re-RegisterModel.
103 // Common use this api for test case.
104 func ResetModelCache() {
105 modelCache.clean()
106 }
......
1 package orm 1 package orm
2 2
3 import ( 3 import (
4 "database/sql"
4 "encoding/json" 5 "encoding/json"
5 "fmt" 6 "fmt"
6 "os" 7 "os"
...@@ -116,27 +117,31 @@ type Data struct { ...@@ -116,27 +117,31 @@ type Data struct {
116 } 117 }
117 118
118 type DataNull struct { 119 type DataNull struct {
119 Id int 120 Id int
120 Boolean bool `orm:"null"` 121 Boolean bool `orm:"null"`
121 Char string `orm:"null;size(50)"` 122 Char string `orm:"null;size(50)"`
122 Text string `orm:"null;type(text)"` 123 Text string `orm:"null;type(text)"`
123 Date time.Time `orm:"null;type(date)"` 124 Date time.Time `orm:"null;type(date)"`
124 DateTime time.Time `orm:"null;column(datetime)""` 125 DateTime time.Time `orm:"null;column(datetime)""`
125 Byte byte `orm:"null"` 126 Byte byte `orm:"null"`
126 Rune rune `orm:"null"` 127 Rune rune `orm:"null"`
127 Int int `orm:"null"` 128 Int int `orm:"null"`
128 Int8 int8 `orm:"null"` 129 Int8 int8 `orm:"null"`
129 Int16 int16 `orm:"null"` 130 Int16 int16 `orm:"null"`
130 Int32 int32 `orm:"null"` 131 Int32 int32 `orm:"null"`
131 Int64 int64 `orm:"null"` 132 Int64 int64 `orm:"null"`
132 Uint uint `orm:"null"` 133 Uint uint `orm:"null"`
133 Uint8 uint8 `orm:"null"` 134 Uint8 uint8 `orm:"null"`
134 Uint16 uint16 `orm:"null"` 135 Uint16 uint16 `orm:"null"`
135 Uint32 uint32 `orm:"null"` 136 Uint32 uint32 `orm:"null"`
136 Uint64 uint64 `orm:"null"` 137 Uint64 uint64 `orm:"null"`
137 Float32 float32 `orm:"null"` 138 Float32 float32 `orm:"null"`
138 Float64 float64 `orm:"null"` 139 Float64 float64 `orm:"null"`
139 Decimal float64 `orm:"digits(8);decimals(4);null"` 140 Decimal float64 `orm:"digits(8);decimals(4);null"`
141 NullString sql.NullString `orm:"null"`
142 NullBool sql.NullBool `orm:"null"`
143 NullFloat64 sql.NullFloat64 `orm:"null"`
144 NullInt64 sql.NullInt64 `orm:"null"`
140 } 145 }
141 146
142 // only for mysql 147 // only for mysql
...@@ -303,9 +308,8 @@ go test -v github.com/astaxie/beego/orm ...@@ -303,9 +308,8 @@ go test -v github.com/astaxie/beego/orm
303 308
304 309
305 #### Sqlite3 310 #### Sqlite3
306 touch /path/to/orm_test.db
307 export ORM_DRIVER=sqlite3 311 export ORM_DRIVER=sqlite3
308 export ORM_SOURCE=/path/to/orm_test.db 312 export ORM_SOURCE='file:memory_test?mode=memory'
309 go test -v github.com/astaxie/beego/orm 313 go test -v github.com/astaxie/beego/orm
310 314
311 315
......
1 package orm 1 package orm
2 2
3 import ( 3 import (
4 "database/sql"
4 "fmt" 5 "fmt"
5 "reflect" 6 "reflect"
6 "strings" 7 "strings"
...@@ -98,30 +99,29 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col ...@@ -98,30 +99,29 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col
98 // return field type as type constant from reflect.Value 99 // return field type as type constant from reflect.Value
99 func getFieldType(val reflect.Value) (ft int, err error) { 100 func getFieldType(val reflect.Value) (ft int, err error) {
100 elm := reflect.Indirect(val) 101 elm := reflect.Indirect(val)
101 switch elm.Kind() { 102 switch elm.Interface().(type) {
102 case reflect.Int8: 103 case int8:
103 ft = TypeBitField 104 ft = TypeBitField
104 case reflect.Int16: 105 case int16:
105 ft = TypeSmallIntegerField 106 ft = TypeSmallIntegerField
106 case reflect.Int32, reflect.Int: 107 case int32, int:
107 ft = TypeIntegerField 108 ft = TypeIntegerField
108 case reflect.Int64: 109 case int64, sql.NullInt64:
109 ft = TypeBigIntegerField 110 ft = TypeBigIntegerField
110 case reflect.Uint8: 111 case uint8:
111 ft = TypePositiveBitField 112 ft = TypePositiveBitField
112 case reflect.Uint16: 113 case uint16:
113 ft = TypePositiveSmallIntegerField 114 ft = TypePositiveSmallIntegerField
114 case reflect.Uint32, reflect.Uint: 115 case uint32, uint:
115 ft = TypePositiveIntegerField 116 ft = TypePositiveIntegerField
116 case reflect.Uint64: 117 case uint64:
117 ft = TypePositiveBigIntegerField 118 ft = TypePositiveBigIntegerField
118 case reflect.Float32, reflect.Float64: 119 case float32, float64, sql.NullFloat64:
119 ft = TypeFloatField 120 ft = TypeFloatField
120 case reflect.Bool: 121 case bool, sql.NullBool:
121 ft = TypeBooleanField 122 ft = TypeBooleanField
122 case reflect.String: 123 case string, sql.NullString:
123 ft = TypeCharField 124 ft = TypeCharField
124 case reflect.Invalid:
125 default: 125 default:
126 if elm.CanInterface() { 126 if elm.CanInterface() {
127 if _, ok := elm.Interface().(time.Time); ok { 127 if _, ok := elm.Interface().(time.Time); ok {
......
...@@ -2,6 +2,7 @@ package orm ...@@ -2,6 +2,7 @@ package orm
2 2
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "database/sql"
5 "fmt" 6 "fmt"
6 "io/ioutil" 7 "io/ioutil"
7 "os" 8 "os"
...@@ -138,6 +139,15 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) { ...@@ -138,6 +139,15 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
138 } 139 }
139 } 140 }
140 141
142 func TestGetDB(t *testing.T) {
143 if db, err := GetDB(); err != nil {
144 throwFailNow(t, err)
145 } else {
146 err = db.Ping()
147 throwFailNow(t, err)
148 }
149 }
150
141 func TestSyncDb(t *testing.T) { 151 func TestSyncDb(t *testing.T) {
142 RegisterModel(new(Data), new(DataNull)) 152 RegisterModel(new(Data), new(DataNull))
143 RegisterModel(new(User)) 153 RegisterModel(new(User))
...@@ -258,12 +268,45 @@ func TestNullDataTypes(t *testing.T) { ...@@ -258,12 +268,45 @@ func TestNullDataTypes(t *testing.T) {
258 err = dORM.Read(&d) 268 err = dORM.Read(&d)
259 throwFail(t, err) 269 throwFail(t, err)
260 270
271 throwFail(t, AssertIs(d.NullBool.Valid, false))
272 throwFail(t, AssertIs(d.NullString.Valid, false))
273 throwFail(t, AssertIs(d.NullInt64.Valid, false))
274 throwFail(t, AssertIs(d.NullFloat64.Valid, false))
275
261 _, err = dORM.Raw(`INSERT INTO data_null (boolean) VALUES (?)`, nil).Exec() 276 _, err = dORM.Raw(`INSERT INTO data_null (boolean) VALUES (?)`, nil).Exec()
262 throwFail(t, err) 277 throwFail(t, err)
263 278
264 d = DataNull{Id: 2} 279 d = DataNull{Id: 2}
265 err = dORM.Read(&d) 280 err = dORM.Read(&d)
266 throwFail(t, err) 281 throwFail(t, err)
282
283 d = DataNull{
284 DateTime: time.Now(),
285 NullString: sql.NullString{"test", true},
286 NullBool: sql.NullBool{true, true},
287 NullInt64: sql.NullInt64{42, true},
288 NullFloat64: sql.NullFloat64{42.42, true},
289 }
290
291 id, err = dORM.Insert(&d)
292 throwFail(t, err)
293 throwFail(t, AssertIs(id, 3))
294
295 d = DataNull{Id: 3}
296 err = dORM.Read(&d)
297 throwFail(t, err)
298
299 throwFail(t, AssertIs(d.NullBool.Valid, true))
300 throwFail(t, AssertIs(d.NullBool.Bool, true))
301
302 throwFail(t, AssertIs(d.NullString.Valid, true))
303 throwFail(t, AssertIs(d.NullString.String, "test"))
304
305 throwFail(t, AssertIs(d.NullInt64.Valid, true))
306 throwFail(t, AssertIs(d.NullInt64.Int64, 42))
307
308 throwFail(t, AssertIs(d.NullFloat64.Valid, true))
309 throwFail(t, AssertIs(d.NullFloat64.Float64, 42.42))
267 } 310 }
268 311
269 func TestCRUD(t *testing.T) { 312 func TestCRUD(t *testing.T) {
...@@ -619,6 +662,14 @@ func TestOperators(t *testing.T) { ...@@ -619,6 +662,14 @@ func TestOperators(t *testing.T) {
619 num, err = qs.Filter("status__in", []*int{&n1}, &n2).Count() 662 num, err = qs.Filter("status__in", []*int{&n1}, &n2).Count()
620 throwFail(t, err) 663 throwFail(t, err)
621 throwFail(t, AssertIs(num, 2)) 664 throwFail(t, AssertIs(num, 2))
665
666 num, err = qs.Filter("id__between", 2, 3).Count()
667 throwFail(t, err)
668 throwFail(t, AssertIs(num, 2))
669
670 num, err = qs.Filter("id__between", []int{2, 3}).Count()
671 throwFail(t, err)
672 throwFail(t, AssertIs(num, 2))
622 } 673 }
623 674
624 func TestSetCond(t *testing.T) { 675 func TestSetCond(t *testing.T) {
...@@ -1577,7 +1628,6 @@ func TestDelete(t *testing.T) { ...@@ -1577,7 +1628,6 @@ func TestDelete(t *testing.T) {
1577 throwFail(t, err) 1628 throwFail(t, err)
1578 throwFail(t, AssertIs(num, 4)) 1629 throwFail(t, AssertIs(num, 4))
1579 1630
1580 fmt.Println("...")
1581 qs = dORM.QueryTable("comment") 1631 qs = dORM.QueryTable("comment")
1582 num, err = qs.Filter("Post__User", 3).Delete() 1632 num, err = qs.Filter("Post__User", 3).Delete()
1583 throwFail(t, err) 1633 throwFail(t, err)
...@@ -1646,10 +1696,10 @@ func TestTransaction(t *testing.T) { ...@@ -1646,10 +1696,10 @@ func TestTransaction(t *testing.T) {
1646 func TestReadOrCreate(t *testing.T) { 1696 func TestReadOrCreate(t *testing.T) {
1647 u := &User{ 1697 u := &User{
1648 UserName: "Kyle", 1698 UserName: "Kyle",
1649 Email: "kylemcc@gmail.com", 1699 Email: "kylemcc@gmail.com",
1650 Password: "other_pass", 1700 Password: "other_pass",
1651 Status: 7, 1701 Status: 7,
1652 IsStaff: false, 1702 IsStaff: false,
1653 IsActive: true, 1703 IsActive: true,
1654 } 1704 }
1655 1705
......
...@@ -8,7 +8,7 @@ package auth ...@@ -8,7 +8,7 @@ package auth
8 // } 8 // }
9 // return false 9 // return false
10 // } 10 // }
11 // authPlugin := auth.NewBasicAuthenticator(SecretAuth) 11 // authPlugin := auth.NewBasicAuthenticator(SecretAuth, "My Realm")
12 // beego.AddFilter("*","AfterStatic",authPlugin) 12 // beego.AddFilter("*","AfterStatic",authPlugin)
13 13
14 import ( 14 import (
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
8 "net/http" 8 "net/http"
9 "net/url" 9 "net/url"
10 "os" 10 "os"
11 "path"
11 "reflect" 12 "reflect"
12 "regexp" 13 "regexp"
13 "runtime" 14 "runtime"
...@@ -545,14 +546,26 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -545,14 +546,26 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
545 546
546 //static file server 547 //static file server
547 for prefix, staticDir := range StaticDir { 548 for prefix, staticDir := range StaticDir {
549 if len(prefix) == 0 {
550 continue
551 }
548 if r.URL.Path == "/favicon.ico" { 552 if r.URL.Path == "/favicon.ico" {
549 file := staticDir + r.URL.Path 553 file := path.Join(staticDir, r.URL.Path)
550 http.ServeFile(w, r, file) 554 if utils.FileExists(file) {
551 w.started = true 555 http.ServeFile(w, r, file)
552 goto Admin 556 w.started = true
557 goto Admin
558 }
553 } 559 }
554 if strings.HasPrefix(r.URL.Path, prefix) { 560 if strings.HasPrefix(r.URL.Path, prefix) {
555 file := staticDir + r.URL.Path[len(prefix):] 561 if len(r.URL.Path) > len(prefix) && r.URL.Path[len(prefix)] != '/' {
562 continue
563 }
564 if r.URL.Path == prefix && prefix[len(prefix)-1] != '/' {
565 http.Redirect(rw, r, r.URL.Path+"/", 302)
566 goto Admin
567 }
568 file := path.Join(staticDir, r.URL.Path[len(prefix):])
556 finfo, err := os.Stat(file) 569 finfo, err := os.Stat(file)
557 if err != nil { 570 if err != nil {
558 if RunMode == "dev" { 571 if RunMode == "dev" {
......
1 package session
2
3 import (
4 "github.com/couchbaselabs/go-couchbase"
5 "net/http"
6 "strings"
7 "sync"
8 )
9
10 var couchbpder = &CouchbaseProvider{}
11
12 type CouchbaseSessionStore struct {
13 b *couchbase.Bucket
14 sid string
15 lock sync.RWMutex
16 values map[interface{}]interface{}
17 maxlifetime int64
18 }
19
20 type CouchbaseProvider struct {
21 maxlifetime int64
22 savePath string
23 pool string
24 bucket string
25 b *couchbase.Bucket
26 }
27
28 func (cs *CouchbaseSessionStore) Set(key, value interface{}) error {
29 cs.lock.Lock()
30 defer cs.lock.Unlock()
31 cs.values[key] = value
32 return nil
33 }
34
35 func (cs *CouchbaseSessionStore) Get(key interface{}) interface{} {
36 cs.lock.RLock()
37 defer cs.lock.RUnlock()
38 if v, ok := cs.values[key]; ok {
39 return v
40 } else {
41 return nil
42 }
43 return nil
44 }
45
46 func (cs *CouchbaseSessionStore) Delete(key interface{}) error {
47 cs.lock.Lock()
48 defer cs.lock.Unlock()
49 delete(cs.values, key)
50 return nil
51 }
52
53 func (cs *CouchbaseSessionStore) Flush() error {
54 cs.lock.Lock()
55 defer cs.lock.Unlock()
56 cs.values = make(map[interface{}]interface{})
57 return nil
58 }
59
60 func (cs *CouchbaseSessionStore) SessionID() string {
61 return cs.sid
62 }
63
64 func (cs *CouchbaseSessionStore) SessionRelease(w http.ResponseWriter) {
65 defer cs.b.Close()
66
67 // if rs.values is empty, return directly
68 if len(cs.values) < 1 {
69 cs.b.Delete(cs.sid)
70 return
71 }
72
73 bo, err := encodeGob(cs.values)
74 if err != nil {
75 return
76 }
77
78 cs.b.Set(cs.sid, int(cs.maxlifetime), bo)
79 }
80
81 func (cp *CouchbaseProvider) getBucket() *couchbase.Bucket {
82 c, err := couchbase.Connect(cp.savePath)
83 if err != nil {
84 return nil
85 }
86
87 pool, err := c.GetPool(cp.pool)
88 if err != nil {
89 return nil
90 }
91
92 bucket, err := pool.GetBucket(cp.bucket)
93 if err != nil {
94 return nil
95 }
96
97 return bucket
98 }
99
100 // init couchbase session
101 // savepath like couchbase server REST/JSON URL
102 // e.g. http://host:port/, Pool, Bucket
103 func (cp *CouchbaseProvider) SessionInit(maxlifetime int64, savePath string) error {
104 cp.maxlifetime = maxlifetime
105 configs := strings.Split(savePath, ",")
106 if len(configs) > 0 {
107 cp.savePath = configs[0]
108 }
109 if len(configs) > 1 {
110 cp.pool = configs[1]
111 }
112 if len(configs) > 2 {
113 cp.bucket = configs[2]
114 }
115
116 return nil
117 }
118
119 // read couchbase session by sid
120 func (cp *CouchbaseProvider) SessionRead(sid string) (SessionStore, error) {
121 cp.b = cp.getBucket()
122
123 var doc []byte
124
125 err := cp.b.Get(sid, &doc)
126 var kv map[interface{}]interface{}
127 if doc == nil {
128 kv = make(map[interface{}]interface{})
129 } else {
130 kv, err = decodeGob(doc)
131 if err != nil {
132 return nil, err
133 }
134 }
135
136 cs := &CouchbaseSessionStore{b: cp.b, sid: sid, values: kv, maxlifetime: cp.maxlifetime}
137 return cs, nil
138 }
139
140 func (cp *CouchbaseProvider) SessionExist(sid string) bool {
141 cp.b = cp.getBucket()
142 defer cp.b.Close()
143
144 var doc []byte
145
146 if err := cp.b.Get(sid, &doc); err != nil || doc == nil {
147 return false
148 } else {
149 return true
150 }
151 }
152
153 func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
154 cp.b = cp.getBucket()
155
156 var doc []byte
157 if err := cp.b.Get(oldsid, &doc); err != nil || doc == nil {
158 cp.b.Set(sid, int(cp.maxlifetime), "")
159 } else {
160 err := cp.b.Delete(oldsid)
161 if err != nil {
162 return nil, err
163 }
164 _, _ = cp.b.Add(sid, int(cp.maxlifetime), doc)
165 }
166
167 err := cp.b.Get(sid, &doc)
168 if err != nil {
169 return nil, err
170 }
171 var kv map[interface{}]interface{}
172 if doc == nil {
173 kv = make(map[interface{}]interface{})
174 } else {
175 kv, err = decodeGob(doc)
176 if err != nil {
177 return nil, err
178 }
179 }
180
181 cs := &CouchbaseSessionStore{b: cp.b, sid: sid, values: kv, maxlifetime: cp.maxlifetime}
182 return cs, nil
183 }
184
185 func (cp *CouchbaseProvider) SessionDestroy(sid string) error {
186 cp.b = cp.getBucket()
187 defer cp.b.Close()
188
189 cp.b.Delete(sid)
190 return nil
191 }
192
193 func (cp *CouchbaseProvider) SessionGC() {
194 return
195 }
196
197 func (cp *CouchbaseProvider) SessionAll() int {
198 return 0
199 }
200
201 func init() {
202 Register("couchbase", couchbpder)
203 }
...@@ -152,8 +152,7 @@ func (fp *FileProvider) SessionExist(sid string) bool { ...@@ -152,8 +152,7 @@ func (fp *FileProvider) SessionExist(sid string) bool {
152 func (fp *FileProvider) SessionDestroy(sid string) error { 152 func (fp *FileProvider) SessionDestroy(sid string) error {
153 filepder.lock.Lock() 153 filepder.lock.Lock()
154 defer filepder.lock.Unlock() 154 defer filepder.lock.Unlock()
155 155 os.Remove(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
156 os.Remove(path.Join(fp.savePath))
157 return nil 156 return nil
158 } 157 }
159 158
......
...@@ -129,7 +129,8 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error { ...@@ -129,7 +129,8 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
129 } 129 }
130 return c, err 130 return c, err
131 }, rp.poolsize) 131 }, rp.poolsize)
132 return nil 132
133 return rp.poollist.Get().Err()
133 } 134 }
134 135
135 // read redis session by sid 136 // read redis session by sid
......
...@@ -56,11 +56,10 @@ type managerConfig struct { ...@@ -56,11 +56,10 @@ type managerConfig struct {
56 EnableSetCookie bool `json:"enableSetCookie,omitempty"` 56 EnableSetCookie bool `json:"enableSetCookie,omitempty"`
57 Gclifetime int64 `json:"gclifetime"` 57 Gclifetime int64 `json:"gclifetime"`
58 Maxlifetime int64 `json:"maxLifetime"` 58 Maxlifetime int64 `json:"maxLifetime"`
59 Maxage int `json:"maxage"`
60 Secure bool `json:"secure"` 59 Secure bool `json:"secure"`
61 SessionIDHashFunc string `json:"sessionIDHashFunc"` 60 SessionIDHashFunc string `json:"sessionIDHashFunc"`
62 SessionIDHashKey string `json:"sessionIDHashKey"` 61 SessionIDHashKey string `json:"sessionIDHashKey"`
63 CookieLifeTime int64 `json:"cookieLifeTime"` 62 CookieLifeTime int `json:"cookieLifeTime"`
64 ProviderConfig string `json:"providerConfig"` 63 ProviderConfig string `json:"providerConfig"`
65 } 64 }
66 65
...@@ -125,8 +124,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se ...@@ -125,8 +124,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
125 Path: "/", 124 Path: "/",
126 HttpOnly: true, 125 HttpOnly: true,
127 Secure: manager.config.Secure} 126 Secure: manager.config.Secure}
128 if manager.config.Maxage >= 0 { 127 if manager.config.CookieLifeTime >= 0 {
129 cookie.MaxAge = manager.config.Maxage 128 cookie.MaxAge = manager.config.CookieLifeTime
130 } 129 }
131 if manager.config.EnableSetCookie { 130 if manager.config.EnableSetCookie {
132 http.SetCookie(w, cookie) 131 http.SetCookie(w, cookie)
...@@ -144,8 +143,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se ...@@ -144,8 +143,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
144 Path: "/", 143 Path: "/",
145 HttpOnly: true, 144 HttpOnly: true,
146 Secure: manager.config.Secure} 145 Secure: manager.config.Secure}
147 if manager.config.Maxage >= 0 { 146 if manager.config.CookieLifeTime >= 0 {
148 cookie.MaxAge = manager.config.Maxage 147 cookie.MaxAge = manager.config.CookieLifeTime
149 } 148 }
150 if manager.config.EnableSetCookie { 149 if manager.config.EnableSetCookie {
151 http.SetCookie(w, cookie) 150 http.SetCookie(w, cookie)
...@@ -206,8 +205,8 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque ...@@ -206,8 +205,8 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque
206 cookie.HttpOnly = true 205 cookie.HttpOnly = true
207 cookie.Path = "/" 206 cookie.Path = "/"
208 } 207 }
209 if manager.config.Maxage >= 0 { 208 if manager.config.CookieLifeTime >= 0 {
210 cookie.MaxAge = manager.config.Maxage 209 cookie.MaxAge = manager.config.CookieLifeTime
211 } 210 }
212 http.SetCookie(w, cookie) 211 http.SetCookie(w, cookie)
213 r.AddCookie(cookie) 212 r.AddCookie(cookie)
......
...@@ -67,7 +67,7 @@ const ( ...@@ -67,7 +67,7 @@ const (
67 fieldIdName = "captcha_id" 67 fieldIdName = "captcha_id"
68 fieldCaptchaName = "captcha" 68 fieldCaptchaName = "captcha"
69 cachePrefix = "captcha_" 69 cachePrefix = "captcha_"
70 urlPrefix = "/captcha/" 70 defaultURLPrefix = "/captcha/"
71 ) 71 )
72 72
73 // Captcha struct 73 // Captcha struct
...@@ -76,7 +76,7 @@ type Captcha struct { ...@@ -76,7 +76,7 @@ type Captcha struct {
76 store cache.Cache 76 store cache.Cache
77 77
78 // url prefix for captcha image 78 // url prefix for captcha image
79 urlPrefix string 79 URLPrefix string
80 80
81 // specify captcha id input field name 81 // specify captcha id input field name
82 FieldIdName string 82 FieldIdName string
...@@ -155,7 +155,7 @@ func (c *Captcha) CreateCaptchaHtml() template.HTML { ...@@ -155,7 +155,7 @@ func (c *Captcha) CreateCaptchaHtml() template.HTML {
155 return template.HTML(fmt.Sprintf(`<input type="hidden" name="%s" value="%s">`+ 155 return template.HTML(fmt.Sprintf(`<input type="hidden" name="%s" value="%s">`+
156 `<a class="captcha" href="javascript:">`+ 156 `<a class="captcha" href="javascript:">`+
157 `<img onclick="this.src=('%s%s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%s%s.png">`+ 157 `<img onclick="this.src=('%s%s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%s%s.png">`+
158 `</a>`, c.FieldIdName, value, c.urlPrefix, value, c.urlPrefix, value)) 158 `</a>`, c.FieldIdName, value, c.URLPrefix, value, c.URLPrefix, value))
159 } 159 }
160 160
161 // create a new captcha id 161 // create a new captcha id
...@@ -224,14 +224,14 @@ func NewCaptcha(urlPrefix string, store cache.Cache) *Captcha { ...@@ -224,14 +224,14 @@ func NewCaptcha(urlPrefix string, store cache.Cache) *Captcha {
224 cpt.StdHeight = stdHeight 224 cpt.StdHeight = stdHeight
225 225
226 if len(urlPrefix) == 0 { 226 if len(urlPrefix) == 0 {
227 urlPrefix = urlPrefix 227 urlPrefix = defaultURLPrefix
228 } 228 }
229 229
230 if urlPrefix[len(urlPrefix)-1] != '/' { 230 if urlPrefix[len(urlPrefix)-1] != '/' {
231 urlPrefix += "/" 231 urlPrefix += "/"
232 } 232 }
233 233
234 cpt.urlPrefix = urlPrefix 234 cpt.URLPrefix = urlPrefix
235 235
236 return cpt 236 return cpt
237 } 237 }
...@@ -242,7 +242,7 @@ func NewWithFilter(urlPrefix string, store cache.Cache) *Captcha { ...@@ -242,7 +242,7 @@ func NewWithFilter(urlPrefix string, store cache.Cache) *Captcha {
242 cpt := NewCaptcha(urlPrefix, store) 242 cpt := NewCaptcha(urlPrefix, store)
243 243
244 // create filter for serve captcha image 244 // create filter for serve captcha image
245 beego.AddFilter(urlPrefix+":", "BeforeRouter", cpt.Handler) 245 beego.AddFilter(cpt.URLPrefix+":", "BeforeRouter", cpt.Handler)
246 246
247 // add to template func map 247 // add to template func map
248 beego.AddFuncMap("create_captcha", cpt.CreateCaptchaHtml) 248 beego.AddFuncMap("create_captcha", cpt.CreateCaptchaHtml)
......
...@@ -443,7 +443,7 @@ func (b Base64) GetLimitValue() interface{} { ...@@ -443,7 +443,7 @@ func (b Base64) GetLimitValue() interface{} {
443 } 443 }
444 444
445 // just for chinese mobile phone number 445 // just for chinese mobile phone number
446 var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|(47)|[8][01236789]))\\d{8}$") 446 var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|(47)|[8][012356789]))\\d{8}$")
447 447
448 type Mobile struct { 448 type Mobile struct {
449 Match 449 Match
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!